<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title>Loggly by Hoover</title>
  
  <link href="http://loggly.com/blog/" />
  <id>http://loggly.com/blog/</id>
  <updated>2012-01-16T23:22:31-08:00</updated>

  
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/LogglyByHoover" /><feedburner:info uri="logglybyhoover" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
      <title>Getting Your Product Sticky</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/-nEtZgi5BIA/" />
      <id>http://loggly.com/blog/2012/01/getting-sticky/</id>
      <updated>2012-01-16T23:22:31-08:00</updated>
      <published>2012-01-13T14:00:00-08:00</published>
      <category term="Log Management" /><category term="Startup" />
      <summary type="html" />
      <content type="html">&lt;p&gt;A few months ago I made an off-the-cuff remark about Loggly. &lt;em&gt;&amp;quot;We&amp;#39;re like one of those shitty solar powered calculators. &amp;nbsp;When it gets dark, we forget everything you&amp;#39;ve typed into us.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/assets/4f10c31ddabe9d16e700a889/feature_thumbnail/loose_calc.jpeg" style="width: 200px; height: 150px; " /&gt;&lt;/p&gt;
&lt;p&gt;That comment wasn&amp;#39;t far off the mark. &amp;nbsp;Historically, we haven&amp;#39;t provided a whole hell of a lot of features that makes it easy to jump back into where you left off on your last search session. &amp;nbsp;Basically when you logged out of Loggly, or even closed the shell in your browser, we&amp;#39;d forget everything you searched for until that point. &amp;nbsp;It made it extremely difficult to get back to something meaningful the next time you logged in.&lt;/p&gt;
&lt;p&gt;We shouldn&amp;#39;t be here if we aren&amp;#39;t meaningful. &amp;nbsp;We should deliver users a &amp;#39;punch in the gut&amp;#39; feature that makes a lasting impact. &amp;nbsp;One they don&amp;#39;t want to avoid.&lt;/p&gt;
&lt;h3&gt;Saving Time with Sticky Features&lt;/h3&gt;
&lt;p&gt;Scaling search for a massive amount of log file data being sent in from thousands of machines has been an overwhelming non-trival problem to solve for us over the past year, and it&amp;#39;s been our top priority. &amp;nbsp;Unfortunately us solving scale issues aren&amp;#39;t readily obvious to users. &amp;nbsp;Users always expect things on the web to be fast. &amp;nbsp;They could care less how hard a problem it was to solve. &amp;nbsp;They don&amp;#39;t think to themselves, &lt;em&gt;&amp;quot;Wow, that&amp;#39;s fucking fast!&amp;quot;&lt;/em&gt;. &lt;strong&gt;&amp;nbsp;No. &lt;/strong&gt;&amp;nbsp;Instead they sit around and mutter things to themselves like &lt;em&gt;&amp;quot;Why the hell doesn&amp;#39;t feature X do Y? &amp;nbsp;This thing is wasting my time!&amp;quot;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And there it is laid bare:&lt;strong&gt;&amp;nbsp;Don&amp;#39;t waste your user&amp;#39;s time.&lt;/strong&gt; &amp;nbsp;It&amp;#39;s the most valuable resource they have. &amp;nbsp;Get to the point quick, make it easy to get back to what you were doing next time, and do it all with little fuss and muss.&lt;/p&gt;
&lt;p&gt;I say give them sticky features!&lt;/p&gt;
&lt;h3&gt;Saved Search and More&lt;/h3&gt;
&lt;p&gt;And so, without further ado, I&amp;#39;m officially announcing one of many-to-come new sticky features: &lt;a href="http://wiki.loggly.com/savedsearch?s[]=saved&amp;amp;s[]=search"&gt;saved search&lt;/a&gt;. &amp;nbsp;Saved search provides users a way to write a search query and then preserve the search to run again later. &amp;nbsp;Saved searches can generate facet graphs or they can simply run a regular search across a given time range.&lt;/p&gt;
&lt;p&gt;The shell has been reworked to provide context changes to use with the saved search feature. &amp;nbsp;You can now change the date context, or limit the context to certain inputs, and then rerun the search or graph using the red rerun button at the top.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a quick screencast running through some of our new sticky features:&lt;/p&gt;
&lt;p&gt;&lt;iframe allowfullscreen="" frameborder="0" height="293" mozallowfullscreen="" src="http://player.vimeo.com/video/35174872?title=0&amp;amp;byline=0&amp;amp;portrait=0" webkitallowfullscreen="" width="520"&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Coming Up Soon&lt;/h3&gt;
&lt;p&gt;We&amp;#39;re continuing to add features that increase stickiness to the product. &amp;nbsp;Next week we&amp;#39;ll be releasing a revamped history feature for the shell page, where what you&amp;#39;ve typed in before in a session will be preserved in your command history, just like it would in a normal shell prompt. &amp;nbsp;We&amp;#39;re also adding customized graph selection on the main dashboard, which will allow you to start viewing events that matter most to you by default when you first log in.&lt;/p&gt;
&lt;p&gt;All these featuers are leading up to a major revamp of the way we provide value for our user&amp;#39;s events. &amp;nbsp;Expect completely customized dashboards for server monitoring, website performance, user analytics, and more soon! &amp;nbsp;If you have a feature you&amp;#39;d like to see us implement, please do drop us a line. &amp;nbsp;We&amp;#39;re keen on not wasting your time!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/-nEtZgi5BIA" height="1" width="1"/&gt;</content>
      <author>
        <name>Kord Campbell</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2012/01/getting-sticky/</feedburner:origLink></entry>
  
    <entry>
      <title>Loggly's Outage for December 19th</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/2BfVkc4lg0Y/" />
      <id>http://loggly.com/blog/2011/12/logglys-outage-for-december-19th/</id>
      <updated>2011-12-21T16:44:56-08:00</updated>
      <published>2011-12-19T16:20:00-08:00</published>
      <category term="Business" /><category term="Startup" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Sometimes there&amp;#39;s just no other way to say &amp;nbsp;&amp;quot;we&amp;#39;re down&amp;quot; than just admitting you screwed up and are down. &amp;nbsp;We&amp;#39;re coming back up now, and in theory by the time this is read, we&amp;#39;ll be serving the app again normally. &amp;nbsp;There will be a good amount of time until we can rebuild the indexes for historic data of our paid customers. This is our largest outage to date, and I&amp;#39;m not at all proud of it.&lt;/p&gt;
