<?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>I'm a lumberjaph</title>
 
 <link href="http://lumberjaph.net/" />
 <updated>2013-03-02T03:47:00+00:00</updated>
 <id>http://lumberjaph.net/</id>
 <author>
   <name>franck cuny</name>
   <email>franck@lumberjaph.net</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ImALumberjaph" /><feedburner:info uri="imalumberjaph" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Practical Joke</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/gjyYupS7gWI/practical-joke.html" />
   <updated>2013-02-24T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/linkfluence/2013/02/24/practical-joke</id>
   <content type="html">&lt;p&gt;I’ve nothing exciting to write about so I’ll share a prank I did a few years ago (because I’m kinda proud of this one).&lt;/p&gt;

&lt;p&gt;To protect the innocent, I’ll change all the names.&lt;/p&gt;

&lt;p&gt;I was working at a company named $LF.  One of my colleague ($NG), always looks at his keyboard when he types.  Some time he can type for a few minutes.  Then he looks at his screen, only to realize that it’s full of typo, or worse, that he had typed in the wrong window.  This used to really bother me, because I know he’s been typing for years, but I was not sure if he was looking at his keyboard because he needs to, or just because his head is too heavy to look at the screen.&lt;/p&gt;

&lt;p&gt;So one day, while everybody (except $GM) were away taking a break, I decided to conduct an experiment.&lt;/p&gt;

&lt;p&gt;The french keyboard uses the &lt;a href="http://en.wikipedia.org/wiki/Azerty"&gt;AZERTY&lt;/a&gt; layout.  $NG uses the &lt;a href="http://www.gnu.org/software/emacs/"&gt;best editor in the world&lt;/a&gt;, where the &lt;em&gt;x&lt;/em&gt; key is &lt;em&gt;really&lt;/em&gt; important (try to do something without ‘Meta-x’).  He also uses a laptop, connected to an external monitor and with an external keyboard.  So I decided to swap the &lt;em&gt;x&lt;/em&gt; and the &lt;em&gt;w&lt;/em&gt; letter on the external keyboard, by switching the caps.  The actual &lt;em&gt;x&lt;/em&gt; and &lt;em&gt;w&lt;/em&gt; were still at the same place, only the label on the key was switched.&lt;/p&gt;

&lt;p&gt;When he came back from the break, he starts typing as usual.  Quickly he realized that something was wrong, and he did a lot of things to figure out what.  Among them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;verify that the content of &lt;code&gt;xmodmaprc&lt;/code&gt; was correct, and then tweak it&lt;/li&gt;
  &lt;li&gt;reinitialize the layout with &lt;code&gt;setxkbmap&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;use a tool (maybe &lt;code&gt;showkey&lt;/code&gt; ?) to see what was the actual code send from the keyboard while hitting the key&lt;/li&gt;
  &lt;li&gt;probably recompiled a bunch of stuff&lt;/li&gt;
  &lt;li&gt;definitely upgraded his Linux distribution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, he understood that when hitting &lt;em&gt;x&lt;/em&gt;, &lt;em&gt;w&lt;/em&gt; was received, and for &lt;em&gt;w&lt;/em&gt;, &lt;em&gt;x&lt;/em&gt;.  He rebooted his laptop (because when in doubt, you should “&lt;a href="http://www.youtube.com/watch?v=nn2FB1P_Mn8"&gt;tried turning it off and on again&lt;/a&gt;”).  But the problem was still there.&lt;/p&gt;

&lt;p&gt;If I remember correctly, that’s when he decided to look at the laptop’s keyboard and tried to use it, only to realize that it was working correctly!  So he asked the ops guy, $GM, who was sitting next to me, if there was a spare keyboard somewhere.  I slowly turned my head toward $GM, whispering ‘noooo’ to him, and he replied to $NG “nop, sorry, no spare keyboard, &amp;lt;insert stupid excuse #49&amp;gt;”.&lt;/p&gt;

&lt;p&gt;The other developers started to realize that something was wrong with $NG, but no one said or did anything yet.  We were about 30 minutes in the experiment now.&lt;/p&gt;

&lt;p&gt;Because he still had work to do, he tried to cop with the problem, and every time he needed a &lt;em&gt;x&lt;/em&gt; or a &lt;em&gt;w&lt;/em&gt;, he would type something, stop, look at the screen, sigh/grumble, and use the laptop’s keyboard to fix all the &lt;em&gt;w&lt;/em&gt; and &lt;em&gt;x&lt;/em&gt;.  That was difficult to miss, and soon other people asked him what was wrong, and so that’s when I revealed .&lt;/p&gt;

&lt;p&gt;When I explained what I did he was surprised, starred at the two keyboards for a while, and saw that, effectively, the keys were swapped!  I’m pretty sure the rest of the team made fun of him but I don’t really remember exactly how.&lt;/p&gt;

&lt;p&gt;I consider the experiment to be a success: I proved that he need to look at his keyboard to type, and I’m also confident that I can reproduce it with the same subject multiple time and obtain the same result again.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/gjyYupS7gWI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/linkfluence/2013/02/24/practical-joke.html</feedburner:origLink></entry>
 
 <entry>
   <title>Should I read the code ?</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/dqM8su59EpY/should-I-read-the-code.html" />
   <updated>2013-02-19T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/devops/2013/02/19/should-I-read-the-code</id>
   <content type="html">&lt;p&gt;This conversation happened twice in the last few weeks at work, the first time during my 1:1 with my manager, and a second time with the whole team.&lt;/p&gt;

&lt;p&gt;We were investigating &lt;a href="http://riemann.io/"&gt;Riemann&lt;/a&gt;, and we started to discuss what it would means to adopt this technology in our stack.  Riemann is written in Clojure, and no one at work is really familiar with this language (except for me, and I’m don’t consider myself efficient with it).&lt;/p&gt;

&lt;p&gt;The question is how do you deal with a new tool when there’s only one person in the team that can read the code, and therefore contribute to the project to add features, fix bugs, etc.  Are we supposed to be familiar with the code of the things that we use?&lt;/p&gt;

&lt;p&gt;I’ve never read the code of MySQL, I’ve read parts of Apache’s code, and I’ve never looked at the source of the Linux’ kernel.  At the same time, I usually read the code of the Perl and Python libraries I use frequently, I’ve also read the source of statsd and Graphite (two other tools that we looked at) in order to understand what they do and hunt for issues (in the way we use them) or bugs.&lt;/p&gt;

&lt;p&gt;I see two ways to approach this question so far: as a developer and as a user.  As a developer, I consider that I &lt;strong&gt;have to&lt;/strong&gt; read and understand the code of the libraries my code depends on (we’ve found some serious issues in libraries we use daily because of this approach).&lt;/p&gt;

&lt;p&gt;For services we use in the infrastructure, it depends of the size of the tool and it’s community.  For a new product, or when the documentation is too sparse, or when the community is rather small, it’s a good thing to be able to look at the code and explain what it does.  For bigger projects (MySQL, Apache, Riak), so far I’ve relied on the experiences people had with the tools, the community.&lt;/p&gt;

&lt;p&gt;I’ll conclude this post with an anecdote.  Last Thursday we were trying to understand why the CPU load on the Graphite’s box went over the roof when we added about 25% more metrics to it.  With Abe and Hachi we said “ok let’s dig into this problem”.  You could have guessed who are the ops while looking at the scene.  We were looking for the same things: reads and write.  Abe and Hachi started to do that with the help of &lt;code&gt;strace&lt;/code&gt;, while I started to walk through the code.  I think the two ways are valid, at least you can use one to correlate the other, and they gave you different information (&lt;code&gt;strace&lt;/code&gt; will help you to time the operations, while the code would explain what you’re writing and reading).&lt;/p&gt;

&lt;p&gt;I’m curious to hear how other approach this problem.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/dqM8su59EpY" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/devops/2013/02/19/should-I-read-the-code.html</feedburner:origLink></entry>
 
 <entry>
   <title>Let's talk about Graphite</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/j-pStbrCJNg/let-s-talk-about-graphite.html" />
   <updated>2013-01-28T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/devops/2013/01/28/let-s-talk-about-graphite</id>
   <content type="html">&lt;p&gt;As I’ve already mentionned in a &lt;a href="http://lumberjaph.net/devops/2013/01/10/carbons-manhole.html"&gt;previous post&lt;/a&gt;, at &lt;a href="http://saymedia.com"&gt;$work&lt;/a&gt; we are currently deploying Graphite and the usual suspects.&lt;/p&gt;

&lt;p&gt;Finding articles on how to install all these tools is easy, there’s plenty of them.  But what’s &lt;em&gt;really&lt;/em&gt; hard to find, are stories on &lt;em&gt;how to use them&lt;/em&gt;: what’s collected, how, why, how do you organize your metrics, do you rewrite them, etc.&lt;/p&gt;

&lt;p&gt;What I want with this post is to start a discussion about usages, patterns, and good practices.  I’m going to share how &lt;em&gt;we&lt;/em&gt;, at SAY, are using them, and maybe this could be the start of a conversation.&lt;/p&gt;

&lt;h2 id="graphitecollectdstatsd"&gt;Graphite/collectd/statsd&lt;/h2&gt;

&lt;p&gt;We’re using &lt;a href="https://github.com/etsy/statsd"&gt;statsd&lt;/a&gt;, &lt;a href="https://collectd.org"&gt;collectd&lt;/a&gt; &lt;a href="https://github.com/graphite-project"&gt;Graphite&lt;/a&gt; (and soon &lt;a href="http://riemann.io"&gt;Riemann&lt;/a&gt; for alerting).&lt;/p&gt;

&lt;h3 id="retention"&gt;Retention&lt;/h3&gt;

&lt;p&gt;Our default retention policy is: &lt;code&gt;10s:1h, 1m:7d, 15m:30d, 1h:2y&lt;/code&gt;.  We don’t believe that Graphite should be used for alerting: it’s a tool for looking at history and trends.&lt;/p&gt;

&lt;p&gt;360 points for the last hour is enough to refer to a graph when an incident occurs.  Most of the teams are releasing at least once a week, so 1 minute definition for a week is enough to compare trends between two releases.  Then we go to a month (2 sprints) and they 2 years.  We thought at first to keep only 15 months (1year + 1 quarter to compare), but since we have enough disk space, we decided to keep two years, however we might decide to change that in the future.&lt;/p&gt;

&lt;h3 id="system"&gt;System&lt;/h3&gt;

&lt;p&gt;We don’t do anything fancy here.  &lt;code&gt;collectd&lt;/code&gt; is running on each host, and then write to a central &lt;code&gt;collectd&lt;/code&gt; server.&lt;/p&gt;

&lt;h3 id="services"&gt;Services&lt;/h3&gt;