&lt;p class="p2"&gt;&lt;img alt="" src="/assets/4eefd496dabe9d46b800ce22/feature_thumbnail/facepalm.jpeg" /&gt;&lt;/p&gt;
&lt;h3 class="p3"&gt;&lt;b&gt;So What Happened?&lt;/b&gt;&lt;/h3&gt;
&lt;p class="p1"&gt;Sometime yesterday afternoon ALL of our machines on Amazon&amp;#39;s East region, availability zone 1d, were rebooted by AWS staff. &amp;nbsp;Originally we stated we had not received reboot notices from Amazon, but the truth is that (4) of the staff here, myself included received two separate vague notices, one from about 10 days ago, and another from 3 days ago, which stated &amp;#39;some or all&amp;#39; of our instances were scheduled to be rebooted. &amp;nbsp;These notices were found in our spam folders on Gmail, placed there with a very large red notice reading: &amp;quot;Warning: This message may not be from whom it claims to be. Beware of following any links in it or of providing the sender with any personal information.&amp;quot; &amp;nbsp;Meh.&lt;/p&gt;
&lt;p class="p1"&gt;Loggly uses a variety of monitoring mechanisms to ensure our services are healthy. &amp;nbsp;These include, but are not limited to, extensive monitoring with Nagios, external monitors like Zerigo, and using a slew of our own API calls for monitoring for errors in our logs. &amp;nbsp;When the mass reboot occurred we failed to alert because a) our monitoring server was rebooted and failed to complete the boot cycle, b) the external monitors were only set to test for pings and established connections to syslog and http (more about that in a moment), and c) the custom API calls using us were no longer running because we were down.&lt;/p&gt;
&lt;p class="p1"&gt;Combined, these failures effectively &amp;nbsp;prevented us from noticing we were down. &amp;nbsp;This in of itself is was the cause of at least half our down time, and to me, the most unacceptable part of this whole situation.&lt;/p&gt;
&lt;h3 class="p3"&gt;&lt;b&gt;The Human Element&lt;/b&gt;&lt;/h3&gt;
&lt;p class="p1"&gt;The other cause to our failures is what some of you on Twitter are calling &amp;quot;a failure to architect for the cloud&amp;quot;. &amp;nbsp;I would refine that a bit to say &amp;quot;a failure to architect for a bunch of guys randomly rebooting 100% of your boxes&amp;quot;. &amp;nbsp;A reboot of all boxes has never been tested at Loggly before. &amp;nbsp;It&amp;#39;s a test we&amp;#39;ve failed completely as of today. &amp;nbsp;We&amp;#39;ve been told by Amazon they actually had to work hard at rebooting a few of our instances, and one scrappy little box actually survived their reboot wrath.&lt;/p&gt;
&lt;p class="p1"&gt;While some might go on a rant about how &amp;#39;normal&amp;#39; failures don&amp;#39;t affect 100% of your boxes the truth is that any and everything (including an army of reboot monkeys) can be expected to happen to your servers if you wait around long enough. &amp;nbsp;The trick to being good at running a reliable service is to architect around any number of everythings that could happen to your service and build for it.&lt;/p&gt;
&lt;p class="p1"&gt;In this case we didn&amp;#39;t ever build the workaround simply because the system we run - a combination of 0MQ+Solr+Zookeeper+Loggly Special Sauce - makes it extremely challenging to survive a complete failure with more than 1/2 of the cluster missing. &amp;nbsp;With other challenges facing us, we decided to live with the risk. Now we&amp;#39;re dealing with the fallout of our decision.&lt;/p&gt;
&lt;h3 class="p3"&gt;&lt;b&gt;So, How Do We Make This Right?&lt;/b&gt;&lt;/h3&gt;
&lt;p class="p1"&gt;Single instances of Loggly&amp;#39;s search cluster can&amp;#39;t be spread across multiple availability zones or regions due to the amount of data we push around, latencies between the search nodes, and the lack of support in our system for redundant indexes. &amp;nbsp;We&amp;#39;ve been OK with those limitations in the past simple because we normally archive data to S3 when we catch it, and we are capable of rebuilding indexes on the fly if we lose one or more indexers.&lt;/p&gt;
&lt;p class="p1"&gt;The first step in addressing this is to start sharding our customers across multiple Loggly deployments. &amp;nbsp;This will prevent further outages to the entire customer base. &amp;nbsp;The second step is to start doing Loggly deployments on dedicated hardware. &amp;nbsp;Because we keep large amounts of data on our boxes (the indexes) this is pretty much a requirement for fast recovery times when a deployment goes down. &amp;nbsp;While S3 is AWESOME for backups, it sucks big-time for rebuilding a large amount of search index data.&lt;/p&gt;
&lt;p class="p1"&gt;The second step is to ensure more robust external monitoring. &amp;nbsp;With multiple deployments, this issue becomes less of an issue, but clearly we need more reliable checks than what we rely on with Zerigo or other services. &amp;nbsp;Sorry, but simple HTTP checks, pings and established connections to a box do not guarantee it&amp;#39;s&amp;nbsp;up!&lt;/p&gt;
&lt;p class="p1"&gt;Finally, we accept full responsibility for the impact to our customers. &amp;nbsp;We will be in touch with our paid customers sometime over the next week to address compensation for this outage.&lt;/p&gt;
&lt;p class="p1"&gt;We welcome feedback below, and encourage useful criticism of our architectural choices. &amp;nbsp;All I would ask is that you consider Loggly&amp;#39;s infrastructure isn&amp;#39;t the same as yours, and I&amp;#39;ve greatly simplified the reasons for not being more redundant in our deployments. &amp;nbsp;We can, and will, endeavor to do better in the future.&lt;/p&gt;
&lt;p class="p1"&gt;&lt;strong&gt;Kord Campbell, CEO&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/2BfVkc4lg0Y" height="1" width="1"/&gt;</content>
      <author>
        <name>Kord Campbell</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/12/logglys-outage-for-december-19th/</feedburner:origLink></entry>
  
    <entry>
      <title>Enabling CORS in Django Piston</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/1X9At0XVZWs/" />
      <id>http://loggly.com/blog/2011/12/enabling-cors-in-django-piston/</id>
      <updated>2011-12-05T15:28:32-08:00</updated>
      <published>2011-12-05T15:00:00-08:00</published>
      <category term="Code" />
      <summary type="html" />
      <content type="html">&lt;p&gt;&lt;img alt="" src="http://blogs.bournemouth.ac.uk/research/files/2011/08/sharing-guinea-pigs.jpg" style="width: 500px; height: 321px; " /&gt;&lt;/p&gt;
&lt;div&gt;Here at Loggly, one of our goals is to make our API accessible and easy to integrate. By enabling CORS (&lt;strong&gt;Cross Origin Resource Sharing&lt;/strong&gt;) on our API endpoints, we hope more Javascript developers can take advantage of what our product has to offer.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;CORS is an addition to the browser security model that allows XHR requests to be made from one domain to another. CORS allows Javascript applications to access resources on domains other than the original document&amp;#39;s domain, working around the same-origin policy. While Javascript application developers have crafted techniques like JSONP, Flash proxies, XHR receivers, and server-side proxies to circumvent the same-origin policy, CORS makes these hacks unnecessary.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;To take advantage of CORS both the server and the browser need to support the standard. The browser needs to initiate a negotiation with the server and the server must signal to the browser which domains are allowed to make cross-domain requests. Our current API is implemented in Django Piston, an open-source project that enabled us to quickly build a RESTful API on top of Django. Piston does not support CORS out-of-the-box, but it wasn&amp;#39;t hard to write some code to enable it and we&amp;#39;d like to show how it was done.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;A full explanation of CORS is beyond the scope of this post, but the central idea behind CORS is a negotiation between the browser and server of allowed and disallowed actions. This negotiation is done via HTTP headers. The essential headers are the following:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Origin&lt;/strong&gt;: Sent by the browser signifying the originating domain.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Access-Control-Allowed-Origin&lt;/strong&gt;: Sent by the server, listing the origin domains allowed to make requests to the server&amp;#39;s domain. Can be a comma-separated list of domains or &amp;quot;*&amp;quot; to allow requests from all domains.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Access-Control-Allow-Methods&lt;/strong&gt;: Sent by the server, listing the HTTP methods the browser is allowed to use in requests to the server.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Access-Control-Allow-Headers&lt;/strong&gt;: Sent by the server, listing the HTTP methods the server is willing to accept from the browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Essentially, to enable CORS we need to have Django Piston respond to an OPTIONS request with the server-sent headers and send the requisite headers along with responses.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;The &lt;strong&gt;Resource&lt;/strong&gt; class is the heart of a Django Piston-built API. The code &amp;nbsp;that injects the headers into responses lives in a subclass of the base Resource class. We&amp;#39;ve called this class &lt;strong&gt;CORSResource&lt;/strong&gt;:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;script src="https://gist.github.com/1429054.js?file=cors_resource.py"&gt;&lt;/script&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;The &lt;strong&gt;CORSResource&lt;/strong&gt; performs two simple tasks. First, it intercepts any OPTIONS method requests to handle the pre-flight negotiation between the browser and the server. Since OPTIONS requests do not have a response body, an empty &lt;strong&gt;HTTPResponse()&lt;/strong&gt; is returned along with the requisite headers. Second, &lt;strong&gt;CORSResource&lt;/strong&gt; intercepts responses from the Django Piston handlers (where responses are generated) and decorates them with the CORS headers.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;To use &lt;strong&gt;CORSResource&lt;/strong&gt;, we simply instantiated our endpoints with the &lt;strong&gt;CORSResource&lt;/strong&gt; sub-class instead of the base &lt;strong&gt;Resource&lt;/strong&gt; class. The change to our API&amp;#39;s &lt;strong&gt;urls.py&lt;/strong&gt; file look like this:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;script src="https://gist.github.com/1429077.js?file=urls.py"&gt;&lt;/script&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;We hope this post helps other Django Piston API implementors enable CORS in their own APIs. We&amp;#39;re planning to release this implementation in the coming weeks and we&amp;#39;re looking forward to see what Javascript developers are going to do with direct access to our API.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Happy hacking!&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;(image from&amp;nbsp;http://blogs.bournemouth.ac.uk/research/2011/09/01/sharing-your-research-data/)&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/1X9At0XVZWs" height="1" width="1"/&gt;</content>
      <author>
        <name>Ivan Tam</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/12/enabling-cors-in-django-piston/</feedburner:origLink></entry>
  
    <entry>
      <title>Java Code Coverage With Cobertura and Jenkins</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/4LKhCO-SX6w/" />
      <id>http://loggly.com/blog/2011/11/java-code-coverage-with-cobertura-and-jenkins/</id>
      <updated>2011-11-29T14:44:13-08:00</updated>
      <published>2011-11-29T14:00:00-08:00</published>
      <category term="Code" /><category term="Startup" />
      <summary type="html" />
      <content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Writing software is tough, tools and processes that reduce the difficulty are always welcome. &amp;nbsp;Code Coverage is an interesting developer tool because it tells you how much you don&amp;#39;t know. &amp;nbsp;Not having a test for a particular piece of code doesn&amp;#39;t mean that it doesn&amp;#39;t work, it just means you aren&amp;#39;t as sure as you could be that it works. &amp;nbsp; &amp;nbsp;In this article, I will be covering getting the open source, Java Code Coverage tool, Cobertura, working with Ant, Jenkins and Github. &amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;Cobertura&lt;/h2&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Since getting continuous integration working in a particular language can be complicated, it is a best practice to break the problem down into discreet chunks. &amp;nbsp;Fortunately, Cobertura makes this easy, because the source code comes with an example ant project. &amp;nbsp;You can download a binary distribution here: &amp;nbsp;&lt;a href="http://cobertura.sourceforge.net/download.html"&gt;http://cobertura.sourceforge.net/download.html&lt;/a&gt;. &amp;nbsp;Inside of the download will be a relative path &amp;nbsp;&lt;em&gt;&lt;strong&gt;..examples/basic&lt;/strong&gt;&lt;/em&gt;. &amp;nbsp;If you cd into that directory, you can generate a code coverage report on a sample Java project by typing: &amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;&lt;strong&gt;ant&amp;nbsp;&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;If you don&amp;#39;t have junit installed, you will get output like the below, on my OS X Lion laptop: &lt;script src="https://gist.github.com/1398307.js?file=CoberturaNoAnt.txt"&gt;&lt;/script&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;If you run ant clean it will remove the reports directory, which contains, old reports. &amp;nbsp;One tricky bit with running the example, is that the build.xml file is set to look for cobertura, and the cobertura lib directory, in a relative path two directories above. &lt;script src="https://gist.github.com/1405656.js?file=build.xml"&gt;&lt;/script&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;This can be tricky if you check in only the examples directory into your git repository and don&amp;#39;t have cobertura installed properly. &amp;nbsp;What will happen then, is that the examples won&amp;#39;t build properly and it will be tricky to figure out. &amp;nbsp;If you find yourself in this situation, one easy hack is to simply place the cobertura jar files, including the dependencies in the lib, inside of your ant home. &amp;nbsp;On Ubuntu linux this is &lt;em&gt;&lt;strong&gt;/usr/share/ant/lib&lt;/strong&gt;&lt;/em&gt;.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;Jenkins&lt;/h2&gt;
&lt;div&gt;With the basic Cobertura configuration out of the way, the next thing to do is to create a throwaway git repository, on github or your own server. &amp;nbsp;Next you will want to check in the whole Cobertura binary distribution that you download from their site: &amp;nbsp; &lt;a href="http://cobertura.sourceforge.net/"&gt;http://cobertura.sourceforge.net/&lt;/a&gt;, or only check in the examples root, and install Cobertura properly on your build server. &amp;nbsp;Inside of jenkins you will need to do the following things:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;1. &amp;nbsp;Point Jenkins at your git repository.&lt;/div&gt;
&lt;div&gt;2. &amp;nbsp;Install the Cobertura jenkins plugin: &amp;nbsp;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin"&gt;https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;3. &amp;nbsp;Configure the reports directory correctly. &amp;nbsp;Because I only checked in the examples directory, my reports configuration looked like this:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;&lt;strong&gt;**/reports/cobertura-xml/coverage.xml&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;4. build it.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Here is a screenshot of what it looks like when Jenkins builds the example project with code coverage:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;img alt="" src="/assets/4ed54eabdabe9d4e5b0191f4/feature_zoom/jenkinscodecoverage.png" /&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;div&gt;If you were able to follow along at home, and have Jenkins automatically building the example project with code coverage, then the next step is to convert this knowledge to your own code base. &amp;nbsp;One problem I had when getting Cobertura working with my code base was configuring the junit stanza properly to fork. &amp;nbsp;Finally, an even simpler way to get code coverage cooking for your Java code base is to install the Eclipse plugin eCobertura. &amp;nbsp;If you are really stuck getting things to work, this is a nice easy win. &amp;nbsp;I hope you enjoyed the article, and if you have any Cobertura tricks, I would love to hear about them.&lt;/div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Ant: &amp;nbsp;&lt;a href="http://ant.apache.org/"&gt;http://ant.apache.org/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;Cobertura Plugin Jenkins: &amp;nbsp;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin"&gt;https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;Jenkins: &amp;nbsp;&lt;a href="http://jenkins-ci.org/"&gt;http://jenkins-ci.org/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;Github: &amp;nbsp;&lt;a href="https://github.com/"&gt;https://github.com/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;Cobertura: &amp;nbsp;&lt;a href="http://cobertura.sourceforge.net/"&gt;http://cobertura.sourceforge.net/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;Measuring Code Coverage With Cobertura: &amp;nbsp;&lt;a href="http://www.ibm.com/developerworks/java/library/j-cobertura/"&gt;http://www.ibm.com/developerworks/java/library/j-cobertura/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;eCobertura: &amp;nbsp;&lt;a href="http://ecobertura.johoop.de/"&gt;http://ecobertura.johoop.de/&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/4LKhCO-SX6w" height="1" width="1"/&gt;</content>
      <author>
        <name>Noah Gift</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/11/java-code-coverage-with-cobertura-and-jenkins/</feedburner:origLink></entry>
  
    <entry>
      <title>Automated Integration</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/lcGb5fqCivM/" />
      <id>http://loggly.com/blog/2011/11/automated-integration/</id>
      <updated>2011-11-18T16:55:15-08:00</updated>
      <published>2011-11-16T09:45:00-08:00</published>
      <category term="Business" /><category term="Code" /><category term="Startup" />
      <summary type="html" />
      <content type="html">&lt;p&gt;One of the fundamental challenges of distributed coding is deciding what/when to integrate. Sure, that patch your colleague just sent you looks good, but is it actually ready to go into master? At Loggly, we&amp;#39;ve been feeling our way towards a disciplined integration process. A year ago, our frontend developers were all making commits directly to trunk in a single SVN repo. Once every few weeks, we&amp;#39;d run `svn up` on our servers, and hope for the best. Today our code goes through peer review, unit testing, and static analysis before it even touches our master branch.&lt;/p&gt;