&lt;p&gt;For shared services (Memcached, Varnish, Apache, etc), we talk to &lt;code&gt;statsd&lt;/code&gt;.  We have a Perl script named &lt;code&gt;sigmoid&lt;/code&gt;, with the following usage:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="sh"&gt;Usage: ./sigmoid &lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;options&amp;gt;&lt;span class="o"&gt;]&lt;/span&gt; &amp;lt;metricname&amp;gt; &amp;lt;value&amp;gt;
 Exactly one of:
 --counter &lt;span class="o"&gt;(&lt;/span&gt;value defaults to 1&lt;span class="o"&gt;)&lt;/span&gt;
 --aggregate
 --gauge
 --event
 --raw

 Other options:
 --disable-multiplex &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;statsd only&lt;span class="o"&gt;)&lt;/span&gt;
 --appname
 --hostname &lt;span class="o"&gt;(&lt;/span&gt;to log on behalf of another machine&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This script is used by other scripts who monitor logs, status of apps, etc.  This way it’s very easy for a Perl, Python, Shell script to just call &lt;code&gt;sigmoid&lt;/code&gt; via &lt;code&gt;system&lt;/code&gt;, and then send the metric and the value to &lt;code&gt;statsd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For some other services we might need something more specific.  Let’s take a look at Apache.  We have another Perl script for the &lt;strong&gt;CustomLog&lt;/strong&gt; settings (&lt;code&gt;CustomLog "|/usr/local/bin/apache-statsd"&lt;/code&gt;).  The script is doing the following things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;compute the size of the HTTP request in bytes&lt;/li&gt;
  &lt;li&gt;compute how long it took to return the response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, it will send the following lines to &lt;code&gt;statsd&lt;/code&gt; (with $base being the vhost in our case):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;$base.all.requests:1|c&lt;/strong&gt; increases the total of HTTP requests we’re receiving&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;$base.all.bytes:$bytes|ms&lt;/strong&gt; send the size, in bytes, of that request&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;$base.all.time:$msec|ms&lt;/strong&gt; the time spend to get the response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we will send the same line two more times, with a different prefix: &lt;strong&gt;$base.method.$request_method&lt;/strong&gt; &lt;em&gt;and&lt;/em&gt; &lt;strong&gt;$base.status.$status&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id="applications"&gt;Applications&lt;/h3&gt;

&lt;p&gt;Here, developers decide what they want to collect, and send the metric to &lt;code&gt;statsd&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id="events"&gt;Events&lt;/h3&gt;

&lt;p&gt;And finally we have events.  Every time we push an application or a configuration, we create a new event.&lt;/p&gt;

&lt;h2 id="proxying-statsd"&gt;Proxying statsd&lt;/h2&gt;

&lt;p&gt;We want metrics to be well organized, in a clear hierarchy.  &lt;a href="https://github.com/obfuscurity"&gt;Jason Dixon&lt;/a&gt; wrote in a &lt;a href="http://obfuscurity.com/2012/05/Organizing-Your-Graphite-Metrics"&gt;blog post&lt;/a&gt; that &lt;em&gt;Misaligned paths are ok&lt;/em&gt;.  I disagree.  We’re collecting more than 100k metrics so far.  If things are not well organized, it will become quickly very difficult to find what you’re looking for.&lt;/p&gt;

&lt;p&gt;So, here’s how we organize our metrics.  The first level is the environment (PROD, CI, DEV, …).  Then we have &lt;em&gt;apps&lt;/em&gt; and &lt;em&gt;hosts&lt;/em&gt;.  For the &lt;em&gt;host&lt;/em&gt; section, we group by cluster type (Hadoop cluster, Web servers for TypePad, etc), and then you have the actual host, with all the metrics collected.  For &lt;em&gt;apps&lt;/em&gt;, we have four main categories: &lt;em&gt;aggregate&lt;/em&gt;, &lt;em&gt;counters&lt;/em&gt;, &lt;em&gt;events&lt;/em&gt; and &lt;em&gt;gauges&lt;/em&gt; (I’ll come back on that later).&lt;/p&gt;

&lt;p&gt;Earlier I said that apps where sending metrics to &lt;code&gt;statsd&lt;/code&gt;, but that’s not exactly true.  We (mostly) never write directly to statsd or Graphite.&lt;/p&gt;

&lt;p&gt;On each host, we have a Perl script listening.  This proxy will rewrite all the incoming metrics by appending to the name the environment, the cluster and so on.  This way when someone want to send a key, he doesn’t have to care convention or using the correct prefix.&lt;/p&gt;

&lt;p&gt;Also, it will also multiplex the metric: we want the same key to end-up under &lt;em&gt;host&lt;/em&gt; and under &lt;em&gt;app&lt;/em&gt;.  Let’s take an example here.  If you’re writing a web service, you may want to send a metric for the total time taken by an endpoint (this will be an aggregate).  Our key will be something like: &lt;strong&gt;&amp;lt;application-name&amp;gt;.&amp;lt;endpoint-name&amp;gt;.&amp;lt;http-method&amp;gt;.&amp;lt;total-time&amp;gt;&lt;/strong&gt;.  The proxy, based on the network address, will determine that it’s environment is CI, and that it’s an application.  But it also knows the name of the server, and the cluster.  So two keys will be created:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&amp;lt;CI&amp;gt;.&amp;lt;apps&amp;gt;.&amp;lt;aggregate&amp;gt;.&amp;lt;application-name&amp;gt;.&amp;lt;endpoint-name&amp;gt;.&amp;lt;http-method&amp;gt;.&amp;lt;total-time&amp;gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&amp;lt;CI&amp;gt;.&amp;lt;hosts&amp;gt;.&amp;lt;cluster-name&amp;gt;.&amp;lt;host-name&amp;gt;.&amp;lt;aggregate&amp;gt;.&amp;lt;application-name&amp;gt;.&amp;lt;endpoint-name&amp;gt;.&amp;lt;http-method&amp;gt;.&amp;lt;total-time&amp;gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way we can find the metric aggregated by application, or if we think there’s a problem in one machine, we can compare per host the same metric.&lt;/p&gt;

&lt;h2 id="other-problems-with-statsd-and-graphite"&gt;Other problems with statsd and Graphite&lt;/h2&gt;

&lt;p&gt;I don’t know if it’s a problem with vocabulary, or our maths (I admit that my maths are not good, but I trust Abe and Hachi’s maths), but you can’t imagine how much time we spend debating around the words gauges, counters and aggregates.  What they mean, how they work, when to use them.  So here’s my questions: are we missing something obvious?  do we over think it? or is it also confusing, and people are misusing them?&lt;/p&gt;

&lt;p&gt;Let’s take &lt;strong&gt;gauge&lt;/strong&gt; as an example.  If you read &lt;a href="https://github.com/etsy/statsd/blob/master/README.md#gauges"&gt;the documentation for gauges&lt;/a&gt;, it seems very simple: you send a value, and it will be recorded.  Well, the thing is it will record only the last value send during the 10 seconds interval.  This work well when you have a cron job that will look at something every minute and report a metric to &lt;code&gt;statsd&lt;/code&gt;, not if you’re sending that 10 times a second (and yes, we will provide a patch for documentation soon).&lt;/p&gt;

&lt;p&gt;Another one where we lost a good amount of time: if you’re smallest retention is different from the interval used by statsd to flush the data, they will be graphed incorrectly (see this &lt;a href="https://github.com/etsy/statsd/issues/32#issuecomment-1830985"&gt;comment&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The best “documentation” for &lt;code&gt;statsd&lt;/code&gt;, so far, are the discussions in the &lt;a href="https://github.com/etsy/statsd/issues"&gt;issues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We have some other complains about Graphite.  Even after reading the &lt;a href="http://graphite.wikidot.com/whisper#toc1"&gt;rationals&lt;/a&gt; for Whisper, I’m not convinced it was a good idea to replace RRD with it.  We also discovered some issues with &lt;a href="http://if.andonlyif.net/blog/2013/01/graphites-derivative-function-lies.html"&gt;Graphite’s functions&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="meetup"&gt;Meetup&lt;/h2&gt;

&lt;p&gt;We’ve a huge basement at work that can be used to host meetup.  There’s already a few meetup in the San Francisco about “devops” stuff (&lt;a href="http://www.meetup.com/San-Francisco-Metrics-Meetup/events/98875712/"&gt;Metrics Meetup&lt;/a&gt;, &lt;a href="http://www.meetup.com/San-Francisco-DevOps/"&gt;SF DevOps&lt;/a&gt;, etc), but maybe there’s room for another one with a different format.  &lt;/p&gt;

&lt;p&gt;What I would like, is a kind of forum, where a topic is picked, and people share their &lt;em&gt;experiences&lt;/em&gt; (the bad, the good and the ugly), not how to configure or deploy something.  And there’s a lot of topics where I’ve questions: deployment (this will be the topic of my next entry I think), monitoring, alerting, post-mortem, etc.  If you’re interested, send me an email, or drop a comment on this post.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/j-pStbrCJNg" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/devops/2013/01/28/let-s-talk-about-graphite.html</feedburner:origLink></entry>
 
 <entry>
   <title>Where I'm excited about a keyboard</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/Tw7VbaOrBj8/where-im-excited-about-a-keyboard.html" />
   <updated>2013-01-14T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/hardware/2013/01/14/where-im-excited-about-a-keyboard</id>
   <content type="html">&lt;p&gt;One thing that I always find fascinating is how an object, or a way of thinking, was modeled 25, 50 or 100 years ago, and how we keep going on with the same design without trying to think if it’s actually the right one, or to challenge our way of thinking with a different one.  Keyboards are one of those things.  We all know the &lt;a href="http://en.wikipedia.org/wiki/Qwerty"&gt;origin&lt;/a&gt; of the QWERTY layout, why the keyboard has this shape, and so on (the &lt;a href="http://en.wikipedia.org/wiki/Computer_keyboard"&gt;wikipedia&lt;/a&gt; page is a good read).  Let’s take a look at this tweet from &lt;a href="http://technomancy.us"&gt;Technomancy&lt;/a&gt; (who, for the the record, also has some &lt;a href="http://www.flickr.com/photos/technomancy/4397554484/"&gt;interesting&lt;/a&gt; keyboard ideas :)&lt;/p&gt;

&lt;blockquote class="twitter-tweet tw-align-center"&gt;&lt;p&gt;I wonder how long it'll be before we can look back and laugh at the idea of poking a QWERTY soft-keyboard on a touch screen. Hope it's soon.&lt;/p&gt;&amp;mdash; Phil Hagelberg (@technomancy) &lt;a href="https://twitter.com/technomancy/status/290959908302647296" data-datetime="2013-01-14T23:13:42+00:00"&gt;January 14, 2013&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;

&lt;p&gt;That’s exactly what I’m talking about: we keep reproducing the same design without questioning it’s benefits (I’ve no doubt that people at Apple and Google have tried a lot of alternatives, an they probably decided to stick to this one because it’s the most common and people are used to it.  Still, it doesn’t mean we have to stick with it).  But even for physical keyboard, we keep the same design: a large space key (why ?!), a capslock key (who need that one, even remapped to “control” I feel like it’s a bad place to physically put a key on the keyboard), large enter/shift keys, etc.&lt;/p&gt;

&lt;p&gt;I’m not a keyboard nerd.  But sometimes I take a look at some new and strange models, sometimes I try one of them, and I might even buy one, like the &lt;a href="http://www.typematrix.com"&gt;TypeMatrix&lt;/a&gt; (that one I really liked).&lt;/p&gt;

&lt;p&gt;So, when &lt;a href="https://twitter.com/obra"&gt;Jesse&lt;/a&gt; announced that he was working on a keyboard, I got &lt;em&gt;really&lt;/em&gt; excited.  His layout is very interesting (it seems to be inspired by the kinesis), and the shape is also innovative.  I also remember reading that he suffers from RSI, which mean it’s something he will be careful bout.  Take a look at the mapping: there’s only 52 keys, control/shift/alt are repeated, but with this shape it makes sense, since they’re dedicated to one half of the keyboard.&lt;/p&gt;

&lt;center&gt;&lt;a href="http://www.flickr.com/photos/obra/8361045529/" title="A reduced travel keyboard layout by jesse, on Flickr"&gt;&lt;img src="http://farm9.staticflickr.com/8096/8361045529_4694afe187.jpg" width="500" height="281" alt="A reduced travel keyboard layout" /&gt;&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;You can &lt;a href="http://blog.fsck.com/2012/12/building-a-keyboard-part-1.html"&gt;read&lt;/a&gt; &lt;a href="http://blog.fsck.com/2012/12/building-a-keyboard-part-2.html"&gt;about&lt;/a&gt; &lt;a href="http://blog.fsck.com/2013/01/a-pound-of-sculpey.html"&gt;his&lt;/a&gt; &lt;a href="http://blog.fsck.com/2013/01/pinkies-and-your-brain.html"&gt;progress&lt;/a&gt;.  He’s also publishing &lt;a href="http://www.flickr.com/photos/obra/"&gt;pictures&lt;/a&gt; on his flickr account.&lt;/p&gt;

&lt;p&gt;I really hope he will be able to build this keyboard and manage to manufacture it (maybe a kickstarter project ?).  I’ll definitely be in line to get one.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/Tw7VbaOrBj8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/hardware/2013/01/14/where-im-excited-about-a-keyboard.html</feedburner:origLink></entry>
 
 <entry>
   <title>Carbon's manhole</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/Ljcb1IHIw5g/carbons-manhole.html" />
   <updated>2013-01-10T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/devops/2013/01/10/carbons-manhole</id>
   <content type="html">&lt;p&gt;We’re rolling out Graphite and statsd at &lt;a href="http://saymedia.com"&gt;work&lt;/a&gt;, and I’ve spend some time debugging our setup.  Most of the time, the only thing I need is &lt;code&gt;tcpdump&lt;/code&gt; to verify that a host is sending correctly the various metrics.&lt;/p&gt;

&lt;p&gt;But today, thanks to a &lt;a href="http://if.andonlyif.net/blog/2013/01/the-case-of-the-disappearing-metrics.html"&gt;stupid reason&lt;/a&gt;, I’ve learned about another way to debug &lt;a href="http://graphite.readthedocs.org/en/latest/carbon-daemons.html"&gt;carbon&lt;/a&gt;: the manhole.  The idea of the manhole is to give you a access to a REPL attached to the live process.  When my boss told me about it, I was at first surprised to see this in a Python application.  I’ve already been exposed to this kind of debugging thanks to Clojure, where it’s not uncommon to connect a REPL to your live application (for example, Heroku &lt;a href="https://devcenter.heroku.com/articles/debugging-clojure"&gt;document how to connect to a remote live REPL in your application&lt;/a&gt;).  When I first heard of that I was very skeptical (give access to a &lt;em&gt;live&lt;/em&gt; environment, and let the developer mess with the process ?!).  But I’ve learned to love it and I feel naked when I’m working in an environment where this is not available.  So I was happy to jump and take a look at that feature.&lt;/p&gt;

&lt;p&gt;Since it’s not very well documented and I had a hard time finding some information, let me share here the basics.&lt;/p&gt;

&lt;p&gt;First you’ll need to configure Carbon’s to allow the connection:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ini"&gt;&lt;span class="na"&gt;ENABLE_MANHOLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;True # by default it&amp;#39;s set to False&lt;/span&gt;
&lt;span class="na"&gt;MANHOLE_INTERFACE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="na"&gt;MANHOLE_PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;7222&lt;/span&gt;
&lt;span class="na"&gt;MANHOLE_USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
&lt;span class="na"&gt;MANHOLE_PUBLIC_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;your public SSH key, the string, not the path to the key&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now you can restart carbon, and connect to the Python shell with &lt;code&gt;ssh admin@127.0.0.1 -p7222&lt;/code&gt;.  This manhole is useful to get an idea of the data structure your process is handling, or to get an idea of what’s going on (is there a lot of keys being held in memory?  Is the queue size for one metric huge? etc).&lt;/p&gt;

&lt;p&gt;From here, you can execute Python code to examine the data of the process:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;carbon.cache&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MetricCache&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;MetricCache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;PROD.apps.xxx.yyy.zzz]&lt;/span&gt;
&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mf"&gt;1357861603.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;93800.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1357861613.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;98200.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1357861623.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;91900.0&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://github.com/graphite-project/carbon/blob/master/lib/carbon/cache.py#L19"&gt;&lt;code&gt;MetricCache&lt;/code&gt;&lt;/a&gt; class is a Python dictionary where you can access your keys.  You can also list all the metrics with the size of their queue with &lt;code&gt;MetricCache.counts()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Or even force the daemon to write to disk all the data points:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="python"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;carbon.writer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;writeCachedDataPoints&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;writeCachedDataPoints&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Before doing any of that, I would recommend to read the code of carbon.  It’s pretty short and quiet straight forward, especially the code of the &lt;a href="https://github.com/graphite-project/carbon/blob/master/lib/carbon/writer.py"&gt;writer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, you have to know what you’re doing when you’re executing code from a REPL in a live environment.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/Ljcb1IHIw5g" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/devops/2013/01/10/carbons-manhole.html</feedburner:origLink></entry>
 
 <entry>
   <title>About DevOps</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/06DxrqFZJiI/about-devops.html" />
   <updated>2012-12-16T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/devops/2012/12/16/about-devops</id>
   <content type="html">&lt;p&gt;There’s a lot of talk about what is or what is not DevOps, and I’ll
throw my opinion in the mix.&lt;/p&gt;

&lt;p&gt;Until a few weeks ago, at &lt;a href="http://saymedia.com"&gt;work&lt;/a&gt;, we had mostly
two teams: the engineering team and the ops team.  Our workflow was
(to simplify) the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;engineers develop services and applications&lt;/li&gt;
  &lt;li&gt;they push their change to Jenkins&lt;/li&gt;
  &lt;li&gt;a build pass and is pushed to CI&lt;/li&gt;
  &lt;li&gt;a few times a week, engineers ask Ops to push the change to
production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s already a lot of articles about the kind of frictions created
by this (who owns what; engineers would blame ops when the push was
failing (or the other way around); it’s hard for ops to know what’s
wrong when something is broken in production; etc).&lt;/p&gt;

&lt;p&gt;A few weeks ago it was decided to create a new team to improve
engineers efficiency, and the team was named “DevOps”.  At first I was
not sure it was the right name for this team, but now I don’t think it
matters.&lt;/p&gt;

&lt;p&gt;I was not sure the name was appropriate because of this 
&lt;a href="http://continuousdelivery.com/2012/10/theres-no-such-thing-as-a-devops-team/"&gt;article&lt;/a&gt;
(and a few other to respond), explaining why you don’t want a DevOps
team, but instead you want the whole organization to be DevOps.  We
need engineers to own their applications, to be able to push when they
want, but also to monitor, know what’s wrong or slow, etc.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;work&lt;/strong&gt; &lt;a href="https://github.com/hachi"&gt;hachi&lt;/a&gt; and I will have to do is to
help engineers and ops to &lt;em&gt;be&lt;/em&gt; the DevOps.  Our team responsibility is
to choose, evaluate and integrate tools.  We will also provide
libraries, documentation, training and support.  &lt;em&gt;We&lt;/em&gt; are not the
DevOps.  Our &lt;strong&gt;goals&lt;/strong&gt; are to create this culture, to give more
responsibilities to engineers, and to free Ops from the work of
pushing code.  The &lt;strong&gt;success&lt;/strong&gt; of this team will be measured by the
adoption of our work by engineers and ops.&lt;/p&gt;

&lt;p&gt;So yes, I agree that you don’t want a dedicated DevOps team, but you
still need a team coming from different background (hachi is coming
from Ops and I’m an engineer) to build that culture.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/06DxrqFZJiI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/devops/2012/12/16/about-devops.html</feedburner:origLink></entry>
 
 <entry>
   <title>Perl, Redis and AnyEvent at Craiglist</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/ilVKNBNUEFo/perl-redis-and-anyevent-at-craiglist.html" />
   <updated>2012-11-28T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/perl/2012/11/28/perl-redis-and-anyevent-at-craiglist</id>
   <content type="html">&lt;p&gt;Last night I went to the
&lt;a href="http://www.meetup.com/San-Francisco-Perl-Mongers/"&gt;SF.pm&lt;/a&gt; meetup,
hosted by Craiglist (thanks for the food!), where
&lt;a href="https://twitter.com/jzawodn"&gt;Jeremy Zawodny&lt;/a&gt; talked about
&lt;a href="http://redis.io"&gt;Redis&lt;/a&gt; and his module
&lt;a href="https://metacpan.org/module/AnyEvent::Redis::Federated"&gt;AnyEvent::Redis::Federated&lt;/a&gt;.
We were about 30 mongers.&lt;/p&gt;

&lt;p&gt;I was eating at the same table as Craiglist CTO’s, and he went through
some details of their infrastructure.  I was surprised by the quantity
of place where they use Perl, and the amount of traffic they deal with.&lt;/p&gt;

&lt;h2 id="redis"&gt;Redis&lt;/h2&gt;

&lt;p&gt;Jeremey started his talk by explaining what is their current problem:
they have hundred of hosts in multiple data center, and they collect
continuously dozen of metrics.  They looked at MySQL to store them,
but it was too slow to support the writes.  Another thing
important for them is that mostly only the most recent data matters.  They
want to know what’s going on &lt;em&gt;now&lt;/em&gt;, they don’t really care about the
past.&lt;/p&gt;

&lt;p&gt;So their goal is simple: they need something fast, &lt;em&gt;really&lt;/em&gt; fast, and
simple.  That’s where Redis enter the game.&lt;/p&gt;

&lt;p&gt;They want data replication, but
Redis don’t have this feature: there’s only a master/slave replication
mechanism (so, one way), and they need a solution with multi master,
where a node becoming master does not drop data. They address this
issue with a “syncer”, that I’ll describe later.&lt;/p&gt;

&lt;p&gt;Because Redis is single thread, and servers have multiple cores, they
start 8 process on each node to take advantages of them.&lt;/p&gt;

&lt;p&gt;To me, the main benefit of Redis over Memcached is that you can use
it as a data structure server.  If you only need something to store
key value, I’ll prefer to stick to memcached: the community around is
bigger, there’s a lot of well know patterns, and a lot of big
companies are contributing to it (lately, Twitter and FaceBook).&lt;/p&gt;

&lt;p&gt;The structure they use the most are the
&lt;a href="http://redis.io/commands#sorted_set"&gt;&lt;em&gt;sorted set&lt;/em&gt;&lt;/a&gt;.  The format to store a metric is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;key: &lt;code&gt;$time_period:$host:$metric&lt;/code&gt; (where the $timeperiod is
usually a day)&lt;/li&gt;
  &lt;li&gt;score: &lt;code&gt;$timestamp&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;value: &lt;code&gt;$timestamp:$value&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition of storing those metrics in the nodes, they also keep a
journal of what has changed.  The journal looks like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;score: &lt;code&gt;$timestamp&lt;/code&gt; of the last time something has changed&lt;/li&gt;
  &lt;li&gt;value: &lt;code&gt;$key&lt;/code&gt; that changed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The journal is only one big structure, and it’s used by their syncer
(more about that in a moment).  The benefit of having ZSET is that
they can delete old data easily by using the key (they don’t have
enough memory to store more than a couple of days, so they need to be
able to delete by day kickly).&lt;/p&gt;

&lt;p&gt;The journal is use for replication.  Each process has a syncer that
track all his peers, pull the data from those nodes and merge them
with the local data.  Earlier Jeremy mentioned that they have 8
instances on each node, so a the syncer from process 1 on node a will
only check for the process 1 on node b.&lt;/p&gt;

&lt;p&gt;He also mentioned a memory optimization done by Redis (you can read
more about that &lt;a href="http://redis.io/topics/memory-optimization"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id="anyeventredisfederated"&gt;AnyEvent::Redis::Federated&lt;/h2&gt;

&lt;p&gt;Now, it’s time to see the Perl code. &lt;code&gt;AnyEventE::Redis::Federated&lt;/code&gt; is
a layer on top of &lt;code&gt;AnyEvent::Redis&lt;/code&gt; that implements a consistent
hashing.  I guess now every body has gave up hope to see someday
&lt;a href="http://redis.io/topics/cluster-spec"&gt;redis cluster&lt;/a&gt; (and I’m more and
more convinced that hit should never be implemented, and let the
client implement their own solution for hashing / replication).&lt;/p&gt;

&lt;p&gt;Some of the nice feature of the modules:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;call chaining&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://metacpan.org/module/AnyEvent::Redis::Federated#SHARED-CONNECTIONS"&gt;you can get singleton object for the connection&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;you can also use it in blocking mode&lt;/li&gt;
  &lt;li&gt;query all node (where you send the same command to all the node,
   can be useful to do sanity check on the data)&lt;/li&gt;
  &lt;li&gt;the client will write to one node, and let the syncer do the job&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He then showed us some code (with a very gross example: &lt;code&gt;new
AnyEvent::Redis::Federated&lt;/code&gt;, I know at least
&lt;a href="http://search.cpan.org/perldoc?indirect"&gt;one person&lt;/a&gt; who would have
probably said something :).&lt;/p&gt;

&lt;h2 id="concerns"&gt;Concerns&lt;/h2&gt;

&lt;p&gt;The idea seems fine, but, as one person noted during the Q&amp;amp;A, how will
this scale when you have more than 2 or 4 nodes in your cluster ?
Since each process’ syncer need to talk to &lt;em&gt;all&lt;/em&gt; the other nodes, it
will probably be very expensive for this process to gather information
from all the nodes and write them.  Also, by adding more nodes, you’re
storing less information into each process, since you replicate
everything.  Maybe a good solution is to keep many small cluster of
2 to 4 nodes, and let each of them deal with some specific metrics.&lt;/p&gt;

&lt;p&gt;The module is not yet used in production, but they’ve tested it
heavily, in a lot of conditions (but I would note that there’s no unit
test :).  They intent to use it soon with some
home made dashboard to display the metrics.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/ilVKNBNUEFo" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/perl/2012/11/28/perl-redis-and-anyevent-at-craiglist.html</feedburner:origLink></entry>
 
 <entry>
   <title>Where we talk about ansible and chef</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/eA1kVq1FvIU/ansible-and-chef.html" />
   <updated>2012-11-27T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/devops/2012/11/27/ansible-and-chef</id>
   <content type="html">&lt;p&gt;I’ve been using &lt;a href="http://www.opscode.com/chef/"&gt;Chef&lt;/a&gt; for some time now, but it was always via &lt;a href="http://vagrantup.com"&gt;Vagrant&lt;/a&gt;,
so a few weeks ago I decided to get more familiar with it.  A friend
of mine had set up a Chef server for his own use and was OK to let me use
it for my personal server.  There was a four days weekend for Thanksgiving
coming, so it was the perfect occasion to take a better look at it,
and to re-install my Linode server with Chef.  And since it was a
really long weekend, I also decided to take a look at &lt;a href="http://ansible.cc"&gt;ansible&lt;/a&gt;, another
tool to push stuff to your server.&lt;/p&gt;

&lt;p&gt;I’m not going to talk about installation, configuration, set up and
all that kind of stuff, there’s enough material available around (blog
posts, articles, books, etc).  Instead, I will talk about my
experience and share my (very valuable) opinion (because, clearly, the
world deserve to know what I think).&lt;/p&gt;

&lt;h2 id="writing-cookbooks-for-chef"&gt;Writing cookbooks for Chef&lt;/h2&gt;

&lt;p&gt;For the few of you who don’t know, cookbooks, in Chef’s world, are a
group of files (templates, static files) and code that are used to
automate your infrastructure.  Usually, you’ll create a cookbook for
each of your application (one for nginx, one for MySQL, etc).&lt;/p&gt;

&lt;p&gt;I’ve a few services on my server (git, gitolite, Jenkins, graphite,
collectd, phabricator, …), and I wanted a coobook for each of them.
I’ve started by looking for the one already existing (there’s a lot of
them on GitHub, on the
&lt;a href="https://github.com/opscode-cookbooks/"&gt;opscode’s account&lt;/a&gt;), and I tried to use
them without any modification.  Usually, a cookbook will let you set
some configuration details in your role or node to override the
defaults it provides (like
the password for MySQL, or the path where to put logs).  So what I did
was to set the interesting cookbook as a git submodule in my cookbook
repository.  Unfortunately, for almost all of them, I had to give up
and import them in the repo, so I could edit and modify them.&lt;/p&gt;

&lt;p&gt;That’s probably my biggest complaint with cookbooks: I doubt code
re-usability is possible.  You can use a cookbook as a base for your
own version, but either they are too generic; or sometimes you need a
workaround; or they do way too many things. And as a result, you need to edit the
code to make them behave the way you want.&lt;/p&gt;

&lt;p&gt;In my opinion, developers/ops should just publish &lt;a href="http://docs.opscode.com/essentials_cookbook_lwrp.html"&gt;LWRP&lt;/a&gt; (Lightweight
Resources and Providers) and templates, that’s the only thing that I
can see as really re-usable (take a look at
&lt;a href="https://github.com/dagolden/perl-chef"&gt;perl-chef&lt;/a&gt;, I think that this one is a good
example).&lt;/p&gt;

&lt;h2 id="using-ansible"&gt;Using ansible&lt;/h2&gt;

&lt;p&gt;ansible was a new tool for me.  A few friends mentionned it to me last
October when I was at the &lt;a href="http://osdc.fr"&gt;OSDC.fr&lt;/a&gt; and it was also suggested to me by a
colleague at work.&lt;/p&gt;

&lt;p&gt;This tool is definitely less known that Chef, so I’ll give a quick
introduction.  In ansible world, you write “playbooks”, which are the
orchestration language for the tool.  That sounds very similar with
Chef, but the main difference is they are not actual code, but a
scenario with actions.&lt;/p&gt;

&lt;p&gt;On the web site of the project, there’s a quote saying:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You can get started in minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and for once, that’s true.  I only had to read the first page of the
documentation, and I was able to write a very simple playbook that I
was able to evolve very quickly to do something actually useful.&lt;/p&gt;

&lt;p&gt;Another difference with Chef is that they don’t incite you to share
your playbooks, but instead to share your modules.  Modules could be
compared to Chef’s LWRP.  They are Python code to do something
specific (like the &lt;a href="http://ansible.cc/docs/modules.html#pip"&gt;&lt;code&gt;pip&lt;/code&gt;&lt;/a&gt; module, to install Python package, or the
&lt;a href="http://ansible.cc/docs/modules.html#template"&gt;&lt;code&gt;template&lt;/code&gt;&lt;/a&gt;’s one).&lt;/p&gt;

&lt;h2 id="chef-vs-ansible"&gt;Chef vs Ansible&lt;/h2&gt;

&lt;p&gt;For now, I’ve decided to stick to this: use Chef for my supporting
application (nginx, MySQL, etc) and ansible for my own applications.&lt;/p&gt;

&lt;p&gt;So far, I prefer ansible to Chef.  There’s definitely less available
material about ansible on the net, but the quality is better, and the
main documentation is very (I insist on the &lt;em&gt;very&lt;/em&gt;) well organized.  I’ve never spend more than
10 minutes looking for something and to implement it.  I can’t say
the same with Chef: the wiki is confusing; there’s way too many
cookbooks available; their quality is very disparate.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/eA1kVq1FvIU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/devops/2012/11/27/ansible-and-chef.html</feedburner:origLink></entry>
 
 <entry>
   <title>Two tech. talks in a day</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/3MJ51EDncg0/two-tech-talks-in-a-day.html" />
   <updated>2012-11-14T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/talk/2012/11/14/two-tech-talks-in-a-day</id>
   <content type="html">&lt;p&gt;Today I assisted to two tech. talks.  One of them was our &amp;#8220;Reading Group&amp;#8221; session at lunch and the second one was the Python meetup tonight.&lt;/p&gt;
&lt;h2&gt;SAY&amp;#8217;s tech talk&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;m trying to organize at &lt;a href="http://saymedia.com"&gt;work&lt;/a&gt;, every two weeks during lunch time, a session where engineers can discuss about an article, tool, or paper they find interesting.  Today we were a very small group (only 4 peoples), and we talked about two tools that &lt;a href="http://sekimura.typepad.com/blog/"&gt;Masa&lt;/a&gt; wanted to explore: &lt;a href="https://github.com/cookpad/kage"&gt;Kage&lt;/a&gt; and &lt;a href="http://www.igvita.com/2012/08/28/web-performance-power-tool-http-archive-har/"&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Archive&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Kage&lt;/h3&gt;
&lt;p&gt;We talked about Kage first (kah-geh means &amp;#8220;shadow&amp;#8221; in Japanese).  Masa started to explain what was the goal of the tool and how it works.  Basically, it&amp;#8217;s a proxy that will send your &lt;span class="caps"&gt;HTTP&lt;/span&gt; request to your production and stage environment.  The basic &lt;a href="https://github.com/cookpad/kage/blob/master/examples/proxy.rb"&gt;example&lt;/a&gt; show how easy it is to write a simple proxy with a few rules to dispatch only your &lt;span class="caps"&gt;GET&lt;/span&gt; request to your two environments, and then compare the payload returned.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s using &lt;a href="https://github.com/igrigorik/em-proxy/"&gt;em-proxy&lt;/a&gt; which is a &lt;span class="caps"&gt;DSL&lt;/span&gt; to write proxy for EventMachine.  We then discussed where we could use it in our architecture and what benefit we could get from it, but for now we don&amp;#8217;t have any plan to use it.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;HAR&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Then the second thing we talked about what &lt;span class="caps"&gt;HAR&lt;/span&gt;.  You can find more detailed information on &lt;a href="http://www.igvita.com/2012/08/28/web-performance-power-tool-http-archive-har/"&gt;Ilya&amp;#8217;s blog&lt;/a&gt; and on this &lt;a href="https://gist.github.com/3500508"&gt;gist&lt;/a&gt;.  To summarize, &lt;span class="caps"&gt;HAR&lt;/span&gt; is an &lt;span class="caps"&gt;HTTP&lt;/span&gt; archive &lt;a href="http://www.softwareishard.com/blog/har-12-spec/"&gt;format&lt;/a&gt;.  When you use the developers tools in Chrome, you can see the request and their response time, but you can also save this information in the &lt;span class="caps"&gt;HAR&lt;/span&gt; format.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a few tools then to analyse this data, like YSlow, or browse them with the HARviewer.  Another interesting thing is that you don&amp;#8217;t have to use a browser to get them, you can use &lt;a href="http://phantomjs.org"&gt;Phantomjs&lt;/a&gt;.  Masa and Kyle talked about it and if they could use that with Nagios, or with Jenkins to measure the response time.&lt;/p&gt;
&lt;h2&gt;SF Python Meetup&lt;/h2&gt;
&lt;p&gt;The last talk of the day was the &lt;a href="http://www.meetup.com/sfpython/"&gt;SF Python Meetup&lt;/a&gt; after a 4 or 5 months break, at the Yelp headquarter.  We were supposed to have some lightning talks to start, but we only had one, from someone who think that &amp;#8220;lightning talk&amp;#8221; means &amp;#8220;publicity for Google and ho by the way, we&amp;#8217;re hiring&amp;#8221; (yeah like no one in the room knew that &amp;#8230;).&lt;/p&gt;
&lt;p&gt;Then David Schachter presented &lt;a href="http://www.rtortell.com/SF_Python_Meetup_slides_public.pdf"&gt;How to Speed Up A Python Program 114,000 times&lt;/a&gt;.  He showed us how he improved the performance of a script by 114,000 times.  I will start by saying the talk was interesting and that David was an entertaining speaker.  He went through some optimization he used, like using multiprocessing modules, &lt;a href="http://cython.org"&gt;cython&lt;/a&gt;, and some more difficult optimization he was not able to get from cython (like the permuted vector code).&lt;/p&gt;
&lt;p&gt;He had a very strong opinion about cluster and I really disagree with him.  One of his complains was that cluster are hard, are young, and we don&amp;#8217;t have any tools, so we should not use them.  But we&amp;#8217;ve been using cluster in universities and laboratories for years now.  Even if the tools are still not very great, they exist, and they work.  And more importantly to me, the fact that he spend 12 weeks on optimizing his program, and doing stuff that I would not be able to do, he proved that optimizing is &lt;strong&gt;also&lt;/strong&gt; very hard, and that doesn&amp;#8217;t seem easier to me that using a cluster.&lt;/p&gt;
&lt;p&gt;All in all, that was a good day, and I learned new things.  Now I need to find a subject for our next reading group session.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/3MJ51EDncg0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/talk/2012/11/14/two-tech-talks-in-a-day.html</feedburner:origLink></entry>
 
 <entry>
   <title>Virtualenv and checkouts</title>
   <link href="http://feedproxy.google.com/~r/ImALumberjaph/~3/awIkvpIKUX4/virtualenv-and-checkouts.html" />
   <updated>2012-10-31T00:00:00+00:00</updated>
   <id>http://lumberjaph.net/python/2012/10/31/virtualenv-and-checkouts</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve started to do some Clojure in my spare time.  The default tool adopted by the community to manage projects is &lt;a href="http://leiningen.org"&gt;leiningen&lt;/a&gt;.  For those of you who don&amp;#8217;t know what &lt;code&gt;lein&lt;/code&gt; is, it&amp;#8217;s a tool to automate your Clojure project: it will boostrap a new project, install the dependencies, and there&amp;#8217;s a plugin mechanism to extend the default possibilities of the tool.&lt;/p&gt;
&lt;p&gt;One of the nice feature of the tool is the &lt;strong&gt;checkouts/&lt;/strong&gt; directory.  From the &lt;a href="https://github.com/technomancy/leiningen/blob/preview/doc/FAQ.md"&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you create a directory named checkouts in your project root and symlink some other project roots into it, Leiningen will allow you to hack on them in parallel.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For Python projects at &lt;a href="http://www.saymedia.com/careers"&gt;$work&lt;/a&gt; I use &lt;a href="http://virtualenvwrapper.readthedocs.org/en/latest/"&gt;virtualenvwrapper&lt;/a&gt; to easily work on them without having to deal with conflicting dependencies.  When I need to change a library that is used by one of the project, usually I go to the virtualenv directory and create a symlink so it  uses the one I&amp;#8217;m editing.&lt;/p&gt;
&lt;p&gt;What I really want is a mechanism similar to &lt;code&gt;lein&lt;/code&gt;, where I can have a &lt;strong&gt;checkouts/&lt;/strong&gt; directory inside the main project, where I can clone a library or create a symlink. Since &lt;code&gt;virtualenvwrapper&lt;/code&gt; provides a hook mechanism, I wrote a small hook inside &lt;code&gt;~/.virtualenvs/postactivate&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# move to the directory of the project&lt;/span&gt;
&lt;span class="nv"&gt;proj_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;|awk -F&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{print $NF}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;proj_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/vagrant/src/&lt;span class="nv"&gt;$proj_name&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$proj_path&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -d checkouts &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="k"&gt;    for &lt;/span&gt;ext in &lt;span class="k"&gt;$(&lt;/span&gt;ls checkouts&lt;span class="k"&gt;)&lt;/span&gt;; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;proj_path/checkouts/&lt;span class="nv"&gt;$ext&lt;/span&gt;:&lt;span class="nv"&gt;$PYTHONPATH&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then, when I type &lt;code&gt;workon $project_name&lt;/code&gt; in my shell, the environment is activated, I&amp;#8217;m moved to the right directory, and the library inside the &lt;strong&gt;checkouts/&lt;/strong&gt; directory are added to my &lt;code&gt;PYTHONPATH&lt;/code&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ImALumberjaph/~4/awIkvpIKUX4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://lumberjaph.net/python/2012/10/31/virtualenv-and-checkouts.html</feedburner:origLink></entry>
 
 
</feed>