&lt;p&gt;Like most projects these days, the process starts on &lt;a href="https://github.com/"&gt;github&lt;/a&gt;. Fork. Push a feature branch to your repo. Open a pull request. Go through a couple rounds of discussion and revision. Merge. Every change to our code goes through this process. At first we thought it would slow us down, that we&amp;#39;d want pull requests for the nontrivial code and to just push to master for the easy stuff. After just a few days, we found the pull requests were slowing us down not at all, and that we all enjoyed the greater transparency into our colleagues&amp;#39; work.&lt;/p&gt;
&lt;p&gt;Once we merge, the automation kicks in -- our default integration branch is &amp;#39;proposed&amp;#39;, so clicking merge doesn&amp;#39;t actually get the code into the master branch. Jenkins polls our &amp;#39;proposed&amp;#39; branch once a minute, then runs a simple preflight script on the code.&lt;/p&gt;
&lt;p&gt;Rather than keep that preflight in a jenkins configuration page, we have it checked into the codebase so that any developer can run it too; this way there&amp;#39;s no excuse for breaking the build -- you should have seen it break locally =P&lt;/p&gt;&lt;script src="https://gist.github.com/1368420.js?file=gistfile1.txt"&gt;&lt;/script&gt;
&lt;p&gt;Here&amp;#39;s our preflight script. Let&amp;#39;s go through it line by line.&lt;/p&gt;
&lt;p&gt;DIR=&amp;quot;$( cd &amp;quot;$( dirname &amp;quot;$0&amp;quot; )&amp;quot; &amp;amp;&amp;amp; pwd )&amp;quot;&lt;/p&gt;
&lt;p&gt;APP=$DIR/..&lt;/p&gt;
&lt;p&gt;First we figure out where we&amp;#39;re running, so that we can find the other scripts distributed with the app.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$DIR/purge_pyc&lt;/p&gt;
&lt;p&gt;Next we purge pyc files. This is done because if a user recently switched from a branch which contained files which don&amp;#39;t exist in our branch, the pyc files may still be around, and may be found by the interpreter.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$DIR/syncenv&lt;/p&gt;
&lt;p&gt;Next we run a script to sync our&amp;nbsp;&lt;a href="http://www.virtualenv.org/en/latest/index.html"&gt;python virtual environment&lt;/a&gt;, and ensure all requirements are present.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$DIR/runtests&lt;/p&gt;
&lt;p&gt;Here, of course, we run our unit tests. Each run prints a coverage report, so that as we recover from our testing debt, we can measure our progress.&lt;/p&gt;
&lt;p&gt;&amp;amp;&amp;amp; $DIR/lint...&lt;/p&gt;
&lt;p&gt;Next, and this is important, we run &lt;a href="http://www.logilab.org/card/pylint_manual"&gt;pylint &lt;/a&gt;over the parts of our app that we expect to pass with no warnings. As we clean up our app, we continue to add modules to this list. Pylint does a few useful things for us. It looks for trivial name errors of the kind that could quickly cause code to stacktrace -- using a module without importing it, etc. It also enforces certain kinds of coding discipline. Our functions and modules can&amp;#39;t exceed a certain length. The &lt;a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity"&gt;cyclomatic complexity&lt;/a&gt;&amp;nbsp;of our functions is limited.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If all of this passes successfully, Jenkins automatically pushes the checked-out commit to master, which is where we base our development. Thus, we&amp;#39;re always basing our development on known-vetted code.&lt;/p&gt;
&lt;p&gt;If any of it fails, Jenkins still has a couple more tricks to pull. Here&amp;#39;s our on-failure script:&lt;/p&gt;&lt;script src="https://gist.github.com/1368451.js?file=Loggly%20Failure%20Script"&gt;&lt;/script&gt;
&lt;p&gt;This comes in two parts. The first runs a standard-issue git-bisect between origin/proposed and origin/master. Since origin/master has already been vetted by jenkins (that&amp;#39;s how it became master), we know there&amp;#39;ll be a regression somewhere between the commits. This goes into the session output, and is e-mailed to the relevant committers. Next, we roll the proposed branch back to the already-vetted master branch. Whatever pull request broke the build will have to be re-made from scratch.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/lcGb5fqCivM" height="1" width="1"/&gt;</content>
      <author>
        <name>Mike Blume</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/11/automated-integration/</feedburner:origLink></entry>
  
    <entry>
      <title>I'm Presenting at MongoSV!</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/Hyrr_QsliGY/" />
      <id>http://loggly.com/blog/2011/11/im-presenting-at-mongosv-1/</id>
      <updated>2011-11-10T14:36:50-08:00</updated>
      <published>2011-11-10T14:00:00-08:00</published>
      
      <summary type="html" />
      <content type="html">&lt;p&gt;In May I had the opportunity to &lt;a href="http://loggly.com/blog/2011/07/visualizing-your-data-with-mongo/"&gt;speak at the MongoDB conference in SF&lt;/a&gt;. &amp;nbsp;I ran through how Loggly uses MongoDB to store statistical data on the data we receive and how customers can use our API calls to render visualizations of their logging data. &amp;nbsp;I also hacked a visualization&amp;nbsp;example of events per device using the &lt;a href="http://mbostock.github.com/protovis/"&gt;smashing protovis.js&lt;/a&gt; library, which you can &lt;a href="http://house.geekceo.com:8082/"&gt;view here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/assets/4ebc4b57dabe9d2b55005839/feature_thumbnail/mongo_viz.png" /&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m thorougly excited to announce I will be speaking again at the &lt;a href="http://www.10gen.com/events/mongosv-2011"&gt;MongoSV conference in Santa Clara in December&lt;/a&gt;.&amp;nbsp; I&amp;#39;m stepping up the presentation this time, and will be showing more details about how we&amp;#39;ve integrated MongoDB into our infrastructure, and how we use MongoDB to generate our &lt;a href="http://en.wikipedia.org/wiki/OLAP_cube#OLAP_operations"&gt;roll up reports&lt;/a&gt;. &amp;nbsp;I&amp;#39;ll run through how we use these roll up stats to drive our own metrics dashboard and how exposing the data to end users via our REST APIs provides a whole host of cool options for visualizing data.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re in town or live within a reasonable distance, defined as the entire Contentintal United States, be sure &lt;a href="http://www.10gen.com/events/mongosv-2011"&gt;to come check out the conference&lt;/a&gt;! The &lt;a href="http://www.10gen.com/"&gt;Mongo/10gen crew&lt;/a&gt; always puts on great events filled with lots of technical talks and a rocking after-party. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;See you there! &amp;nbsp;Again.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/Hyrr_QsliGY" height="1" width="1"/&gt;</content>
      <author>
        <name>Kord Campbell</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/11/im-presenting-at-mongosv-1/</feedburner:origLink></entry>
  
    <entry>
      <title>Ajax This!</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/tVvMfWsexoU/" />
      <id>http://loggly.com/blog/2011/11/ajax-this/</id>
      <updated>2011-11-08T14:46:46-08:00</updated>
      <published>2011-11-07T09:00:00-08:00</published>
      <category term="Code" /><category term="Log Management" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Today&amp;rsquo;s blog post is more of a tool than a toy. &amp;nbsp;Lately I&amp;rsquo;ve been working on a bookmarklet that utilizes &lt;a href="http://www.pusher.com" target="_blank"&gt;Pusher&lt;/a&gt; (if you want to learn a little about Pusher, &lt;a href="http://loggly.harmonyapp.com/blog/2011/10/get-real-with-pusher/" target="_blank"&gt;check out my previous blogpost&lt;/a&gt;). &amp;nbsp;The bookmarklet I&amp;rsquo;m working on is really silly, but these technologies have the potential to be used for some really cool apps.&lt;/p&gt;
&lt;p&gt;I needed to figure out a way for javascript to manipulate objects on web pages remotely through &lt;a href="http://en.wikipedia.org/wiki/Ajax_(programming)"&gt;ajax&lt;/a&gt; calls. &amp;nbsp;&amp;nbsp;You can already do this with click events and Pusher by sending the class or ID of any element you click on, but what if there is no class or ID? &amp;nbsp;I also want this to work on any webpage. &amp;nbsp;As a result, I needed to figure out how to build a selector that was as unique as possible. &amp;nbsp;One way to do this is &amp;nbsp;to select using all attributes the object has to offer.&lt;/p&gt;
&lt;p&gt;Enter, the custom attribute selector syntax: &lt;script src="https://gist.github.com/1339876.js"&gt; &lt;/script&gt;&lt;/p&gt;
&lt;p&gt;This selector will only select objects that have a class value of &amp;ldquo;whatever&amp;rdquo; AND a myattribute value of &amp;ldquo;customattribute&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Some stack overflow and basic google searching told me I can tease attributes out using a regex(gross). &amp;nbsp;I knew there had to be a better way so I started fiddling with javascript objects I captured on click and tried to figure out how to uniqify my selector string. &amp;nbsp;What I discovered is that every object I clicked on contained a ton of info. &amp;nbsp;The parts that I use to build my unique-ish selector are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;localName&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The name of the html tag. &amp;nbsp;in the gist above, this value is customhtml.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;attribute&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;All attribute(s) associated with the object (if any). In the gist above, these attributes are class=&amp;rdquo;whatever&amp;rdquo; and myattribute=&amp;rdquo;customattribute&amp;rdquo; &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;parentNode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the object that contains the one clicked on. &amp;nbsp;Technically my gist has no parent, but I use the parent node to map out a path from the object I clicked on all the way up to the body of the page. &amp;nbsp;If the object you click on doesn&amp;rsquo;t have any attributes ( a &amp;lt;p&amp;gt; object for example) you can still select it based on the specific path to that object.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;textContent&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is any text that&amp;rsquo;s in the object. &amp;nbsp;For example &amp;lt;p&amp;gt;writing stuff&amp;lt;/p&amp;gt; will have a textContent value of &amp;ldquo;writing stuff&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Apart these elements aren&amp;rsquo;t bad at selecting the object you want, but together they get pretty close to behaving like a this object. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here is how I stitch these elements together to create my this-ish selector:&lt;/p&gt;
&lt;script src="https://gist.github.com/1339965.js"&gt; &lt;/script&gt;
&lt;p&gt;There are a few tricks here:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;I found that if the object you click on has no attributes the path doesn&amp;rsquo;t help too much, so if the object I&amp;rsquo;m building a selector for doesn&amp;rsquo;t have any attributes I just give it a class with an empty value, and it works really well. &amp;nbsp;&lt;/li&gt;
	&lt;li&gt;In an attempt to keep my selector as unique as possible I&amp;rsquo;m also using :contains() to select on specific strings as well as the path. &amp;nbsp;This helps ensure that you&amp;rsquo;re manipulating the exact object you want.&lt;/li&gt;
	&lt;li&gt;If you&amp;rsquo;re clicking on an image tag, I found that contains won&amp;rsquo;t allow you to select that image, but if we take it out it works, so I added a filter to keep image tag selectors from using :contains(). (although it currently only works in the developer tools javascript console, I haven&amp;rsquo;t yet figured out why it&amp;rsquo;s not working for my bookmarklet).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Generally, the resulting selector ends up looking something like this:&lt;/p&gt; &lt;script src="https://gist.github.com/1340021.js"&gt;
&lt;p&gt;The very last part of making all of this work happens on the receiving end. &amp;nbsp;If you are sending this selector string (or multiple selector strings) as a JSON encoded object, the string you get back has all the quotes escaped. &amp;nbsp;In this case to turn your string into a valid selector all you have to do is the following:&lt;/p&gt;
&lt;script src="https://gist.github.com/1340068.js"&gt; &lt;/script&gt;
&lt;p&gt;While this method doesn&amp;rsquo;t currently work on every single element of every single webpage, it has worked on most of the pages I have tried out, including the google search page.&lt;/p&gt;
&lt;p&gt;Anyone who has every tried to explain, on the phone (so 1991), to a grandparent or non-tech savvy friend/family member how to do certain things on the web should be able to see the power of this. &amp;nbsp;With these selectors it&amp;rsquo;s now possible to build a bookmarklet that allows two or more people to see what elements are being clicking on. &amp;nbsp;Now describing webpage elements to your grandfather isn&amp;rsquo;t needed. &amp;nbsp;Hook him up with your Pusher powered bookmarklet and all he has to do is go to a URL, click a bookmark button, and let&amp;rsquo;s say... click on the text you just highlighted in yellow. &amp;nbsp;On the flip side, you&amp;rsquo;ll know (almost)exactly what elements on the page he&amp;rsquo;s clicking on because his clicks will make highlights on the page as well. &amp;nbsp;Super neat!&lt;/p&gt;
&lt;p&gt;Obviously this method isn&amp;rsquo;t perfected, but if you&amp;rsquo;re interested helping me make it more precise, &lt;em&gt;please&lt;/em&gt; fork my project on github.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/brainTrain/ajaxThis"&gt;https://github.com/brainTrain/ajaxThis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/tVvMfWsexoU" height="1" width="1"/&gt;</content>
      <author>
        <name>Brian Schroeder</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/11/ajax-this/</feedburner:origLink></entry>
  
    <entry>
      <title>PagerDuty, Loggly, and Alert Birds</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/p66U1A_MuRU/" />
      <id>http://loggly.com/blog/2011/10/pagerduty-loggly-and-alert-birds/</id>
      <updated>2011-10-28T16:48:52-07:00</updated>
      <published>2011-10-28T14:45:00-07:00</published>
      <category term="Business" /><category term="Code" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Well, I&amp;#39;m back, and this time I&amp;#39;m here to talk about an awesome product that we use all the time, &lt;a href="http://www.pagerduty.com/"&gt;PagerDuty&lt;/a&gt;. &amp;nbsp;We use it internally for our own alerting (as do a number of Fortune 500 companies along with a million other startups), but we&amp;#39;ve also integrated it into &lt;a href="https://alertbirds.appspot.com/"&gt;Alert Birds&lt;/a&gt;, which is our alerting tool. &amp;nbsp;With Alert Birds, you can configure saved searches that run against Loggly, and you&amp;#39;ll run those searches over a period of time that you&amp;#39;ve selected, and Alert Birds will escalate alerts in PagerDuty. &amp;nbsp;Before you can do any of those things, however, you need to set up the PagerDuty endpoint:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://wiki.loggly.com/_media/pd_ep.png" style="width: 331px; height: 502px; " /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After you&amp;#39;ve done that, the next thing you&amp;#39;ll need to do is to configure a saved search, and then configure the alert that you want to run. &amp;nbsp;The search itself is pretty straightforward, it has a name, a search string e.g.&lt;/p&gt;
&lt;p&gt;&lt;script src="http://gist.github.com/1323693.js"&gt; &lt;/script&gt;&lt;/p&gt;
&lt;p&gt;(this is why it&amp;#39;s cool to send us JSON!), and a list of inputs and devices that you choose - you may want to run a particular search on only your web servers, for instance.&amp;nbsp; The interesting bit is the alert itself, which runs a search that you choose, but has a number of options as to what conditions consitute an alert, and what the message should be:&lt;/p&gt;
&lt;p&gt;&lt;span id="cke_bm_388E" style="display: none; "&gt;&amp;nbsp;&lt;/span&gt;&lt;span id="cke_bm_387E" style="display: none; "&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://wiki.loggly.com/_media/ab_ca.png" style="width: 573px; height: 543px; " /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This is where PagerDuty comes in. &amp;nbsp;Although you can send a GET or POST request to an endpoint of your choosing with the alert data, triggering an alert in PagerDuty is far more useful, as they can SMS/email/phone you, and they also handle escalations and reporting. &amp;nbsp;So, in the example above, if my web servers are spewing 500 exceptions, I want my ops folks to get notified, provided there are more than 10 - I don&amp;#39;t want to wake anyone up over a little blip! &amp;nbsp;I&amp;#39;m a nice IT manager like that. &amp;nbsp;Anyhow, once an alert is in a critical state, it will run your search every minute until you&amp;#39;re below the threshold, and once that happens, Alert Birds will automatically resolve your alert in PagerDuty.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s pretty much all there is to it! &amp;nbsp;You can find the docs on Alert Birds &lt;a href="http://wiki.loggly.com/alertbirds"&gt;here&lt;/a&gt;, please do drop me a line at support@loggly.com if you need a hand, and until next time, happy alerting!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/p66U1A_MuRU" height="1" width="1"/&gt;</content>
      <author>
        <name>David Lanstein</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/10/pagerduty-loggly-and-alert-birds/</feedburner:origLink></entry>
  
    <entry>
      <title>Alert Birds, OAuth, and Loggly</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/Hm9VmMDqj3g/" />
      <id>http://loggly.com/blog/2011/10/alert-birds-oauth-and-loggly/</id>
      <updated>2011-10-10T17:15:15-07:00</updated>
      <published>2011-10-10T17:14:00-07:00</published>
      <category term="Code" />
      <summary type="html" />
      <content type="html">&lt;p&gt;In today&amp;#39;s edition of the Loggly Blog, we&amp;#39;re going to talk about integrating with Loggly using OAuth. &amp;nbsp;You can authenticate against Loggly in a couple different ways, but we&amp;#39;re going to focus on OAuth today, because that&amp;#39;s how Alert Birds is able to run saved searches on a user&amp;#39;s behalf. &amp;nbsp;OAuth can be a little tricky to set up at first, which is a big reason why we&amp;#39;re open-sourced Alert Birds, and the code can be found at&amp;nbsp;&lt;a href="https://github.com/loggly/alertbirds-community-edition"&gt;http://github.com/loggly/alertbirds-community-edition&lt;/a&gt;. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;To build an app, the very first thing you&amp;#39;ll need to do is to register an app in your Loggly instance, at /account/applications/. &amp;nbsp;Apps are called &amp;#39;Consumers&amp;#39; in OAuth parlance, and after your application gets approved, you can get started working with our API using OAuth.&lt;/p&gt;
&lt;p&gt;In basic terms, the OAuth flow looks something like this:&lt;/p&gt;
&lt;p&gt;1. Get a request token, which is good for a single request&lt;/p&gt;
&lt;p&gt;2. Hit the authorization URL, and pass the request token&lt;/p&gt;
&lt;p&gt;3. Log into Loggly when redirected&lt;/p&gt;
&lt;p&gt;4. Authorize the application with your consumer key to access Loggly on your behalf&lt;/p&gt;
&lt;p&gt;5. Get redirected back to your app, and with the OAuth verifier and the request token, get an access token, which is what you&amp;#39;ll need to make future requests&lt;/p&gt;
&lt;p&gt;This sounds pretty simple, but everything has to be just right for the flow to work. &amp;nbsp;Query string parameters have to be encoded in the right order, you need to send the correct HTTP method that Loggly is expecting, and you can&amp;#39;t lose the OAuth verifier or the request token, because if the access token request fails, you&amp;#39;ll have to ask the user to re-authenticate your app - no good! &amp;nbsp;&lt;/p&gt;
&lt;p&gt;The OAuth wrapper you&amp;#39;ll probably want to use is here: &amp;nbsp;&lt;a href="https://github.com/loggly/alertbirds-community-edition/blob/master/lib/oauth.py"&gt;https://github.com/loggly/alertbirds-community-edition/blob/master/lib/oauth.py&lt;/a&gt;, and a working client code implementation is here: &lt;a href="http://github.com/loggly/alertbirds-community-edition/blob/master/controllers/main.py"&gt;http://github.com/loggly/alertbirds-community-edition/blob/master/controllers/main.py&lt;/a&gt;. &amp;nbsp;The wrapper class simply wraps the &lt;a href="https://github.com/dgouldin/python-oauth2"&gt;OAuth 2 Python library&lt;/a&gt;, and makes it a little easier to interact with Loggly, and the client code is where you&amp;#39;ll find the interesting stuff in terms of hanging onto the request token, handling the return from Loggly, etc. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;A simplified walkthough of what&amp;#39;s happening in main.py is this:&lt;/p&gt;&lt;script src="https://gist.github.com/1276890.js"&gt; &lt;/script&gt;
&lt;p&gt;That&amp;#39;s pretty much all there is to it. &amp;nbsp;Using the lib/oauth.py wrapper from Alert Birds should make it considerably easier to get going. &amp;nbsp;Happy coding!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/Hm9VmMDqj3g" height="1" width="1"/&gt;</content>
      <author>
        <name>David Lanstein</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/10/alert-birds-oauth-and-loggly/</feedburner:origLink></entry>
  
    <entry>
      <title>Get Real with Pusher! Getting Those Alert Birds Squawking...</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/D_buZ39MXUU/" />
      <id>http://loggly.com/blog/2011/10/get-real-with-pusher/</id>
      <updated>2011-10-04T21:43:50-07:00</updated>
      <published>2011-10-04T09:42:00-07:00</published>
      <category term="Code" /><category term="Startup" />
      <summary type="html" />
      <content type="html">&lt;p&gt;&lt;img alt="" src="http://loggly.com/assets/4e85f424dabe9d5963015388/screen_shot_20110930_at_9.45.18_am.png" /&gt;&lt;/p&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&lt;strong&gt;&lt;a href="http://pusher.com/" target="_blank"&gt;Pusher&lt;/a&gt;&amp;nbsp;rocks!&lt;/strong&gt;&amp;nbsp;&amp;nbsp;It gets real with the web in a major way. &amp;nbsp;Websockets! &amp;nbsp;I&amp;#39;m the new kid on the Loggly block&amp;nbsp;and I&amp;#39;ve been working on Loggly&amp;#39;s first&amp;nbsp;&lt;a href="http://loggly.com/features/systems-monitoring-allerting/"&gt;alerting&lt;/a&gt;&amp;nbsp;app,&amp;nbsp;&lt;a href="http://www.alertbirds.com" target="_blank"&gt;Alert Birds&lt;/a&gt;. &amp;nbsp;Alert Birds uses Pusher because it&amp;#39;s fast&amp;nbsp;(real time is kinda hard to beat) and it&amp;#39;s easy to use.&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;I&amp;#39;m giving you guys some code to play around with. &amp;nbsp;Using Pusher and&amp;nbsp;&lt;a href="http://www.schillmania.com/projects/soundmanager2/" target="_blank"&gt;Sound Manager&lt;/a&gt;, we&amp;#39;re going to set up a site that makes Loggly&amp;#39;s Alert Birds&amp;nbsp;hop and sing on a page whenever anyone clicks on them. That means you see when your buddies click birds, and&amp;nbsp;vise verse. &amp;nbsp;Just think of it as a bird chatroom. &amp;nbsp;Trust me, it&amp;#39;s awesome.&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&lt;strong&gt;If you want to follow along with the code, clone the github repo I created here:&lt;/strong&gt;&lt;/div&gt;
	&lt;div&gt;&lt;a href="http://github.com/brainTrain/PusherBirds" target="_blank"&gt;http://github.com/brainTrain/PusherBirds&lt;/a&gt;&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;All you need to do in order to get pusher working is sign up for an account, grab some credentials and get coding.&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&lt;strong&gt;Pusher has two main components:&lt;/strong&gt;&lt;/div&gt;
	&lt;ul&gt;
		&lt;li&gt;&amp;nbsp; &amp;nbsp; Listening for events.&lt;/li&gt;
		&lt;li&gt;&amp;nbsp; &amp;nbsp; Triggering events.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&lt;strong&gt;Let&amp;#39;s start with listening:&lt;/strong&gt;&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;To listen for a pusher event you only need the app key, channel name and event name. &amp;nbsp;With these compoenets listening to a Pusher channel is pretty straight forward and looks something like this:&lt;/div&gt;
	&lt;script src="https://gist.github.com/1262329.js?file=pb_1"&gt;&lt;/script&gt;
	&lt;div&gt;
		&lt;pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; "&gt;
&lt;/pre&gt;
		&lt;div class="line" id="LC1" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; line-height: 1.4em; "&gt;&amp;nbsp; &amp;nbsp;&lt;/div&gt;
	&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&lt;strong&gt;Triggering&amp;nbsp;&lt;/strong&gt;is just as straight forward and requires the same elements as listening, plus the app secret and a backend to handle and send data to Pusher.&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;First you&amp;#39;ll need some data to send, let&amp;#39;s go nuts with ajax!&lt;/div&gt;
	&lt;script src="https://gist.github.com/1262362.js?file=pb_2"&gt;&lt;/script&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;This brings us to the backend&amp;nbsp;component of triggering events, so let&amp;#39;s look at the trigger.php file.&lt;/div&gt;
	&lt;script src="https://gist.github.com/1262375.js?file=gistfile1.aw"&gt;&lt;/script&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;The first thing you need to do is head over to pusher&amp;#39;s Publisher Libraries and choose the backend language&amp;nbsp;you heart the most.&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;&lt;strong&gt;You can find Pusher&amp;#39;s list of Publisher Libraries here&lt;/strong&gt;:&amp;nbsp;&lt;a href="http://pusher.com/docs/rest_libraries" target="_blank"&gt;http://pusher.com/docs/rest_libraries&lt;/a&gt;&lt;/div&gt;
	&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;div&gt;Once you do that simply follow the Library authors instructions and go nuts! &amp;nbsp;In my case I chose the generic&amp;nbsp;php library to demonstrate this simple example. It&amp;#39;s all fairly straight forward but I did run into a namespace&amp;nbsp;issue with my host. &amp;nbsp;To fix it I simply commented out the namespace in Pusher.php.&lt;/div&gt;
	&lt;div&gt;
		&lt;div&gt;&amp;nbsp; &amp;nbsp;&lt;/div&gt;
		&lt;div&gt;In trigger.php I add Pusher.php using php&amp;#39;s require function, put my keys, secrets etc into variables and&amp;nbsp;use Pusher.php&amp;#39;s Pusher() class to validate. &amp;nbsp;The last line triggers the event and grabs data from the button&amp;nbsp;variable I sent to the URL using my ajax call.&lt;/div&gt;
		&lt;div&gt;&amp;nbsp;&lt;/div&gt;
		&lt;div&gt;I&amp;nbsp;should point out that Pusher is somewhat flash dependent as well. For browsers that don&amp;#39;t support websockets, they have a solution. &amp;nbsp;Flash. &amp;nbsp;Which means it&amp;#39;s probably a good idea to handle flashblockers for any pusher app you create.&amp;nbsp;&lt;/div&gt;
		&lt;div&gt;&amp;nbsp;&lt;/div&gt;
		&lt;div&gt;&lt;strong&gt;Here&amp;#39;s Pusher&amp;#39;s list of supported browsers:&amp;nbsp;&lt;/strong&gt;&amp;nbsp;&lt;a href="http://pusher.com/docs/browser_compatibility" target="_blank"&gt;http://pusher.com/docs/browser_compatibility&lt;/a&gt;&lt;/div&gt;
		&lt;div&gt;&amp;nbsp;&lt;/div&gt;
		&lt;div&gt;&lt;strong&gt;That&amp;#39;s it!&lt;/strong&gt;&lt;/div&gt;
		&lt;div&gt;&amp;nbsp;&lt;/div&gt;
		&lt;div&gt;At this point you should have everything you need to communicate with our Alert Birds. &amp;nbsp;Go nuts!&lt;/div&gt;
		&lt;div&gt;&amp;nbsp;&lt;/div&gt;
	&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/D_buZ39MXUU" height="1" width="1"/&gt;</content>
      <author>
        <name>Brian Schroeder</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/10/get-real-with-pusher/</feedburner:origLink></entry>
  
    <entry>
      <title>Creating Heroku Addons: Getting Started</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/iakvQrkI_7g/" />
      <id>http://loggly.com/blog/2011/09/creating-heroku-addons-getting-started/</id>
      <updated>2011-09-27T16:46:08-07:00</updated>
      <published>2011-09-27T09:49:00-07:00</published>
      <category term="Code" />
      <summary type="html" />
      <content type="html">&lt;p&gt;&lt;img alt="Heroku" class="prestyled" src="http://www.wemakeprojects.com/files/2011/06/heroku-logo_big-300x93.png" style="width: 300px; height: 93px; " /&gt;&lt;/p&gt;
&lt;div&gt;Recently the Loggly add-on went live for all Heroku users. Creating this add-on involved&amp;nbsp;implementing a few API endpoints in our service for Heroku to call. This is a quick overview&amp;nbsp;of what the development process looks like.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Heroku&amp;#39;s add-on API specs have a number of calls that fall into the following three categories:&lt;/div&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Provisioning/deprovisioning&lt;/strong&gt;: These are calls that ask the add-on service to create&amp;nbsp;or remove resources on behalf of the Heroku user. One thing to remember here is that&amp;nbsp;Heroku will ask the add-on service to create resources per Heroku *app*, not per Heroku&amp;nbsp;user account.&lt;br /&gt;
		In most cases, when Heroku makes a provisioning call to the add-on service, a new&amp;nbsp;account is created for a Heroku app.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Single-sign-on&lt;/strong&gt;: Heroku users do not need to provide separate account credentials to access&amp;nbsp;services the add-on provides. As long as they are logged into Heroku, they are&amp;nbsp;able to use or configure the add-on. This is accomplished by forwarding the user to&amp;nbsp;the add-on&amp;#39;s URL. A token and a timestamp are forwarded along with this request&amp;nbsp;for authentication.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Plan change&lt;/strong&gt;: Heroku allows add-on providers to change users based on tiers of service.&amp;nbsp;A Heroku user is free to upgrade or downgrade add-on tiers at any time.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Each of these required actions corresponds to a REST endpoint that the add-on service&lt;/div&gt;
&lt;div&gt;must implement:&lt;/div&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;POST&lt;/strong&gt; and &lt;strong&gt;DELETE&lt;/strong&gt; to &lt;strong&gt;http://&amp;lt;addon_service&amp;gt;/heroku/resources&lt;/strong&gt; respectively provision&amp;nbsp;and deprovision accounts.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;GET&lt;/strong&gt; to &lt;strong&gt;http://&amp;lt;addon_service&amp;gt;/heroku/resources/&amp;lt;id&amp;gt;?token=&amp;lt;token&amp;gt;&amp;amp;timestamp=&amp;lt;timestamp&amp;gt;&lt;/strong&gt;&amp;nbsp;does authentication and any necessary forwarding for SSO.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; to &lt;strong&gt;http://&amp;lt;addon_service&amp;gt;/heroku/resources/&amp;lt;id&amp;gt;&lt;/strong&gt; will update the account&amp;#39;s service&amp;nbsp;tier.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Heroku provides an awesome tool called &lt;strong&gt;kensa&lt;/strong&gt; that simulates API calls from Heroku&amp;nbsp;on these endpoints to test the add-on service.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;To install &lt;strong&gt;kensa&lt;/strong&gt; open up a terminal and make sure you have Ruby and gems installed and type:&lt;br /&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;pre style="margin-left: 40px; "&gt;
sudo gem install kensa
&lt;/pre&gt;
&lt;div&gt;&lt;strong&gt;Kensa&lt;/strong&gt; is used to generate the boilerplate manifest that describes properties of the&amp;nbsp;add-on:&lt;/div&gt;
&lt;pre style="margin-left: 40px; "&gt;

Brasero:blogpost ivan$ kensa init&lt;/pre&gt;
&lt;pre style="margin-left: 40px; "&gt;
Initialized new addon manifest in addon-manifest.json

Brasero:blogpost ivan$ cat addon-manifest.json 
{
  &amp;quot;id&amp;quot;: &amp;quot;myaddon&amp;quot;,
  &amp;quot;api&amp;quot;: {
    &amp;quot;config_vars&amp;quot;: [ &amp;quot;MYADDON_URL&amp;quot; ],
    &amp;quot;password&amp;quot;: &amp;quot;QQMmzfm3pkzzE3Fn&amp;quot;,
    &amp;quot;sso_salt&amp;quot;: &amp;quot;eqs5xOh7kGqen5hd&amp;quot;,
    &amp;quot;production&amp;quot;: &amp;quot;https://yourapp.com/&amp;quot;,
    &amp;quot;test&amp;quot;: &amp;quot;http://localhost:4567/&amp;quot;
  }
}

&lt;/pre&gt;
&lt;div&gt;Edit the &lt;strong&gt;id&lt;/strong&gt; to name the add-on. Edit the &lt;strong&gt;test&lt;/strong&gt; and &lt;strong&gt;production&lt;/strong&gt; urls to reflect&amp;nbsp;the hostnames of your respective test and development hosts.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Heroku doesn&amp;#39;t call it as such, but &lt;strong&gt;kensa&lt;/strong&gt; is also a tool that cleverly puts&amp;nbsp;test-driven development into your add-on development process. When you run the&amp;nbsp;tool in test mode, it makes REST calls to the host defined in the &lt;strong&gt;test&lt;/strong&gt; directive&amp;nbsp;of the &lt;strong&gt;addon-manifest.json&lt;/strong&gt; file:&lt;br /&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;pre style="margin-left: 40px; "&gt;
Brasero:workspace ivan$ kensa test provision

Testing manifest id key
  Check if exists [PASS]
  Check is a string [PASS]
  Check is not blank [PASS]

Testing manifest api key
  Check if exists [PASS]
  Check is a hash [PASS]
  Check contains password [PASS]
  Check contains test url [PASS]
  Check contains production url [PASS]
  Check production url uses SSL [PASS]
  Check contains config_vars array [PASS]
  Check containst at least one config var [PASS]
  Check all config vars are uppercase strings [PASS]

  Check all config vars are prefixed with the addon id [PASS]
  Check deprecated fields [PASS]
done.


Testing POST /heroku/resources
  Check response [FAIL]
    ! expected 200, got 401&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;The output above is typical from early runs of &lt;strong&gt;kensa&lt;/strong&gt;, but by running the kensa tool early and often the test failures will&amp;nbsp;guide development.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;After all the provision tests pass, invoke the next set of tests&amp;nbsp;for deprovisioning by running:&lt;br /&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;pre style="margin-left: 40px; "&gt;
Brasero:workspace ivan$ kensa test deprovision &amp;lt;some account id&amp;gt;

&lt;/pre&gt;
&lt;div&gt;Follow through with the &lt;strong&gt;planchange&lt;/strong&gt;, and &lt;strong&gt;sso&lt;/strong&gt; tests. When all tests&amp;nbsp;pass, the integration is complete!&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;What remains is to upload &lt;strong&gt;addon-manifest.json&lt;/strong&gt; to your Heroku&amp;nbsp;provider account and to document the add-on for the Heroku&amp;nbsp;Addon Catalog. More information on how to do that is&amp;nbsp;available &lt;a href="https://addons.heroku.com/provider/resources/technical/build/submit"&gt;here&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Other tips:&lt;/strong&gt;&lt;/div&gt;
&lt;ul&gt;
	&lt;li&gt;Until the add-on leaves Beta, the only plan available to test is&amp;nbsp;the &lt;strong&gt;test&lt;/strong&gt; plan. Be sure your add-on has a &lt;strong&gt;test&lt;/strong&gt; plan during&amp;nbsp;development.&lt;/li&gt;
	&lt;li&gt;Don&amp;#39;t go into Beta until the add-on is feature complete. An add-on cannot&amp;nbsp;be taken out of Beta back into Alpha without help from Heroku.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/iakvQrkI_7g" height="1" width="1"/&gt;</content>
      <author>
        <name>Ivan Tam</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/09/creating-heroku-addons-getting-started/</feedburner:origLink></entry>
  
    <entry>
      <title>Java logging, and our awesome community</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/CoFTFPYkXBY/" />
      <id>http://loggly.com/blog/2011/09/logging-out-of-your-java-code/</id>
      <updated>2011-10-20T10:57:48-07:00</updated>
      <published>2011-09-20T09:52:00-07:00</published>
      <category term="Code" /><category term="Log Management" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Since I&amp;#39;m on a roll with the blog posts, I thought I&amp;#39;d quickly cover some of the ways you can log out of your Java code to us. I&amp;#39;ve been buried in *our* java code for nearly two years now, and we&amp;#39;ve been talking about improving the quality of the logging that we&amp;#39;re doing there recently. As it turns out, there are some pretty interesting projects out there that look like they may be just what we need...&lt;/p&gt;
&lt;p&gt;Before talking about them, though, I thought I&amp;#39;d give you a quick run-down on how we&amp;#39;re doing things now. We use a very slightly tweaked version of&amp;nbsp;&lt;a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/net/SyslogAppender.html"&gt;the log4j SyslogAppender&lt;/a&gt;&amp;nbsp; (version 1.2.16) - the tweak is that we upped the message size from 1k to 32k. Yep, we&amp;#39;re completely ignoring the syslog RFC, but its been working perfectly fine for us for quite a while, so I&amp;#39;m ok with that. We configure log4j as described on&amp;nbsp;&lt;a href="http://wiki.loggly.com/log4j"&gt;our wiki&lt;/a&gt;&amp;nbsp;so that we log to a local syslog-ng (using a different facility for each app) which forwards to the appropriate ports on logs.loggly.com. Its a very simple approach, but has been very reliable for us.&lt;/p&gt;
&lt;p&gt;So why would we want to change it?&lt;/p&gt;
&lt;p&gt;The main reason is that we set this up before we could send JSON data, and we log a lot of performance data, which is a perfect fit for JSON. We&amp;#39;re going to be moving all of our java logging to JSON over the next few months, because it will let us dive deeper into our logs, without all the noise.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago, Patrick Lightbody from neustar emailed us to tell us about a java class he&amp;#39;d written to send data into Loggly using http. Its an extension of java.util.logging.Handler and is only a couple of hundred lines of nice clean code . He shared it on &lt;a href="https://github.com/webmetrics/loggly-java"&gt;github&lt;/a&gt;&amp;nbsp;and described how to use it in his email.&lt;/p&gt;&lt;script src="https://gist.github.com/1230936.js?file=java_log.j"&gt;&lt;/script&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;If you&amp;#39;re using java.util.logging, give it a whirl!&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This got me thinking that we&amp;#39;ve been a little, um, remiss in communicating just how many libraries people have written for us, so I did a search on github for java projects with&amp;nbsp;&lt;a href="https://github.com/search?type=Repositories&amp;amp;language=Java&amp;amp;q=loggly&amp;amp;repo=&amp;amp;langOverride=&amp;amp;x=13&amp;amp;y=25&amp;amp;start_value=1"&gt;loggly in the repo name&lt;/a&gt;&amp;nbsp;and found some other projects that also look pretty nice...&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;M&amp;aring;rten Gustafson has implemented a &lt;a href="https://github.com/chids/logback-loggly-appender"&gt;logback/SLF4J appender&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Spidertracks has implemented a&amp;nbsp;&lt;a href="https://github.com/Spidertracks/logglylog4j"&gt;log4j appender&lt;/a&gt;&amp;nbsp;that uses an embedded HSQL db to guarantee delivery of your log events&lt;/li&gt;
	&lt;li&gt;Raoul Schmidigerhas is working on a&amp;nbsp;&lt;a href="https://github.com/raoulsson/log4j2loggly"&gt;log4j appender&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Thomas Engelschmidt is working on a&amp;nbsp;&lt;a href="https://github.com/zamaterian/Ring-Loggly-Access"&gt;clojure&lt;/a&gt;&amp;nbsp;logger&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these projects use our HTTP interface, rather than TCP or UDP, which makes sense since we don&amp;#39;t currently support JSON except over HTTP. We&amp;#39;re planning on fixing that :-)&lt;/p&gt;
&lt;p&gt;Expanding the search a little, there are a bunch of projects in github, on top of the ones we&amp;#39;ve created, that should make it easy to log out of javascript, python, ruby, and C#, as well as the Java stuff I talked about above.&lt;/p&gt;
&lt;p&gt;We&amp;#39;re obviously pretty happy that so many people are working on making it easier to get data to us, and I want to say thank you to everyone who has been contributing to all of those projects. &amp;nbsp;I&amp;#39;d like to encourage all of you reading this to jump in and help out if you can. Everyone who is contributing to these projects should drop us a line, and we&amp;#39;ll send you one of our &lt;a href="http://dl.dropbox.com/u/9290791/wallpaper/xray/xray_1024x768.png"&gt;X-Ray Beaver&lt;/a&gt;&amp;nbsp;tee&amp;#39;s as a thank you :-)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/CoFTFPYkXBY" height="1" width="1"/&gt;</content>
      <author>
        <name>jon@loggly.com</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/09/logging-out-of-your-java-code/</feedburner:origLink></entry>
  
    <entry>
      <title>Alerting with Alert Birds</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/aoljE7HYJ2U/" />
      <id>http://loggly.com/blog/2011/09/alerting-with-alert-birds/</id>
      <updated>2011-09-14T11:54:18-07:00</updated>
      <published>2011-09-13T16:40:00-07:00</published>
      <category term="Log Management" /><category term="Startup" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Back during my ISP heydays in the late 90s, I stumbled across a project called &lt;a href="http://peep.sourceforge.net/intro.html"&gt;Peep&amp;nbsp;The Network Auralizer&lt;/a&gt;. &amp;nbsp;Peep basically takes things like netflow events from remote clients and sends them to a audio enabled server. &amp;nbsp;Network traffic sounds like running water. &amp;nbsp;Pings sound like birds chirping. SSH logins like frog croaks. &amp;nbsp;The result is something that sounds like one of those sleep machines from the 80s.&lt;/p&gt;
&lt;p&gt;&lt;embed flashvars="audioUrl=http://peep.sourceforge.net/demo/demo2.mp3" height="27" quality="best" src="http://www.google.com/reader/ui/3523697345-audio-player.swf" type="application/x-shockwave-flash" width="400"&gt;&lt;/embed&gt;&lt;/p&gt;
&lt;p&gt;What was really interesting about Peep, besides the fact it could lull you to sleep, was it could notify you of events that were important in aggregate but not necessaraly by themselves. &amp;nbsp;A ton of failed SSH logins became a chorus of servers crying for help. &amp;nbsp;High network load became a rushing river.&lt;/p&gt;
&lt;p&gt;Now I look back on it, my use of Peep was my first pass at alerting and monitoring complex events in my infrastructure. &amp;nbsp;Today it&amp;#39;s also a good excuse to build an app for Loggly which makes a bunch of stupid bird noises.&lt;/p&gt;
&lt;h2&gt;Alerting Rules&lt;/h2&gt;
&lt;p&gt;Alerting is the #1 Loggly customer requested feature, so much so in fact that I broke down a few months ago and wrote a &lt;a href="http://loggly.com/blog/2011/03/alerting-with-loggly-and-pagerduty/"&gt;post on doing alerting with Loggly and Pagerduty&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After I wrote the post one of our customers commented that it sucked he had to run his own server to execute the cron jobs which ran the searches on Loggly. &amp;nbsp;He&amp;#39;s right. &amp;nbsp;Requiring your users to run yet more infrastructure just to use a core bit of your service isn&amp;#39;t the best way to win favors. &amp;nbsp;And, it certainly doesn&amp;#39;t scale well.&lt;/p&gt;
&lt;p&gt;On that note, I&amp;#39;m pleased as punch to announce Loggly is &lt;a href="http://alertbirds.com/"&gt;now shipping alerting via the Alert Birds service&lt;/a&gt;. &amp;nbsp;You can &lt;a href="http://twitter.com/alertbirds"&gt;follow the Alert Birds on Twitter&lt;/a&gt; too!&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://loggly.com/assets/4e6fbeb4dabe9d483b000451/feature_thumbnail/largebirdslogo.png" style="width: 300px; height: 201px; " /&gt;&lt;/p&gt;
&lt;h2&gt;Using Alert Birds with Loggly&lt;/h2&gt;
&lt;p&gt;Using Alert Birds with your Loggly account is simple. &amp;nbsp;Navigate to&amp;nbsp;&lt;a href="http://alertbirds.com/"&gt;the Alert Birds website&lt;/a&gt; and then log into your Google Account. &amp;nbsp;Once you are logged in, you&amp;#39;ll be given a form that allows you to enter your Loggly&amp;#39;s account &amp;#39;subdomain&amp;#39;. &amp;nbsp;Once you submit your subdomain, you&amp;#39;ll be taken to Loggly to login to that account and grant access to the Alert Birds&amp;#39; app. &amp;nbsp;You&amp;#39;ll be taken back to the Alert Birds&amp;#39; site when you are done authing the app to Loggly.&lt;/p&gt;
&lt;p&gt;Alertbirds allows you to create an unlimited number of alerts, each of which are comprised of saved searches run on Loggly and endpoints that get called when searches return above or below a given threshold. &amp;nbsp;Alerts are run on a schedule you define, and the endpoints currently (only) support pushing events to &lt;a href="http://pagerduty.com"&gt;PagerDuty&amp;#39;s APIs&lt;/a&gt; for notification. &amp;nbsp;Alert Birds&amp;nbsp;also allows you to trigger sound events in a &amp;nbsp;browser viewing the Alert Birds&amp;#39; website.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a short video on using the Alert Birds&amp;#39; application (sorry for saying um so much):&lt;/p&gt;
&lt;p&gt;&lt;iframe allowfullscreen="" frameborder="0" height="488" src="http://player.vimeo.com/video/29015559?title=0&amp;amp;byline=0&amp;amp;portrait=0" webkitallowfullscreen="" width="520"&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;For more detailed setup info, you can &lt;a href="http://wiki.loggly.com/alertbirds"&gt;reference our wiki page on Alert Birds&lt;/a&gt;. &amp;nbsp;If you&amp;#39;d like to trigger an alert for Kord on his blog, click &lt;a href="http://geekceo.com/failftw"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Apps for a Logging Platform&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve &lt;a href="https://github.com/loggly/alertbirds-community-edition"&gt;Open Sourced the Alert Birds project&lt;/a&gt; to help illustrate how easy it is to build a logging application on Loggly. &amp;nbsp;Alert Birds was writtien to run on &lt;a href="http://appspot.com"&gt;Google&amp;#39;s AppEngine service&lt;/a&gt;, but we&amp;#39;ll be launching other apps soon that run on other frameworks and services.&lt;/p&gt;
&lt;p&gt;Keep an eye out for more applications and app support coming out of Loggly in the near future. &amp;nbsp;We&amp;#39;re working on apps like &amp;nbsp;a 3D globe for visualizing website traffic, web analytics, application reporting, and more!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/aoljE7HYJ2U" height="1" width="1"/&gt;</content>
      <author>
        <name>Kord Campbell</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/09/alerting-with-alert-birds/</feedburner:origLink></entry>
  
    <entry>
      <title>IBM developerWorks podcast with Andy Glover</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/T_tixX6gGw0/" />
      <id>http://loggly.com/blog/2011/09/ibm-developerworks-podcast-with-andy-glover/</id>
      <updated>2011-09-07T15:50:50-07:00</updated>
      <published>2011-09-07T15:25:00-07:00</published>
      <category term="Log Management" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Andy Glover (from &lt;a href="http://www.app47.com/"&gt;App47&lt;/a&gt;) hosts a podcast on IBM developerWorks, and asked me to chat about some of the things we&amp;#39;re doing here at loggly. I never realized how many ... pauses I take while I&amp;#39;m ... speaking. I&amp;#39;m going to pretend that this is because I&amp;#39;m ... carefully considering what I&amp;#39;m saying, rather than that I took a few too many knocks to the head back when I was playing Rugby.&lt;/p&gt;
&lt;p&gt;Anyway, here&amp;#39;s the link:&amp;nbsp;&lt;a href="http://www.ibm.com/developerworks/java/library/j-gloverpodcast3/index.html"&gt;http://www.ibm.com/developerworks/java/library/j-gloverpodcast3/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Beware the strong gravitational pull of developerWorks. Its way too easy to lose hours and hours browsing through all of the awesome content there.&lt;/p&gt;
&lt;p&gt;Thanks to Andy for letting me ramble on about the wonders of search :-)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/T_tixX6gGw0" height="1" width="1"/&gt;</content>
      <author>
        <name>jon@loggly.com</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/09/ibm-developerworks-podcast-with-andy-glover/</feedburner:origLink></entry>
  
    <entry>
      <title>DreamForce presentation</title>
      <link href="http://feedproxy.google.com/~r/LogglyByHoover/~3/M5sdU6dGzIY/" />
      <id>http://loggly.com/blog/2011/09/dreamforce-presentation/</id>
      <updated>2011-09-07T15:47:20-07:00</updated>
      <published>2011-09-07T15:22:00-07:00</published>
      <category term="Code" /><category term="Log Management" />
      <summary type="html" />
      <content type="html">&lt;p&gt;Last week at DreamForce, I did a talk about how magical Loggly is, and a few people have asked to get copies of the slides. So, to make it a bit easier for everyone, here they are...&lt;/p&gt;
&lt;p&gt;&lt;a href="http://loggly.com/assets/4e67ec60dabe9d63dc002074/dreamworks_2011.pdf"&gt;http://loggly.com/assets/4e67ec60dabe9d63dc002074/dreamworks_2011.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;I was able to demo at DreamForce, so most of the exmaple slides (&amp;quot;Simple search&amp;quot; through &amp;quot;uniq&amp;quot;) never saw the light of day there. They&amp;#39;re included here, just for the sake of completeness.&lt;/p&gt;
&lt;p&gt;Big thanks to Heroku &amp;amp; SalesForce for inviting us to DreamForce to celebrate us &lt;a href="http://loggly.com/blog/2011/08/announcing-the-loggly-addon-for-heroku/"&gt;becoming an Add-on for Heroku&lt;/a&gt;&amp;nbsp;- we had a lot of fun, and everyone seemed to love Hoover. Then again, how could you not?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/LogglyByHoover/~4/M5sdU6dGzIY" height="1" width="1"/&gt;</content>
      <author>
        <name>jon@loggly.com</name>
      </author>
    <feedburner:origLink>http://loggly.com/blog/2011/09/dreamforce-presentation/</feedburner:origLink></entry>
  
</feed>

