<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Monitoring on Dieter&#39;s blog</title>
    <link>https://dieter.plaetinck.be/tags/monitoring/</link>
    <description>Recent content in Monitoring on Dieter&#39;s blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Sat, 10 Dec 2016 19:13:03 +0000</lastBuildDate><atom:link href="https://dieter.plaetinck.be/tags/monitoring/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Practical fault detection: redux. Next-generation alerting now as presentation</title>
      <link>https://dieter.plaetinck.be/posts/practical-fault-detection-redux-next-generation-alerting-now-as-presentation/</link>
      <pubDate>Sat, 10 Dec 2016 19:13:03 +0000</pubDate>
      
      
      <guid>http://dieter.plaetinck.be/post/practical-fault-detection-redux-next-generation-alerting-now-as-presentation/</guid>
      
      
      <description>&lt;p&gt;This summer I had the opportunity to present my &lt;a href=&#34;https://dieter.plaetinck.be/post/practical-fault-detection-alerting-dont-need-to-be-data-scientist/&#34;&gt;practical fault detection&lt;/a&gt; concepts and &lt;a href=&#34;https://dieter.plaetinck.be/posts/practical-fault-detection-on-timeseries-part-2/&#34;&gt;hands-on approach&lt;/a&gt; as conference presentations.&lt;/p&gt;
&lt;p&gt;First at &lt;a href=&#34;http://conferences.oreilly.com/velocity/vl-ca-2016/public/schedule/detail/49335&#34;&gt;Velocity&lt;/a&gt; and then at &lt;a href=&#34;https://www.usenix.org/conference/srecon16europe/program/presentation/plaetinck&#34;&gt;SRECon16 Europe&lt;/a&gt;.  The latter page also contains the recorded video.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dieter.plaetinck.be/files/poor-mans-fault-detection.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested at all in tackling non-trivial timeseries alerting use cases (e.g. working with seasonal or trending data) this video should be useful to you.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s basically me trying to convey in a concrete way why I think the big-data and math-centered algorithmic approaches come with a variety of problems making them unrealistic and unfit,
whereas the real breakthroughs happen when tools recognize the symbiotic relationship between operators and software, and focus on supporting a collaborative, iterative process to managing alerting over time. There should be a harmonious relationship between operator and monitoring tool, leveraging the strengths of both sides, with minimal factors harming the interaction.
From what I can tell, &lt;a href=&#34;http://bosun.org/&#34;&gt;bosun&lt;/a&gt; is pioneering this concept of a modern alerting IDE and is far ahead of other alerting tools in terms of providing high alignment between alerting configuration, the infrastructure being monitored, and individual team members, which are all moving targets, often even fast moving.  In my experience this results in high signal/noise alerts and a happy team.
(according to Kyle, the bosun project leader, my take &lt;a href=&#34;https://twitter.com/kylembrandt/status/804409406846746624&#34;&gt;is a useful one&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;That said, figuring out the tool and using it properly has been, and remains, rather hard.  I know many who rather not fight the learning curve.  Recently the bosun team has been making strides at making it easier for newcomers -
e.g. &lt;a href=&#34;https://github.com/bosun-monitor/bosun/pull/1817&#34;&gt;reloadable configuration&lt;/a&gt; and &lt;a href=&#34;https://grafana.net/plugins/bosun-app&#34;&gt;Grafana integration&lt;/a&gt; - but there is lots more to do.
Part of the reason is that some of the UI tabs aren&amp;rsquo;t implemented for non-opentsdb databases and integrating Graphite for example into the tag-focused system that is bosun, is bound to be a bit weird.  (that&amp;rsquo;s on me)&lt;/p&gt;
&lt;p&gt;For an interesting juxtaposition, we released &lt;a href=&#34;http://docs.grafana.org/guides/whats-new-in-v4/&#34;&gt;Grafana v4 with alerting functionality&lt;/a&gt; which approaches the problem from the complete other side: simplicity and a unified dashboard/alerting workflow first, more advanced alerting methods later.  I&amp;rsquo;m doing what I can to make the ideas of both projects converge, or at least make the projects take inspiration from each other and combine the good parts. (just as I hope to bring the ideas behind &lt;a href=&#34;http://vimeo.github.io/graph-explorer/&#34;&gt;graph-explorer&lt;/a&gt; into Grafana, eventually&amp;hellip;)&lt;/p&gt;
&lt;p&gt;Note:
One thing that somebody correctly pointed out to me, is that I&amp;rsquo;ve been inaccurate with my terminology.
Basically, machine learning and anomaly detection can be as simple or complex as you want to make it. In particular, what we&amp;rsquo;re doing with our alerting software (e.g. bosun) can rightfully also be considered machine learning, since we construct models that learn from data and make predictions.  It may not be what we think of at first, and indeed, even a simple linear regression is a machine learning model.  So most of my critique was more about the big data approach to machine learning, rather than machine learning itself.  As it turns out then the key to applying machine learning successfully is tooling that assists the human operator in every possible way, which is what IDE&amp;rsquo;s like bosun do and how I should have phrased it, rather than presenting it as an alternative to machine learning.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>25 Graphite, Grafana and statsd gotchas</title>
      <link>https://dieter.plaetinck.be/posts/25-graphite-grafana-statsd-gotchas/</link>
      <pubDate>Tue, 15 Mar 2016 16:22:03 +1000</pubDate>
      
      
      <guid>http://dieter.plaetinck.be/post/25-graphite-grafana-statsd-gotchas/</guid>
      
      
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;This is a crosspost of &lt;a href=&#34;https://blog.raintank.io/25-graphite-grafana-and-statsd-gotchas/&#34;&gt;an article I wrote on the raintank.io blog&lt;/a&gt;&lt;br&gt;
For several years I&amp;rsquo;ve worked with Graphite, Grafana and statsd on a daily basis and have been participating in the community.  All three are fantastic tools and solve very real problems.  Hence my continued use and recommendation.  However, between colleagues, random folks on irc, and personal experience, I&amp;rsquo;ve seen a plethora of often subtle issues, gotchas and insights, which today I&amp;rsquo;d like to share.&lt;/p&gt;
&lt;p&gt;I hope this will prove useful to users while we, open source monitoring developers, work on ironing out these kinks.  At raintank we&amp;rsquo;re addressing a bunch of these as well but we have a long road ahead of us.
&lt;br&gt;
Before we begin, when trying to debug what&amp;rsquo;s going on with your metrics (whether they&amp;rsquo;re going in or out of these tools), don&amp;rsquo;t be afraid to dive into the network or the whisper files. They can often be invaluable in understanding what&amp;rsquo;s up.&lt;/p&gt;
&lt;p&gt;For network sniffing, I almost always use these commands:&lt;br&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ngrep -d any -W byline port &lt;span style=&#34;color:#ae81ff&#34;&gt;2003&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# carbon traffic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ngrep -d any -W byline port &lt;span style=&#34;color:#ae81ff&#34;&gt;8125&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# statsd traffic&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Getting the json output from Graphite (just append &lt;code&gt;&amp;amp;format=json&lt;/code&gt;) can be very helpful as well. Many dashboards, including &lt;a href=&#34;http://www.grafana.org&#34;&gt;Grafana&lt;/a&gt; already do this, so you can use the browser network inspector to analyze requests. For the whisper files, Graphite comes with various useful utilities such as whisper-info, whisper-dump, whisper-fetch, etc.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;here we go:&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;1-omg-did-all-our-traffic-just-drop&#34;&gt;1. OMG! Did all our traffic just drop?&lt;/h3&gt;
&lt;p&gt;Probably the most common gotcha, and one i run into periodically. Graphite will return data up until the current time, according to your data schema.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; if your data is stored at 10s resolution, then at 10:02:35, it will show
data up until 10:02:30. Once the clock hits 10:02:40, it will also include that point (10:02:40) in its response.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;It typically takes some time for your services to send data for that timestamp, and for it to be processed by Graphite, so Graphite will typically return a null here for that timestamp. Depending on how you visualize (see for example the &amp;ldquo;null as null/zero&amp;rdquo; option in grafana), or if you use a function such as sumSeries (see below) it may look like a drop in your graph, and cause panic.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can work around this with &amp;ldquo;null as null&amp;rdquo; in Grafana, transformNull() or keepLastValue() in Graphite, or plotting until a few seconds ago instead of now. See below for some other related issues.&lt;/p&gt;
&lt;h3 id=&#34;2-null-handling-in-math-functions&#34;&gt;2. Null handling in math functions&lt;/h3&gt;
&lt;p&gt;Graphite functions don&amp;rsquo;t exactly follow the rules of logic (by design). When you request something like &lt;code&gt;sumSeries(diskspace.server_*.bytes_free)&lt;/code&gt; Graphite returns the sum of all bytes_free&amp;rsquo;s for all your servers, at each point in time. If all of the servers have a null for a given timestamp, the result will be null as well for that time. However, if only some - but not all - of the terms are null, they are counted as 0.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; The sum for a given point in time, 100 + 150 + null + null = 250.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;So when some of the series have the
occasional null, it may look like a drop in the summed series. This especially commonly happens for the last point at each point in time, when your servers don&amp;rsquo;t submit their metrics at the exact same time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now let&amp;rsquo;s say you work for a major video sharing website that runs many upload and transcoding clusters around the world. And let&amp;rsquo;s also say you build this really cool traffic routing system that sends user video uploads to the most appropriate cluster, by taking into account network speeds, transcoding queue wait times, storage cluster capacity (summed over all servers), infrastructure cost and so forth.  Building this on top of Graphite would make a lot of sense, and in all testing everything works fine, but in production the decisions made by the algorithm seem nonsensical, because the storage capacity seems to fluctuate all over the place.   Let&amp;rsquo;s just say that&amp;rsquo;s  how a certain Belgian engineer became intimately familiar with Graphite&amp;rsquo;s implementation of functions such as sumSeries.  Lesson learned.  No videos were hurt.&lt;/p&gt;
&lt;p&gt;Graphite could be changed to strictly follow the rules of logic, meaning as soon as there&amp;rsquo;s a null in an equation, emit a null as output. But a low number of nulls in a large sum is usually not a big deal and having a  result with the nulls counted as 0 can be more useful than no result at all. Especially when averaging, since those points can typically be safely excluded  without impact on the output. Graphite has the xFilesFactor option in storage-aggregation.conf, which lets you configure the minimum fraction of non-null values, which it uses during storage aggregation (rollups) to determine whether the input is sufficiently known for output to be known, otherwise the output value will be null.&lt;/p&gt;
&lt;p&gt;It would be nice if these on-demand math requests would take an xFilesFactor argument to do the same thing. But for now, just be aware of it, not using the last point is usually all you need if you&amp;rsquo;re only looking at the most recent data. Or get the timing of your agents tighter and only request data from Graphite until now=-5s or so.&lt;/p&gt;
&lt;div class=&#34;chroma&#34;&gt;
&lt;strong&gt;INTERMEZZO:&lt;/strong&gt;
At this point we should describe the many forms of consolidation; a good understanding of this is required for the next points.
&lt;br/&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;storage consolidation aka aggregation, aka rollups&lt;/strong&gt;: data aggregated to optimize the cost of historical archives and make it faster to return large timeframes of data. Driven by storage-aggregation.conf&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;&lt;strong&gt;runtime consolidation&lt;/strong&gt;: when you want to render a graph but there are more datapoints than pixels for the graph, or more than the maxDataPoints setting. Graphite will reduce the data in the http response. Averages by default, but can be overridden through consolidateBy()&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;&lt;strong&gt;Grafana consolidation&lt;/strong&gt;: Grafana can visualize stats such as min/max/avg which it computes on the data returned by your timeseries system.&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;&lt;strong&gt;statsd consolidation&lt;/strong&gt;: statsd is also commonly used to consolidate usually very high rates of irregular incoming data in properly spaced timeframes, before it goes into Graphite.&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;Unlike all above mechanisms which work per series,
the &lt;a href=&#34;http://graphite.readthedocs.org/en/1.0/functions.html#graphite.render.functions.sumSeries&#34;&gt;sumSeries()&lt;/a&gt;, &lt;a href=&#34;http://graphite.readthedocs.org/en/1.0/functions.html#graphite.render.functions.averageSeries&#34;&gt;saverageSeries()&lt;/a&gt;, &lt;a href=&#34;http://graphite.readthedocs.org/en/1.0/functions.html#graphite.render.functions.groupByNode&#34;&gt;groupByNode()&lt;/a&gt; Graphite functions work
across series. They merge multiple series into a single or fewer series by aggregating  
points from different series at each point in time.&lt;/li&gt;
&lt;br/&gt;
&lt;li&gt;And then there&#39;s &lt;a href=&#34;http://graphite.readthedocs.org/en/latest/carbon-daemons.html#carbon-aggregator-py&#34;&gt;carbon-aggregator&lt;/a&gt; and &lt;a href=&#34;https://github.com/graphite-ng/carbon-relay-ng&#34;&gt;carbon-relay-ng&lt;/a&gt; which operate on your metrics stream and can aggregate on per-series level, as well as across series, as well as a combination thereof.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&#34;3-null-handling-during-runtime-consolidation&#34;&gt;3. Null handling during runtime consolidation&lt;/h3&gt;
&lt;p&gt;Similar to above, when Graphite performs runtime consolidation it simply ignores null values. Imagine a series that measures throughput with points 10, 12, 11, null, null, 10, 11, 12, 10. Let&amp;rsquo;s say it needs to aggregate every 3 points with sum. this would return 33, 10, 33. This will visually look like a drop in throughput, even though there probably was none.&lt;/p&gt;
&lt;p&gt;For some functions like avg, a missing value amongst several valid values is usually not a big deal, but the likeliness of it becoming a big deal increases with the amount of nulls, especially with sums. For runtime consolidation, Graphite needs something similar to the xFilesFactor setting for rollups.&lt;/p&gt;
&lt;h3 id=&#34;4-no-consolidation-or-aggregation-for-incoming-data&#34;&gt;4. No consolidation or aggregation for incoming data&lt;/h3&gt;
&lt;p&gt;If you submit multiple values into Graphite for the same interval, the last one overwrites any previous values, no consolidation/aggregation happens in this scenario.&lt;/p&gt;
&lt;p&gt;Never send multiple values for the same interval. However, carbon-aggregator or carbon-relay-ng may be of help (see above)&lt;/p&gt;
&lt;h3 id=&#34;5-limited-storage-aggregation-options&#34;&gt;5. Limited storage aggregation options&lt;/h3&gt;
&lt;p&gt;In storage-aggregation.conf you configure which function to use for historical rollups. It can be limiting that you can only choose one. Often you may want to retain both the max values as well as the averages for example.(very useful for throughput). This feature exists in &lt;a href=&#34;http://oss.oetiker.ch/rrdtool/&#34;&gt;RRDtool&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another issue with this is that often these functions will be misconfigured. Make sure to think about all the possible metrics you&amp;rsquo;ll be sending (e.g. min and max values through statsd) and set up the right configuration for them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://blog.librato.com/posts/time-series-data&#34;&gt;Proprietary systems tend to be more flexible&lt;/a&gt; and I&amp;rsquo;m sure it will make a come back in the Graphite stack as well. (more on that later)&lt;/p&gt;
&lt;h3 id=&#34;6-runtime-consolidation-is-detached-from-storage-aggregation&#34;&gt;6. Runtime consolidation is detached from storage aggregation&lt;/h3&gt;
&lt;p&gt;The function chosen in storage-aggregation.conf is only used for rollups.&lt;/p&gt;
&lt;p&gt;If Graphite performs any runtime consolidation it will always use average unless told otherwise through consolidateBy.  This means it&amp;rsquo;s easy to run into cases where data is rolled up (in whisper) using, say, max or count,  but then accidentally with average while creating your visualization, resulting in incorrect information and nonsensical charts. Beware!&lt;/p&gt;
&lt;p&gt;It would be nice if the configured roll-up function would also apply here (and also the xFilesFactor, as above),
For now, just be careful :)&lt;/p&gt;
&lt;h3 id=&#34;7-grafana-consolidation-is-detached-from-storage-aggregation-and-runtime-consolidation&#34;&gt;7. Grafana consolidation is detached from storage aggregation and runtime consolidation&lt;/h3&gt;
&lt;p&gt;Like mentioned earlier, Grafana can provide min/max/avg/&amp;hellip; values from the received data. For now, it just computes these from the received data, which may already have been consolidated (twice: in storage and in runtime) using different functions, so these results may not be always representative. (&lt;a href=&#34;http://play.grafana.org/dashboard/db/ultimate-graphite-query-guide&#34;&gt;more info&lt;/a&gt;) We will make this mechanism more powerful and accurate.&lt;/p&gt;
&lt;h3 id=&#34;8-aggregating-percentiles&#34;&gt;8. Aggregating percentiles&lt;/h3&gt;
&lt;p&gt;The pet peeve of many, it has been written about a lot: If you have percentiles, such as those collected by statsd, (e.g. 95th percentile response time for each server) there is in theory no proper way to aggregate those numbers.&lt;/p&gt;
&lt;p&gt;This issue appears when rolling up the data in the storage layer, as well when doing runtime consolidation, or when  trying to combine the data for all servers (multiple series) together. There is real math behind this, and I&amp;rsquo;m not going into it because in practice it actually doesn&amp;rsquo;t seem to matter much. If you&amp;rsquo;re trying to spot issues or alert on outliers you&amp;rsquo;ll get quite far with averaging the data together or taking the max value seen. This is especially true when the amount of requests, represented by each latency measurement, is in the same order of magnitude.  E.g. You&amp;rsquo;re averaging per-server latency percentiles and your servers get a similar load or you&amp;rsquo;re averaging multiple points in time for one server, but there was a similar load at each point.  You can always set up a separate alerting rule for unbalanced servers or drops in throughput.  As we&amp;rsquo;ll see in some of the other points, taking sensible shortcuts instead of obsessing over math is often the better way to accomplish your job of operating your infrastructure or software.&lt;/p&gt;
&lt;h3 id=&#34;9-deriving-and-integration-in-graphite&#34;&gt;9. Deriving and integration in Graphite&lt;/h3&gt;
&lt;p&gt;The Graphite documentation for &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/functions.html#graphite.render.functions.derivative&#34;&gt;derivative()&lt;/a&gt; hints at this already (&amp;ldquo;This function does not normalize for periods of time, as a true derivative would.&amp;rdquo;), but to be  entirely clear:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Graphite&#39;s &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/functions.html#graphite.render.functions.derivative&#34;&gt;derivative&lt;/a&gt; is not a derivative. A &lt;a href=&#34;https://en.wikipedia.org/wiki/Derivative&#34;&gt;derivative&lt;/a&gt; divides difference in value by difference in time.  Graphite&#39;s derivative just returns the value deltas. Similar for &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/functions.html#graphite.render.functions.nonNegativeDerivative&#34;&gt;nonNegativeDerivative()&lt;/a&gt;.  If you want an actual derivative, use the somewhat awkwardly named &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/functions.html#graphite.render.functions.perSecond&#34;&gt;perSecond()&lt;/a&gt; function.&lt;/li&gt;
&lt;li&gt;Graphite&#39;s integral is not an integral either. An &lt;a href=&#34;https://en.wikipedia.org/wiki/Integral&#34;&gt;integral sums the multiplications of the value difference with the time span&lt;/a&gt;.  &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/functions.html#graphite.render.functions.integral&#34;&gt;Graphite&#39;s integral&lt;/a&gt; just adds up the value differences.  To my knowledge there&#39;s no proper way to do an actual integral, but luckily this is an uncommon operation anyway. Note also that Graphite&#39;s integral just skips null values, so a value at each  point in time can be lower than it should, due to nulls that preceded it.&lt;/li&gt;
&lt;/ul&gt;
Maybe for a future stable Graphite release this can be reworked.  for now, just something to be aware of.  
&lt;h3 id=&#34;10-graphite-quantization&#34;&gt;10. Graphite quantization&lt;/h3&gt;
&lt;p&gt;We already saw in the consolidation paragraph that for multiple points per interval, last write wins. But you should also know that any data point submitted gets the timestamp rounded down.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: You record points every 10 seconds but submit a point with timestamp at 10:02:59, in Graphite this will be stored at 10:02:50. To be more precise if you submit points at 10:02:52, 10:02:55 and 10:02:59, and have 10s resolution, Graphite will pick the point from 10:02:59 but store it at 10:02:50. So it&amp;rsquo;s important that you make sure to submit points at consistent intervals, aligned to your Graphite retention intervals (e.g. if every 10s, submit on timestamps divisible by 10)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;11-statsd-flush-offset-depends-on-when-statsd-was-started&#34;&gt;11. Statsd flush offset depends on when statsd was started&lt;/h3&gt;
&lt;p&gt;Statsd lets you configure a flushInterval, i.e. how often it should compute the output stats and submit them to your backend. However, the exact timing is pretty arbitrary and depends on when statsd is  started.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: If you start statsd at 10:02:00 with a flushInterval of 10, then it
will emit values with timestamps at 10:02:10, 10:02:20, etc (this is what you want), but if you happened to start it at 10:02:09 then it will submit values with timestamps 10:02:19, 10:02:29, etc. So typically, the values sent by statsd are subject to Graphite&amp;rsquo;s quantization and are moved into the past.  In the latter example, by 9 seconds.  This can make troubleshooting harder, especially when comparing statsd metrics to metrics from a different service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: &lt;a href=&#34;https://github.com/vimeo/statsdaemon&#34;&gt;vimeo/statsdaemon&lt;/a&gt; (and possibly other servers as well) will always submit values at quantized intervals  so that it&amp;rsquo;s guaranteed to map exactly to Graphite&amp;rsquo;s timestamps as long as the interval is correct.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;12-improperly-time-attributed-metrics&#34;&gt;12. Improperly time-attributed metrics&lt;/h3&gt;
&lt;p&gt;You don&amp;rsquo;t tell statsd the timestamps of when things happened.  Statsd applies its own timestamp when it flushes the data. So this is prone to various (mostly network) delays. This could result in a metric being generated in a certain interval only arriving in statsd after the next interval has started. But it can get worse.  Let&amp;rsquo;s say you measure how long it takes to execute a query on a database server. Typically it takes 100ms but let&amp;rsquo;s say now many queries are taking 60s, and you have a flushInterval of 10s. Note that the metric is only sent after the full query has completed. So during the full minute where queries were slow, there are no  metrics (or only some metrics that look good, they came through cause they were part of a group of queries that managed to execute timely), and only after a minute do you get the stats that reflect queries  spawned a minute ago. The higher a timing value, the higher the attribution error, the more into the past the values it represents and the longer the issue will go undetected or invisible.&lt;/p&gt;
&lt;p&gt;Keep in mind that other things, such as garbage collection cycles or paused goroutines under cpu saturation may also delay your metrics reporting. Also watch out for the queries aborting all together, causing the metrics never to be sent and these faults to be invisble! Make sure you properly monitor throughput and the functioning (timeouts, errors, etc) of the service from the client perspective, to get a more accurate picture.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note that many instrumentation libraries have similar issues.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;13-the-relation-between-timestamps-and-the-intervals-they-describe&#34;&gt;13. The relation between timestamps and the intervals they describe&lt;/h3&gt;
&lt;p&gt;When I look at a point at a graph that represents a spike in latency, a drop in throughput, or anything interesting really, I always wonder whether it describes the timeframe before, or after it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: With points every minute, and a spike at 10:17:00, does it mean the spike happened in the timeframe between 10:16 and 10:17, or between 10:17 and 10:18?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I don&amp;rsquo;t know if a terminology for this exists already, but I&amp;rsquo;m going to call the former &lt;em&gt;&lt;strong&gt;premarking&lt;/strong&gt;&lt;/em&gt; (data described by a timestamp that precedes the observation period) and the latter &lt;em&gt;&lt;strong&gt;postmarking&lt;/strong&gt;&lt;/em&gt; (data described by a timestamp at the end). As we already saw statsd postmarks, and many tools seem to do this, but some, including Graphite, premark.&lt;/p&gt;
&lt;p&gt;We saw above that any data received by Graphite for a point in between an interval is adjusted to get the timestamp at the beginning of the interval. Furthermore, during aggregation (say, aggregating sets of 10 minutely points into 10min points), each 10 minutes taken together get assigned the timestamp that precedes those 10 intervals. (i.e. the timestamp of the first point)&lt;/p&gt;
&lt;p&gt;So essentially, Graphite likes to show metric values before they actually happened, especially after aggregation, whereas other tools rather use a timestamp in the future of the event than in the past. As a monitoring community, we should probably standardize on an approach. I personally favor postmarking because measurements being late is fairly intuitive, predicting the future not so much.&lt;/p&gt;
&lt;h3 id=&#34;14-the-statsd-timing-type-is-not-only-for-timings&#34;&gt;14. The statsd timing type is not only for timings&lt;/h3&gt;
&lt;p&gt;The naming is a bit confusing, but anything you want to compute summary statistics (min, max, mean, percentiles, etc) for (for example message or packet sizes) can be submitted as a timing metric. You&amp;rsquo;ll get your  summary stats just fine. The type is just named &amp;ldquo;timing&amp;rdquo; because that was the original (and still most  common) use case. Note that if you want to time an operation that happens at consistent intervals,  you may just as well simply use a statsd gauge for it. (or write directly to Graphite)&lt;/p&gt;
&lt;h3 id=&#34;15-the-choice-of-metric-keys-depends-on-how-you-deployed-statsd&#34;&gt;15. The choice of metric keys depends on how you deployed statsd&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s common to deploy a statsd server per machine or per cluster. This is a convenient way to assure you have a lot of processing capacity. However, if multiple statsd servers receive the same metric, they will do their own independent computations and emit the same output metric, overwriting each other. So if you run a statsd server per host, you should include the host in the metrics you&amp;rsquo;re sending into statsd, or into the prefixStats (or similar option) for your statsd server, so that statsd itself differentiates the metrics.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: there&amp;rsquo;s some other statsd options to diversify metrics but the global
prefix is the most simple and common one used.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;16-statsd-is-fire-and-forget-non-blocking--udp-sends-have-no-overhead&#34;&gt;16. statsd is &amp;ldquo;fire and forget&amp;rdquo;, &amp;ldquo;non-blocking&amp;rdquo; &amp;amp; UDP sends &amp;ldquo;have no overhead&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;This probably stems from this snippet in the &lt;a href=&#34;https://codeascraft.com/2011/02/15/measure-anything-measure-everything/&#34;&gt;original statsd announcement&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;q class=&#34;cite&#34;&gt;&amp;quot;[UDP is] fast — you don’t want to slow your application down in order to track its performance — but also sending a UDP packet is fire-and-forget.&amp;quot;&lt;/q&gt;&lt;/p&gt;
&lt;p&gt;UDP sends do have an overhead that can slow your application down. I think a more accurate description is that the overhead is insignificant either if you&amp;rsquo;re lucky, or if you&amp;rsquo;ve spent a lot of attention to the details. In specific, it depends on the following factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Your network stack.&lt;/strong&gt;  UDP sends are not asynchronous, which is a common assumption.  (i.e. they are not &amp;ldquo;non-blocking&amp;rdquo;) Udp write calls from userspace will block until the kernel has moved the data  through the networking stack, firewall rules, through the network driver, onto the network.
I found this out the hard way once when an application I was testing on my laptop ran much slower than expected due to my consumer grade WiFi adapter, which was holding back my program by hanging on statsd calls. Using this &amp;lt;a href&amp;quot;http://play.golang.org/p/1YOZ1oxB-d&amp;quot;&amp;gt;simple go program&lt;/a&gt; I found that I could do 115 k/s UDP sends to localhost (where the kernel can bypass some of the network stack), but only 2k/s to a remote host (where it needs to go through all layers, including your NIC).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;other code running, and its performance.&lt;/strong&gt;  If you have a PHP code base with some statsd calls amongst slow / data-intensive code to generate complex pages, there won&amp;rsquo;t be much difference. This is a common, and the original setting, for statsd instrumentation calls. But I have conducted cpu profiling of high-performance Golang
applications, both at Vimeo and raintank, and when statsd was used, the apps were often spending most of their time in UDP writes caused by statsd invocations. Typically they were using a simple statsd client, where each statsd call  corresponds to a UDP write.  There are some statsd clients that buffer messages and send batches of data to statsd, reducing the UDP writes, which is a lot more efficient. (see below). You can also use sampling to lower the volume.  This does come with some problems however, see the gotcha below.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The performance of client code itself can wildly vary as well.&lt;/strong&gt; Besides how it maps metric updates to UDP writes (see above) the invocations themselves can carry an overhead, which as you can see through &lt;a href=&#34;https://github.com/Dieterbe/statsdbench&#34;&gt;these benchmarks&lt;/a&gt; of  all Go statsd clients I&amp;rsquo;m aware of, vary anywhere between 15 microseconds to 0.4 microseconds. &lt;br /&gt;&lt;br/&gt;
When I saw this, &lt;a href=&#34;https://github.com/alexcesaro/statsd&#34;&gt; Alex Cesaro&amp;rsquo;s statsd client&lt;/a&gt; promptly became my favorite statsd library for Go.  It has zero-allocation logic and various performance tweaks, such as the much needed client side buffering. Another interesting one is &lt;a href=&#34;https://github.com/quipo/statsd&#34;&gt;quipo&amp;rsquo;s&lt;/a&gt;, which offloads some of the computations into the client to reduce traffic and workload for the server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Finally, it should be noted that sending to non-listening destinations may
make your application slower.&lt;/strong&gt;
This is because destination hosts receiving UDP traffic for a closed socket, will return ICMP rejects to the sender, which the sender then has to process. I&amp;rsquo;ve not seen this with my own eyes, but the people on the #go-nuts channel who  were helping me out definitely seemed to know what they&amp;rsquo;re talking about. Sometimes &amp;ldquo;disabling&amp;rdquo; statsd sends is implemented by pointing to a random host or port that&amp;rsquo;s not listening (been there done that) and is hence not the best idea!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Takeaway: If you use statsd in high-performance situations, use optimized client libraries . Or use client libraries such as go-metrics, but be prepared to pay a processing tax on all of your servers. Be aware that slow NICs and sending to non-listening destinations will slow your app down.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;17-statsd-sampling&#34;&gt;17. statsd sampling&lt;/h3&gt;
&lt;p&gt;The sampling feature was part of the original statsd, so it can be seen in pretty much every client and server alternative.  The idea sounds simple enough: If a certain statsd invocation causes too much statsd network traffic or  overloads the server, sample down the messages. However, there&amp;rsquo;s several gotchas with this.  A common invocation with a typical  statsd client looks something like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;statsd.Increment(&amp;#34;requests.$backend.$http_response&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this code, we have 1 statement, and it increments a counter to track http response codes for different backends.  It works for different values of backend and http_response, tracking the counts for each. However, let&amp;rsquo;s say the backend &amp;ldquo;default&amp;rdquo; and http_response 200 are causing too much statsd traffic. It&amp;rsquo;s easy to just sample down and change the line to:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;statsd.Increment(&amp;#34;requests.$backend.$http_response&amp;#34;, 0.1)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There&amp;rsquo;s 3 problems here though:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;How do you select a good sampling ratio? It&amp;rsquo;s usually based on a gut feeling or some very quick math at best to come up with a reasonable number, without any attention to the impact on statistical significance, so you may be hurting the quality of your data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;While you mainly wanted to target the highest volume metric (something like &amp;ldquo;requests.default.200&amp;rdquo;), your sampling setting affects the metrics for all values of backend and http_response.  Those variable combinations that are less  frequent (for a backend that&amp;rsquo;s rarely used or a response code not commonly seen)  will be too drastically sampled down, resulting in an inaccurate view of those cases. Worst case, you won&amp;rsquo;t see any data over the course over a longer time period, even though there were points at every interval. You can add some code to use different invocations with different sample rates based on the values of the variables, but that can get kludgy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Volumes of metric calls tend to constantly evolve over time.  It&amp;rsquo;s simply not feasible to be constantly manually adjusting sample rates.  And given the above, it&amp;rsquo;s not a good solution anyway.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One of the ideas I wanted to implement in &lt;a href=&#34;https://github.com/vimeo/statsdaemon&#34;&gt;https://github.com/vimeo/statsdaemon&lt;/a&gt; was a feedback mechanism where the server would maintain counts of received messages for each key. Based on performance criteria and standard deviation measurements, it would periodically update &amp;ldquo;recommended sampling rates&amp;rdquo; for every single key, which then could be fed back to the clients (by compiling into a PHP config file for example, or over a TCP connection).   Ultimately I decided it was just too complicated and deployed a statsdaemon server on every single machine so I could sample as gently as possible.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Takeaway: Sampling can be used to lower load, but be aware of the trade offs.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;18-as-long-as-my-network-doesnt-saturate-statsd-graphs-should-be-accurate&#34;&gt;18. As long as my network doesn&amp;rsquo;t saturate, statsd graphs should be accurate&lt;/h3&gt;
&lt;p&gt;We all know that graphs from statsd are not guaranteed to be accurate, because it uses UDP, so is prone to data loss and inaccurate graphs. And we&amp;rsquo;re OK with that trade  off, because the convenience is worth the loss in accuracy. However, it&amp;rsquo;s commonly believed that the only, or main reason of inaccurate  graphs is UDP data loss on the network. In my experience, I&amp;rsquo;ve seen a lot more message loss due to the UDP buffer overflowing on the statsd server.&lt;/p&gt;
&lt;p&gt;A typical statsd server is constantly receiving a flood of metrics. For a network socket, the Linux kernel maintains a buffer in which it stores newly received network packets, while the listening application (statsd) reads  them out of the buffer.  But if for any reason the application can&amp;rsquo;t read from the buffer fast enough and it fills up, the kernel has to drop incoming traffic. The most common case are the statsd flushes, which compute all summary statistics and submit them each flushInterval. Typically this operation takes between 50ms and a few seconds, depending mostly on how many timing metrics were received, because those are the most computationally expensive.  Usually statsd&amp;rsquo;s cpu is maxed out during this operation, but you won&amp;rsquo;t see it on  your cpu graphs because your cpu measurements are averages taken at intervals that typically don&amp;rsquo;t exactly coincide with the statsd flush-induced spikes. During this time, it temporarily cannot read from the UDP buffer, and it is very  common for the UDP buffer to rapidly fill up with new packets, at which point the Linux kernel is forced to drop incoming network packets for the UDP socket. In my experience this is very common and often even goes undetected, because  only a portion of the metrics are lost, and the graphs are not obviously wrong. Needless to say, there&amp;rsquo;s also plenty of other scenarios for the buffer to fill up and cause traffic drops other than statsd flushing.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s two things to be done here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Luckily we can tune the size of the incoming UDP buffer with the net.core.rmem_max and net.core.rmem_default sysctl&amp;rsquo;s. I recommend setting it to the &lt;a href=&#34;http://stackoverflow.com/questions/2090850/specifying-udp-receive-buffer-size-at-runtime-in-linux&#34;&gt;max values&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The kernel increments a counter every time it drops a UDP packet. You can see UDP packet drops with &lt;code&gt;netstat -s --udp&lt;/code&gt; on the command  line. I highly encourage you to monitor this with something like collectd, visualize  it over time, and make sure to set an alert on it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Note also that the larger of a buffer you need, the more delay between receiving a metric and including it in the output data, possibly skewing data into the future.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;chroma&#34;&gt;
&lt;strong&gt;INTERMEZZO:&lt;/strong&gt;
There&#39;s a lot of good statsd servers out there with various feature  sets. Most of them provide improved performance (upstream statsd is single threaded JavaScript), but some come with additional interesting features. My favorites include &lt;a href=&#34;https://github.com/armon/statsite&#34;&gt;statsite&lt;/a&gt;, &lt;a href=&#34;http://githubengineering.com/brubeck/&#34;&gt;brubeck&lt;/a&gt; and of course &lt;a href=&#34;https://github.com/vimeo/statsdaemon&#34;&gt;vimeo&#39;s statsdaemon version&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&#34;19-incrementingdecrementing-gauges&#34;&gt;19. Incrementing/decrementing gauges&lt;/h3&gt;
&lt;p&gt;Statsd supports a syntax to &lt;a href=&#34;https://github.com/etsy/statsd/blob/master/docs/metric_types.md#gauges&#34;&gt; increment and decrement gauges&lt;/a&gt;. However, as we&amp;rsquo;ve seen, any message can be lost. If you do this and a message gets dropped, your gauge value will be incorrect forever (or until you set it explicitly again). Also by sending increment/decrement values you can confuse a statsd server if it was just started. For this reason, I highly recommend not using this particular feature, and always setting gauge values explicitly.  In fact, some statsd servers don&amp;rsquo;t support this syntax for this reason.&lt;/p&gt;
&lt;h3 id=&#34;20-you-cant-graph-what-you-havent-seen&#34;&gt;20. You can&amp;rsquo;t graph what you haven&amp;rsquo;t seen&lt;/h3&gt;
&lt;p&gt;Taking the earlier example again:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;statsd.Increment(&amp;#34;requests.$backend.$http_response&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The metrics will only be created after the values have been sent. Sounds obvious, but this can get surprisingly annoying. Let&amp;rsquo;s say you want to make a graph of http 500&amp;rsquo;s, but they haven&amp;rsquo;t happened yet. The metrics won&amp;rsquo;t exist and with many  dashboarding tools, you won&amp;rsquo;t be able to create the graph yet, or at least need extra  work.&lt;/p&gt;
&lt;p&gt;I see this very commonly with all kinds of error metrics.  I think with Grafana it will become easier to deal with this over time,  but for now I write code to just send each metric once at startup.  For counts you can just send a 0, for gauges and timers it&amp;rsquo;s of course harder/weirder to come up with a fake value but it&amp;rsquo;s still a  reasonable approach.&lt;/p&gt;
&lt;h3 id=&#34;21-dont-let-the-data-fool-you-nulls-and-deleteidlestats-options&#34;&gt;21. Don&amp;rsquo;t let the data fool you: nulls and deleteIdleStats options&lt;/h3&gt;
&lt;p&gt;statsd has the deleteIdleStats, deleteGauges, and similar options. By default they are disabled, meaning statsd will keep sending data for metrics it&amp;rsquo;s no longer seeing. So for example, it&amp;rsquo;ll keep sending the last gauge value even if it didn&amp;rsquo;t get an update. I have three issues with this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Your graphs are misleading.&lt;/strong&gt; Your service may be dead but you can&amp;rsquo;t tell from
the gauge graphs cause they will still &amp;ldquo;look good&amp;rdquo;. If you have something like  counters for requests handled, you can&amp;rsquo;t tell the difference between your  service being dead or it being up but not getting incoming requests.  I rather have no data show up if there is none, combined with something else (alerting, different graph) to deduce whether the service is up or not&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Any alerting rules defined on the metrics have the same fate as humans and
can&amp;rsquo;t reliably do their work&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tougher to phase out metrics.&lt;/strong&gt;  If you decommission servers or services, it&amp;rsquo;s nice that the metrics stop updating so you can clean them up later&lt;/li&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My recommendation is, enable deleteIdleStats.  I went as far as hard coding that behavior into &lt;a  href=&#34;https://github.com/vimeo/statsdaemon&#34;&gt;vimeo/statsdaemon&lt;/a&gt; and not making it configurable.&lt;/p&gt;
&lt;p&gt;To visualize it, make sure in Grafana to set the &amp;ldquo;null as null&amp;rdquo; option, though &amp;ldquo;null as zero&amp;rdquo; can make sense for counters. You can also use the &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/functions.html#graphite.render.functions.transformNull&#34;&gt;transformNull()&lt;/a&gt; or &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.15/render_api.html#drawnullaszero&#34;&gt;drawNullAsZero&lt;/a&gt; options in Graphite for those  cases where you want to explicitly get 0&amp;rsquo;s instead of nulls, which I typically  do in some of my bosun alerting rules, so I can treat null counts as no traffic received, while having a separate alerting rule to make sure my service is up  and running, based on a different metric, while using null as null for visualization.&lt;/p&gt;
&lt;h3 id=&#34;22-keeplastvalue-works-almost-always&#34;&gt;22. keepLastValue works&amp;hellip; almost always&lt;/h3&gt;
&lt;p&gt;Another Graphite function to change the semantics of nulls is &lt;a href=&#34;http://graphite.readthedocs.org/en/latest/functions.html#graphite.render.functions.keepLastValue&#34;&gt; keepLastValue&lt;/a&gt;, which causes null values to be represented by the last known value that precedes them. However, that known value must be included in the requested time range.  This is probably a rare case that you may never encounter, but if you have scripts that infrequently update a metric and you use this function, it may result in a graph sometimes showing no data at all if the last known value becomes too old.  Especially confusing to newcomers, if the graph does &amp;ldquo;work&amp;rdquo; at other times.&lt;/p&gt;
&lt;h3 id=&#34;23-statsd-counters-are-not-counters-in-the-traditional-sense&#34;&gt;23. statsd counters are not counters in the traditional sense&lt;/h3&gt;
&lt;p&gt;You may know counters such as switch traffic/packet counters, that just keep increasing over time. You can see their rates per second by deriving the data. Statsd counters however, are typically either stored as the number of hits per flushInterval, or per second, or both (perhaps because of Graphite&amp;rsquo;s derivative issue?). This in itself is not a huge problem, however this is more vulnerable to loss of data.  If your statsd server has trouble flushing some data to Graphite and some data gets lost.  If it were using a traditional counter, you could still derive the data and average out the gap across the nulls. In this case however this is not possible and you have no idea what the numbers were.  In practice this doesn&amp;rsquo;t happen often though.  Many statsd implementations can buffer a writequeue or use something like &lt;a href=&#34;https://github.com/graphite-ng/carbon-relay-ng&#34;&gt; carbon-relay-ng&lt;/a&gt; as a write queue.
Other disadvantages of this approach is that you need to know the flushInterval
value to make sense of the count values, and the rounding that happens when
computing the rates per second, which is also slightly lossy.&lt;/p&gt;
&lt;h3 id=&#34;24-what-can-i-send-as-input&#34;&gt;24. What can I send as input?&lt;/h3&gt;
&lt;p&gt;Neither &lt;a href=&#34;http://graphite.readthedocs.org/en/latest/feeding-carbon.html&#34;&gt;Graphite&lt;/a&gt;, nor &lt;a href=&#34;https://github.com/etsy/statsd/blob/master/docs/metric_types.md&#34;&gt;statsd&lt;/a&gt; does a great job specifying exactly what they allow as input, which can be frustrating.  Graphite timestamps are 32bit unix timestamp integers, while values for both Graphite and statsd can be integers or floats, up to float 64bit precision. For statsd, see the &amp;lt;a href&amp;quot;https://github.com/b/statsd_spec&amp;quot;&amp;gt;statsd_spec&lt;/a&gt; project for more details.&lt;/p&gt;
&lt;p&gt;As for what characters can be included in the metric keys. Generally, Graphite is somewhat forgiving and may alter your metric keys: it converts slashes to dots (which can be confusing), subsequent dots become single dots, prefix dots get removed, postfix dots will get it confused a bit though and create an extra hierarchy with an empty node at the end if you&amp;rsquo;re using whisper. Non-alphanumeric characters such as &lt;a href=&#34;https://github.com/graphite-project/graphite-web/issues/242&#34;&gt;parenthesis&lt;/a&gt;, &lt;a href=&#34;https://github.com/graphite-project/graphite web/issues/604&#34;&gt;colons&lt;/a&gt;, or &lt;a href=&#34;https://github.com/brutasse/graphite-api/issues/57&#34;&gt; equals signs&lt;/a&gt; often don&amp;rsquo;t work well or at all.&lt;/p&gt;
&lt;p&gt;Graphite as a policy does not go far in validating incoming data, citing performance in large-throughput systems as the major reason. It&amp;rsquo;s up to the senders to send data in proper form, with non-empty nodes (words between dots) separated by single dots.  You can use alphanumeric characters, hyphens and underscores, but straying from that will probably not work well. You may want to use &lt;a href=&#34;https://github.com/graphite-ng/carbon-relay-ng&#34;&gt; carbon-relay-ng&lt;/a&gt; which provides metric validation. See also &lt;a href=&#34;https://github.com/graphite-project/carbon/issues/417&#34;&gt;this issue&lt;/a&gt; which aims to formalize what is, and isn&amp;rsquo;t allowed.&lt;/p&gt;
&lt;h3 id=&#34;25-hostnames-and-ip-addresses-in-metric-keys&#34;&gt;25. Hostnames and ip addresses in metric keys&lt;/h3&gt;
&lt;p&gt;The last gotcha relates to the previous one but is so common it deserves its own spot. Hostnames, especially FQDN&amp;rsquo;s, and IP addresses (due to their dots), when included in metric keys, will be interpreted by Graphite as separate pieces. Typically, people replace all dots in hostnames and IP addresses with hyphens or underscores to combat this.&lt;/p&gt;
&lt;h3 id=&#34;closing-thoughts&#34;&gt;Closing thoughts&lt;/h3&gt;
&lt;p&gt;Graphite, Grafana and statsd are great tools, but there&amp;rsquo;s some things to watch out for. When setting them up, make sure you configure Graphite and statsd to play well together. Make sure to set your roll-up functions and data retentions properly, and  whichever statsd version you decide to use, make sure it flushes at the same  interval as your Graphite schema configuration. &lt;a  href=&#34;https://github.com/etsy/statsd/blob/master/docs/graphite.md&#34;&gt;More tips if you use the nodejs version&lt;/a&gt;. Furthermore, I hope this is an extensive list of gotchas and will serve to improve our practices at first, and our tools themselves, down to road. We are definitely working on making things better and have some announcements coming up&amp;hellip;&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Focusing on open source monitoring.  Joining raintank.</title>
      <link>https://dieter.plaetinck.be/posts/focusing-on-open-source-monitoring-joining-raintank/</link>
      <pubDate>Fri, 03 Jul 2015 09:22:02 -0700</pubDate>
      
      
      <guid>http://dieter.plaetinck.be/post/focusing-on-open-source-monitoring-joining-raintank/</guid>
      
      
      <description>&lt;h2&gt;Goodbye Vimeo&lt;/h2&gt;
&lt;p&gt;
It&#39;s never been as hard saying goodbye to the people and the work environment as it is now.
&lt;br/&gt;
Vimeo was created by dedicated film creators and enthusiasts, just over 10 years ago, and today it still shows.
From the quirky, playful office culture, &lt;a href=&#34;https://vimeo.com/staff&#34;&gt;the staff created short films&lt;/a&gt;,
to the &lt;a href=&#34;https://vimeo.com/categories&#34;&gt;tremendous curation effort&lt;/a&gt; and &lt;a href=&#34;https://vimeo.com/channels/staffpicks/videos&#34;&gt;staff picks&lt;/a&gt; including &lt;a href=&#34;http://websta.me/p/797128421285501516_12986477&#34;&gt;monthly staff screenings&lt;/a&gt; where we get to see the best of the best videos on the Internet each month,
to the dedication towards building the best platform and community on the web to enjoy videos and the uncompromising commitment to supporting movie creators and working in their best interest.
&lt;br/&gt;Engineering wise, there has been plenty of opportunity to make an impact and learn.
&lt;br/&gt;Nonetheless, I have to leave and I&#39;ll explain why.  First I want to mention a few more things.
&lt;/p&gt;
&lt;img src=&#34;https://dieter.plaetinck.be/files/bye_vimeo.jpg&#34; alt=&#34;vimeo goodbye drink&#34; /&gt;
&lt;br/&gt;
&lt;br/&gt;

&lt;p&gt;
In Belgium I used to hitchhike to and from work so that each day brought me opportunities to have conversations with a diverse, fantastic assortment of people.  I still fondly remember some of those memories. (and it was also usually faster than taking the bus!)
&lt;br/&gt;Here in NYC this isn&#39;t really feasible, so I tried the next best thing.  A mission to have lunch with every single person in the company, starting with those I don&#39;t typically interact with.  I managed to have lunch with 95 people, get to know them a bit, find some gems of personalities and anecdotes, and have conversations on a tremendous variety of subjects, some light-hearted, some deep and profound.  It was fun and I hope to be able to keep doing such social experiments in my new environment.

&lt;/p&gt;
&lt;p&gt;
	Vimeo is also part of my life in an unusually personal way.  When I came to New York (my first ever visit to the US) in 2011 to interview, I also met a pretty fantastic woman in a random bar in Williamsburg. We ended up traveling together in Europe, I decided to move the US and we moved in together.  I&#39;ve had the pleasure of being submerged in both American and Greek culture for the last few years, but the best part is that today we are engaged and I feel like the luckiest guy in the world.  While I&#39;ve tried to keep work and personal life somewhat separate, Vimeo has made an undeniable ever lasting impact on my life that I&#39;m very grateful for.
&lt;/p&gt;
&lt;p&gt;
At Vimeo I found an area where a bunch of my interests converge: operational best practices, high performance systems, number crunching, statistics and open source software.  Specifically, timeseries metrics processing in the context of monitoring.  While I have enjoyed my opportunity &lt;a href=&#34;https://dieter.plaetinck.be/tags/monitoring/&#34;&gt;to make contributions in this space&lt;/a&gt; to help our teams and other companies who end up using my tools, I want to move out of the cost center of the company, I want to be in the department that creates the value.  If I want to focus on open source monitoring, I should align my incentives with those of my employer.  Both for my and their sake.
&lt;b&gt;I want to make more profound contributions to the space.  The time has come for me to join a company for which the main focus is making open source monitoring better.&lt;/b&gt;
&lt;/p&gt;
&lt;h2&gt;Hello raintank!&lt;/h2&gt;
Over the past two years or so I&#39;ve talked to many people in the industry about monitoring, many of them trying to bring me into their team.
I never found a perfect fit but as we transitioned from 2014 into 2015, the stars seemingly aligned for me.
Here&#39;s why I&#39;m very excited to join the &lt;a href=&#34;http://www.raintank.io/&#34;&gt;raintank&lt;/a&gt; crew:
&lt;ul&gt;
&lt;li&gt;I&#39;m a strong believer in open source.  I believe fundamental infrastructure tooling should be modifiable and in your control.  It&#39;s partially a philosophical argument, but also what I believe will separate long lasting business from short term successes.
&lt;br/&gt;SaaS is great, but not if it&#39;s built to lock you in.  In this day and age, I think you should &#34;lock in&#34; your customers by providing a great experience they can&#39;t say no to, not by having them build technical debt as they integrate into your stack.
&lt;br/&gt;That said, integrating with open source also incurs technical debt, and some closed source service providers are so good that the debt is worth it.  But I don&#39;t believe this lasts long term, especially given the required pricing models.  I think you can entice customers more by lowering the debt they build up (i.e. use standardized protocols, tooling and making it easy for them to leave) as they adopt your service.
&lt;!-- I was really interested in datadog for example.  I liked the team, I liked the product they are/were building and I saw they would become successfull, but it&#39;s not the kind of business I want to build towards long term. --&gt;
&lt;br/&gt;raintank&#39;s commitment to open source is not a gimmick but stems from a fundamental conviction that 100% open source is the right thing to do.  That by providing freedom, you get loyalty.
I think they came up with a good business model that combines the benefits of SaaS with those of open source.  At least it&#39;s a bet I want to take.
It&#39;s not an easy feat but I think we got a good formula. (basically openSAAS, the stack is open source, integrates in the wider ecosystem, you can run it yourself, you own your data, you can use our SAAS, or create a mixed setup.)&lt;/li&gt;
&lt;br&gt;
&lt;iframe src=&#34;https://player.vimeo.com/video/131790481&#34; width=&#34;500&#34; height=&#34;281&#34; frameborder=&#34;0&#34; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;
&lt;li&gt;Something I value a lot in coworkers, besides &#34;technical&#34; abilities is emotional intelligence and professional maturity.  Part of me thinks it&#39;s a vastly underestimated quality in general, although perhaps I just happen to find it more important than average.  Either way, the new team seems solid on both fronts.  I&#39;m mostly impressed by the founder/CEO Raj Dutt who has shown a very personal and graceful approach.
	Strong high-stakes relationships with people in general, and coworkers in particular are a very worthy pursuit and two months in I can still vouch for the level of alignment and maturity that I haven&#39;t experienced before.
	&lt;br&gt;
	&lt;br&gt;
	&lt;img src=&#34;https://dieter.plaetinck.be/files/20150429_194521_HDR.jpg&#34; alt=&#34;Yours truly and Raj Dutt&#34; /&gt;
	&lt;br&gt;
	&lt;br&gt;
	&lt;li&gt;I (and my fiancee) want to see the world. The common conception that significant leisure travel can&#39;t be combined with hard, or even normal amounts of work seems so backwards to me.  Today more than ever, we have globalization, we are developing a sharing economy (airbnb, lyft, ...).  There&#39;s no reason we can&#39;t do great work while enjoying our personal time to the fullest.  Working remotely, and/or with remote colleagues requires more discipline but I simply only want to work with disciplined people.  Working on a fixed schedule, in a fixed office location is needlessly arcane, constrained and inefficient. It puts a damper on life.
		Almost all software companies I know see open office plans as a great thing, but it&#39;s usually an attempt at compensating for employee&#39;s poor communication skills, forcing them
		to talk to the detriment of people who need focus and get distracted.  Isolation of workers does not preclude healthy communication and collaboration.
		I get a lot more done in isolation, with sync-ups and face-to-face when appropriate, especially if it&#39;s on my schedule. Working remote is a great way to facilitate this and I&#39;m happy that raintank not only agrees with the idea, but actually encourages travel, and encourages me to follow whatever time allocation works best for me.
		I work hard but we travel where ever we want, we&#39;ll have plenty of time to spend with our families in Belgium and Cyprus.  And yet I don&#39;t think I ever worked this closely with anyone.&lt;/li&gt;
	&lt;br&gt;
&lt;img src=&#34;https://dieter.plaetinck.be/files/office_shasta.jpg&#34; alt=&#34;office mount shasta&#34; /&gt;
	&lt;br&gt;
	&lt;br&gt;
&lt;li&gt;I&#39;ve always wanted to be in a company from the start and experience the &#34;true&#34; start-up feel.  I have a lot of opinions on organization, culture, and product and so I&#39;m glad to have the opportunity to make that kind of impact as well.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;OK, so what am I really up to?&lt;/h2&gt;
&lt;p&gt;
	Grafana is &lt;a href=&#34;http://play.grafana.org/dashboard/db/stats&#34;&gt;pretty much the leading open source metrics dashboard&lt;/a&gt; right now.
So it only makes sense that raintank is a heavy Grafana user and contributor.
My work, logically, revolves around codifying some of the experience and ideas I have, and making
them accessible through the polished interface that is Grafana, which now also has a full time UX designer working on it.
Since according to the &lt;a href=&#34;https://infogr.am/grafana_user_survey_mar2015&#34;&gt;Grafana user survey&lt;/a&gt; &lt;b&gt;alerting is the most sorely missed non-feature of Grafana&lt;/b&gt;,
we are working hard on rectifying this and it is my full-time focus.  If you&#39;ve followed my blog you know I have some thoughts on where the sweet spot lies in clever alerting.
In short, take the claims of anomaly detection via machine learning with a big grain of salt, and instead, focus on enabling operators to express complex logic simply, quickly,
and in an agile way.  My latest favorite project, &lt;a href=&#34;http://bosun.org/&#34;&gt;bosun&lt;/a&gt; exemplifies this approach (highly recommend giving this a close look).
&lt;/p&gt;
&lt;p&gt;
The way I&#39;m thinking of it now, the priorities (and sequence of focus) for alerting within Grafana will probably be something like this:
&lt;ul&gt;
	&lt;li&gt;cover the low hanging fruit: simple threshold checks with email notifications actually go a long way&lt;/li&gt;
	&lt;li&gt;gradually provide more power and sophistication (reduction functions, boolean logic, etc), while keeping things in a nice UI&lt;/li&gt;
	&lt;li&gt;provide full-on integration with advanced alerting systems such as Bosun. Iterative workflow, Signal/noise analysis, etc&lt;/li&gt;
&lt;/ul&gt;

There&#39;s a lot of thought work, UX and implementation details around this topic,
I&#39;ve created a &lt;a href=&#34;https://github.com/grafana/grafana/issues/2209&#34;&gt;github ticket&lt;/a&gt; to kick off a discussion and am curious to hear your thoughts.

Finally, if any of this sounds interesting to you, you can sign up to the &lt;a href=&#34;http://grafana.org/&#34;&gt;grafana newsletter&lt;/a&gt; or the &lt;a href=&#34;http://raintank.io/&#34;&gt;raintank newsletter&lt;/a&gt; which will get you info on the open source platform as well
as the SaaS product.  Both are fairly low volume.

&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src=&#34;https://dieter.plaetinck.be/files/office_sausolito.jpg&#34; alt=&#34;office sausolito&#34; /&gt;
&lt;i&gt;It may look like I&#39;m not doing much from my temporary Mill Valley office, but trust me, cool stuff is coming!&lt;/i&gt;



&lt;!--
some reminisic about meeting up with torkel and talking buziness models in pdx
 how i see myself integrating in the team:
the way I see it, there&#39;s some good, next-gen ideas and implementation in some of the things i&#39;ve built and/or have experience with (metrics2.0, graph-explorer, bosun) but clearly some of these projects (esp the former two) have been handicapped by a steep learning curve and weak UX.  Part of the reason I&#39;m excited in joining in RT is that over time I will be able to gently infuse some of these re-envisioned ideas into the grafana package, with a much higher focus on user friendlyness.
nyc skin issues
alternative funding? crowd etc


https://vimeo.com/blog/post:702
grown as backend engineer, carbon-relay-ng most fun
my various projects
contributor to graphite, influxdb, bosun, diamond, statsd, graphite-api,
https://github.com/brutasse/graphite-api
https://github.com/Dieterbe/timeserieswidget
https://github.com/Dieterbe/profile-process
http://vimeo.github.io/graph-explorer/
https://github.com/vimeo/graphite-influxdb
https://github.com/vimeo/carbon-tagger
https://github.com/vimeo/statsdaemon
https://github.com/vimeo/graphite-api-influxdb-docker
https://github.com/vimeo/whisper-to-influxdb
https://github.com/vimeo/smoketcp
https://github.com/vimeo/timeserieswidget
https://github.com/vimeo/simple-black-box
https://groups.google.com/forum/#!forum/it-telemetry

https://github.com/python-diamond
https://github.com/bosun-monitor

https://github.com/Dieterbe/anthracite
https://github.com/Dieterbe/influx-cli

https://github.com/graphite-ng/graphite-ng
https://github.com/graphite-ng/carbon-relay-ng
http://metrics20.org/
humbled by big players who saw my work and invited me to work with them
basically 2 big camps.


it seems like every week a monitoring startup launches somewhere.  There is, and will be, more and more competition.  It&#39;s almost ludicrous to start or join a new one.
--&gt;
</description>
      
    </item>
    
    <item>
      <title>Practical fault detection on timeseries part 2: first macros and templates</title>
      <link>https://dieter.plaetinck.be/posts/practical-fault-detection-on-timeseries-part-2/</link>
      <pubDate>Mon, 27 Apr 2015 09:05:02 -0400</pubDate>
      
      
      <guid>practical-fault-detection-on-timeseries-part-2</guid>
      
      
      <description>In the &lt;a href=&#34;https://dieter.plaetinck.be/practical-fault-detection-alerting-dont-need-to-be-data-scientist.html&#34;&gt;previous fault detection article&lt;/a&gt;, we saw how we can cover a lot of ground in fault detection with simple methods and technology that is available today.
It had an example of a simple but effective approach to find sudden spikes (peaks and drops) within fluctuating time series.
This post explains the continuation of that work and provides you the means to implement this yourself with minimal effort.
I&#39;m sharing with you:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://bosun.org&#34;&gt;Bosun&lt;/a&gt; macros which detect our most common not-trivially-detectable symptoms of problems&lt;/li&gt;
&lt;li&gt;Bosun notification template which provides a decent amount of information&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.grafana.org&#34;&gt;Grafana&lt;/a&gt; and &lt;a href=&#34;http://vimeo.github.io/graph-explorer/&#34;&gt;Graph-Explorer&lt;/a&gt; dashboards and integration for further troubleshooting&lt;/li&gt;
&lt;/ul&gt;
We reuse this stuff for a variety of cases where the data behaves similarly and I suspect that you will be able to apply this to a bunch of your monitoring targets as well.

&lt;h2&gt;Target use case&lt;/h2&gt;
As in the previous article, we focus on the specific category of timeseries metrics driven by user activity.
Those series are expected to fluctuate in at least some kind of (usually daily) pattern, but is expected to have a certain smoothness to it. Think web requests per second or uploads per minute.   There are a few characteristics that are considered faulty or at least worth our attention:
&lt;br/&gt;
&lt;table&gt;
&lt;tr&gt;
    &lt;td style=&#34;padding:0px;&#34; width=&#34;160px;&#34;&gt;&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-good.png&#34;&gt;&lt;img width=&#34;160px;&#34; src=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-good.png&#34;/&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td style=&#34;padding:0px;&#34; width=&#34;160px;&#34;&gt;&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-bad-spikes.png&#34;&gt;&lt;img width=&#34;160px;&#34; src=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-bad-spikes.png&#34;/&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td style=&#34;padding:0px;&#34; width=&#34;160px;&#34;&gt;&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-bad-erratic.png&#34;&gt;&lt;img width=&#34;160px;&#34; src=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-bad-erratic.png&#34;/&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td style=&#34;padding:0px;&#34; width=&#34;160px;&#34;&gt;&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-bad-timeseries-median-drop.png&#34;&gt;&lt;img width=&#34;160px;&#34; src=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeseries-bad-timeseries-median-drop.png&#34;/&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;&lt;b style=&#34;color: green;&#34;&gt;looks good&lt;/b&gt;&lt;br/&gt;consistent pattern&lt;br/&gt;consistent smoothness&lt;/td&gt;
  &lt;td&gt;&lt;b style=&#34;color: red;&#34;&gt;sudden deviation (spike)&lt;/b&gt;&lt;br/&gt;Almost always something broke or choked.&lt;br/&gt;could also be pointing up. ~ peaks and valleys&lt;/td&gt;
  &lt;td&gt;&lt;b style=&#34;color: red;&#34;&gt;increased erraticness&lt;/b&gt;&lt;br/&gt;Sometimes natural&lt;br/&gt;often result of performance issues&lt;/td&gt;
  &lt;td&gt;&lt;b style=&#34;color: red;&#34;&gt;lower values than usual&lt;/b&gt; (in the third cycle)&lt;br/&gt;Often caused by changes in code or config, sometimes innocent.  But best to alert operator in any case [*]&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;br/&gt;
[*] Note that some regular patterns can look like this as well. For example weekend traffic lower than weekdays, etc.  We see this a lot.
&lt;br/&gt;The illustrations don&#39;t portray this for simplicity.   But the alerting logic below supports this just fine by comparing to same day last week instead of yesterday, etc.


&lt;h2&gt;Introducing the new approach&lt;/h2&gt;

The &lt;a href=&#34;https://dieter.plaetinck.be/practical-fault-detection-alerting-dont-need-to-be-data-scientist.html&#34;&gt;previous article&lt;/a&gt; demonstrated using graphite to compute standard deviation.
This let us alert on the erraticness of the series in general and as a particularly interesting side-effect, on spikes up and down.
The new approach is more refined and concrete by leveraging some of bosun&#39;s and Grafana&#39;s strengths.  We can&#39;t always detect the last case above via erraticness checking (a lower amount may be introduced gradually, not via a sudden drop) so now we monitor for that as well, covering all cases above.

We use 
&lt;ul&gt;
&lt;li&gt;Bosun macros which encapsulate all the querying and processing&lt;/li&gt;
&lt;li&gt;Bosun template for notifications&lt;/li&gt;
&lt;li&gt;A generic Grafana dashboard which aids in troubleshooting&lt;/li&gt;
&lt;/ul&gt;
We can then leverage this for various use cases, as long as the expectations of the data are as outlined above.
We use this for web traffic, volume of log messages, uploads, telemetry traffic, etc.
For each case we simply define the graphite queries and some parameters and leverage the existing mentioned Bosun and Grafana configuration.
&lt;br/&gt;
&lt;p&gt;
The best way to introduce this is probably by showing how a notification looks like:
&lt;br/&gt;
&lt;center&gt;
&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-dm-notification.png&#34;&gt;&lt;img height=&#34;600px&#34; src=&#34;https://dieter.plaetinck.be/files/practical-alerting-dm-notification.png&#34;/&gt;&lt;/a&gt;
&lt;br/&gt;
(image redacted to hide confidential information
&lt;br/&gt;the numbers are not accurate and for demonstration purposes only)
&lt;/center&gt;
&lt;p&gt;
As you can tell by the sections, we look at some global data (for example &#34;all web traffic&#34;, &#34;all log messages&#34;, etc), and also
by data segregated by a particular dimension (for example web traffic by country, log messages by key, etc)
&lt;br/&gt;
To cover all problematic cases outlined above, we do 3 different checks:
(note, everything is parametrized so you can tune it, see further down)
&lt;ul&gt;
&lt;li&gt;Global volume: comparing the median value of the last 60 minutes or so against the corresponding 60 minutes last week and expressing it as a &#34;strength ratio&#34;.  Anything below a given threshold such as 0.8 is alerted on&lt;/li&gt;
&lt;li&gt;Global erraticness. To find all forms of erraticness (increased deviation), we use a refined formula.  See details below.  A graph of the input data is included so you can visually verify the series&lt;/li&gt;
&lt;li&gt;On the segregated data: compare current (hour or so) median against median derived from the corresponding hours during the past few weeks, and only allow a certain amount of standard deviations difference&lt;/li&gt;
&lt;/ul&gt;

If any, or multiple of these conditions are in warning or critical state, we get 1 alert that gives us all the information we need.
&lt;br/&gt;
Note the various links to GE (Graph-Explorer) and Grafana for timeshifts.
The Graph-Explorer links are just standard GEQL queries, I usually use this if i want to be easily manage what I&#39;m viewing (compare against other countries, adjust time interval, etc) because that&#39;s what GE is really good at.
The timeshift view is a Grafana dashboard that takes in a Graphite expression as a template variable, and can hence be set via a GET parameter by using the url  &lt;pre&gt;http://grafana/#/dashboard/db/templatetimeshift?var-patt=expression&lt;/pre&gt;
It shows the current past week as red dots, and the past weeks before that as timeshifts in various shades of blue representing the age of the data. (darker is older).
&lt;br/&gt;
&lt;br/&gt;

&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-screenshot-template-timeshift.png&#34;&gt;&lt;img src=&#34;https://dieter.plaetinck.be/files/practical-alerting-screenshot-template-timeshift.png&#34; /&gt;&lt;/a&gt;
&lt;br/&gt;
This allows us to easily spot when traffic becomes too low, overly erratic, etc as this example shows:
&lt;br/&gt;
&lt;br/&gt;

&lt;a href=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeshift-use.png&#34;&gt;&lt;img src=&#34;https://dieter.plaetinck.be/files/practical-alerting-timeshift-use.png&#34; /&gt;&lt;/a&gt;
&lt;br/&gt;

&lt;h2&gt;Getting started&lt;/h2&gt;

Note: I Won&#39;t explain the details of the bosun configuration.  Familiarity with bosun is assumed.  The &lt;a href=&#34;http://bosun.org/&#34;&gt;bosun documentation&lt;/a&gt; is pretty complete.
&lt;br/&gt;
&lt;br/&gt;
&lt;a href=&#34;https://gist.github.com/Dieterbe/d1892fa0b4454b892216&#34;&gt;Gist with bosun macro, template, example use, and Grafana dashboard definition&lt;/a&gt;.  Load the bosun stuff in your bosun.conf and import the dashboard in Grafana.
&lt;br/&gt;
&lt;br/&gt;
The pieces fit together like so:

&lt;ul&gt;
&lt;li&gt;The alert is where we define the graphite queries, the name of the dimension segregated by (used in template), how long the periods are, what the various thresholds are and the expressions to be fed into Grafana and Graph-Explorer.
&lt;br/&gt;
It also lets you set an importance which controls the sorting of the segregated entries in the notification (see screenshot).  By default it is based on the historical median of the values but you could override this.  For example for a particular alert we maintain a lookup table with custom importance values.&lt;/li&gt;
&lt;li&gt;The macros are split in two:
&lt;ol&gt;
&lt;li&gt;dm-load loads all the initial data based on your queries and computes a bunch of the numbers.&lt;/li&gt;
&lt;li&gt;dm-logic does some final computations and evaluates the warning and critical state expressions.&lt;/li&gt;
&lt;/ol&gt;
They are split so that your alerting rule can leverage the returned tags from the queries in dm-load to use a lookup table to set the importance variable or other thresholds, such as s_min_med_diff on a case-by-case basis, before calling dm-logic.
&lt;br/&gt;
We warn if one or more segregated items didn&#39;t meet their median requirements, and if erraticness exceeds its threshold (note that the latter can be disabled).
&lt;br&gt;Critical is when more than the specified number of segregated items didn&#39;t meet their median requirements, the global volume didn&#39;t meet the strength ratio, or if erraticness is enabled and above the critical threshold.
&lt;/li&gt;
&lt;li&gt;The template is evaluated and generates the notification like shown above&lt;/li&gt;
&lt;li&gt;Links to Grafana (timeshift) and GE are generated in the notification to make it easy to start troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Erraticness formula refinements&lt;/h2&gt;
You may notice that the formula has changed to
&lt;pre&gt;
(deviation-now * median-historical) /
((deviation-historical * median-now) + 0.01)
&lt;/pre&gt;
&lt;img style=&#34;float: right; margin: 45px;&#34; width=&#34;40%&#34; src=&#34;https://dieter.plaetinck.be/files/practical-alerting-notes-cleaned-small.jpg&#34; /&gt;
&lt;ul&gt;
&lt;li&gt;Current deviation is compared to an automatically chosen historical deviation value (so no more need to manually set this)&lt;/li&gt;
&lt;li&gt;Accounts for difference in volume: for example if traffic at any point is much higher, we can also expect the deviation to be higher.  With the previous formula we would have cases where in the past the numbers were very low, and naturally the deviation then was low and not a reasonable standard to be held against when traffic is higher, resulting in trigger happy alerting with false positives.
&lt;br/&gt;Now we give a fair weight to the deviation ratio by making it inversely proportional to the median ratio&lt;/li&gt;
&lt;li&gt;The + 0.01 is to avoid division by zero&lt;/li&gt;
&lt;/ul&gt;

&lt;!--
streak covers cases where values are very low so that stdev is in the same order (like low volume logs) and we can&#39;t properly use the erraticness or x-deviations. for example logs with very little traffic, datapoints representing healthy traffic can look like (1, 2, 0, 3, 1, ..)
although i think the ratio of medians (median_now/median_then) should work just as well as streak

&lt;img src=&#34;https://dieter.plaetinck.be/files/practical-alerting-low-values-zeroes.png&#34; /&gt;
&lt;img src=&#34;https://dieter.plaetinck.be/files/practical-alerting-low-values-low.png&#34; /&gt;
--&gt;

&lt;h2&gt;Still far from perfect&lt;/h2&gt;
While this has been very helpful to us, I want to highlight a few things that could be improved.
&lt;ul&gt;
&lt;li&gt;With these alerts, you&#39;ll find yourself wanting to iteratively fine tune the various parameters and validate the result of your changes by comparing the status-over-time timeline before and after the change.  While Bosun already makes iterative development easier and lets you &lt;a href=&#34;http://bosun.org/public/ss_rule_timeline.png&#34;&gt;run test rules against old data and look at a the status over time&lt;/a&gt;, the interface could be improved by
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bosun-monitor/bosun/issues/636&#34;&gt;showing timeseries (with event markers where relevant) alongside the status visualization&lt;/a&gt;, so you have context to interpret the status timeline&lt;/li&gt;
&lt;li&gt;routinely building &lt;a href=&#34;https://github.com/grafana/grafana/pull/1569&#34;&gt;a knowledge base of time ranges annotated with a given state for a given alerting concern, which would help in validating the generated status timeline, both visually and in code.  We could compute percentage of issues found, missed, etc&lt;/a&gt;. &#34;unit tests for alerting&#34; my boss called it.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Template could be prettier.  In particular the plots often don&#39;t render very well.  We&#39;re looking into closer Grafana-Bosun integration so I think that will be resolved at some point.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bosun-monitor/bosun/issues/719&#34;&gt;Current logic doesn&#39;t take past outages into account. &#34;just taking enough periods in graphiteBand()&#34; helps alleviate it mostly, but it&#39;s not very robust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;See that drop in the screenshot a bit higher up? That one was preceded by a code deploy event in anthracite which made some changes where a drop in traffic was actually expected.  Would love to be able to mark stuff like this in deploys (like putting in the commit message something like &#34;expect 20-50 drop&#34; and have the monitoring system leverage that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;In conclusion&lt;/h2&gt;
I know many people are struggling with poor alerting rules (static thresholds?)
&lt;br/&gt;As I explained in the previous article I fondly believe that the commonly cited solutions (anomaly detection via machine learning) are a very difficult endeavor and results can be achieved much quicker and simpler.
&lt;br/&gt;While this only focuses on one class of timeseries (it won&#39;t work on diskspace metrics for example) I found this class to be in the most dire need of better fault detection.  Hopefully this is useful to you. Good luck and let me know how it goes!

</description>
      
    </item>
    
    <item>
      <title>Practical fault detection &amp; alerting.  You don&#39;t need to be a data scientist</title>
      <link>https://dieter.plaetinck.be/posts/practical-fault-detection-alerting-dont-need-to-be-data-scientist/</link>
      <pubDate>Thu, 29 Jan 2015 09:08:02 -0400</pubDate>
      
      
      <guid>practical-fault-detection-alerting-dont-need-to-be-data-scientist</guid>
      
      
      <description>&lt;br/&gt;
As we try to retain visibility into our increasingly complicated applications and infrastructure, we&#39;re building out more advanced monitoring systems.
Specifically, a lot of work is being done on alerting via fault and anomaly detection.
This post covers some common notions around these new approaches, debunks some of the myths that ask for over-complicated solutions, and provides some practical pointers that any programmer or sysadmin can implement that don&#39;t require becoming a data scientist.

&lt;br/&gt;
&lt;br/&gt;

&lt;h2&gt;It&#39;s not all about math&lt;/h2&gt;
&lt;p&gt;
I&#39;ve seen smart people who are good programmers decide to tackle anomaly detection on their timeseries metrics.
(anomaly detection is about building algorithms which spot &#34;unusual&#34; values in data, via statistical frameworks).  This is a good reason to brush up on statistics, so you can apply some of those concepts.
But ironically, in doing so, they often seem to think that they are now only allowed to implement algebraic mathematical formulas. No more if/else, only standard deviations of numbers.  No more for loops, only moving averages. And so on.
&lt;br/&gt;When going from thresholds to something (&lt;i&gt;anything&lt;/i&gt;) more advanced, suddenly people only want to work with mathematical formula&#39;s.  Meanwhile we have entire Turing-complete programming languages available, which allow us to execute any logic, as simple or as rich as we can imagine.  Using only math massively reduces our options in implementing an algorithm.
&lt;br/&gt;
&lt;br/&gt;For example I&#39;ve seen several presentations in which authors demonstrate how they try to fine-tune moving average algorithms and try to get a robust base signal to check against but which is also not affected too much by previous outliers, which raise the moving average and might mask subsequent spikes).
&lt;br/&gt;
&lt;img src=&#34;https://dieter.plaetinck.be/files/fault-detection-moving-average.png&#34;&gt;
from &lt;a href=&#34;https://speakerdeck.com/astanway/a-deep-dive-into-monitoring-with-skyline&#34;&gt;A Deep Dive into Monitoring with Skyline&lt;/a&gt;
&lt;br/&gt;
&lt;br/&gt;
But you can&#39;t optimize both, because a mathematical formula at any given point can&#39;t make the distinction between past data that represents &#34;good times&#34; versus &#34;faulty times&#34;.
&lt;br/&gt;However: we wrap the output of any such algorithm with some code that decides what is a fault (or &#34;anomaly&#34; as labeled here) and alerts against it, so why would we hold ourselves back in feeding this useful information back into the algorithm?
&lt;br/&gt;I.e. &lt;b&gt;assist the math with logic&lt;/b&gt; by writing some code to make it work better for us:  In this example, we could modify the code to just retain the old moving average from before the time-frame we consider to be faulty.  That way, when the anomaly passes, we resume &#34;where we left off&#34;.  For timeseries that exhibit seasonality and a trend, we need to do a bit more, but the idea stays the same.   Restricting ourselves to only math and statistics cripples our ability to detect actual &lt;b&gt;faults&lt;/b&gt; (problems).
&lt;/p&gt;
&lt;p&gt;
Another example: During his &lt;a href=&#34;https://coderanger.net/talks/echo/&#34;&gt;Monitorama talk&lt;/a&gt;, Noah Kantrowitz made the interesting and thought provoking observation that Nagios flap detection is basically a low-pass filter.  A few people suggested re-implementing flap detection as a low-pass filter.  This seems backwards to me because reducing the problem to a pure mathematical formula loses information.  The current code has the high-resolution view of above/below threshold and can visualize as such.  Why throw that away and limit your visibility?
&lt;/p&gt;

&lt;h2&gt;Unsupervised machine learning... let&#39;s not get ahead of ourselves.&lt;/h2&gt;
&lt;a href=&#34;https://codeascraft.com/2013/06/11/introducing-kale/&#34;&gt;Etsy&#39;s Kale&lt;/a&gt; has ambitious goals: you configure a set of algorithms, and those algorithms get applied to &lt;b&gt;all&lt;/b&gt; of your timeseries.  Out of that should come insights into what&#39;s going wrong.  The premise is that the found anomalies are relevant and indicative of faults that require our attention.
&lt;br/&gt;I have quite a variety amongst my metrics.  For example diskspace metrics exhibit a sawtooth pattern (due to constant growth and periodic cleanup),
crontabs cause (by definition) periodic spikes in activity, user activity causes a fairly smooth graph which is characterized by its daily pattern and often some seasonality and a long-term trend.
&lt;br/&gt;
&lt;br/&gt;
&lt;img width=&#34;70%&#34; src=&#34;https://dieter.plaetinck.be/files/anomaly-detection-cases.png&#34;&gt;
&lt;br/&gt;
&lt;br/&gt;Because they look differently, anomalies and faults look different too.  In fact, within each category there are multiple problematic scenarios. (e.g. user activity based timeseries should not suddenly drop, but also not be significantly lower than other days, even if the signal stays smooth and follows the daily rhythm)
&lt;br/&gt;
&lt;br/&gt;I have a hard time believing that running the same algorithms on all of that data, and doing minimal configuration on them, will produce meaningful results. At least I expect a very low signal/noise ratio.  Unfortunately, of the people who I&#39;ve asked about their experiences with Kale/Skyline, the only cases where it&#39;s been useful is where skyline input has been restricted to a certain category of metrics - it&#39;s up to you do this filtering (perhaps via carbon-relay rules), potentially running multiple skyline instances - and sufficient time is required hand-selecting the appropriate algorithms to match the data.  This reduces the utility.
&lt;br/&gt;&#34;Minimal configuration&#34; sounds great but this doesn&#39;t seem to work.
&lt;br/&gt;
Instead, something like &lt;a href=&#34;http://bosun.org/&#34;&gt;Bosun&lt;/a&gt; (see further down) where you can visualize your series, experiment with algorithms and see the results in place on current and historical data, to manage alerting rules seems more practical.
&lt;br/&gt;
&lt;br/&gt;Some companies (all proprietary) take it a step further and pay tens of engineers to work on algorithms that inspect all of your series, classify them into categories, &#34;learn&#34; them and automatically configure algorithms that will do anomaly detection, so it can alert anytime something looks unusual (though not necessarily faulty).
This probably works fairly well, but has a high cost, still can&#39;t know everything there is to know about your timeseries, is of no help if your timeseries is behaving faulty from the start and still alerts on anomalous, but irrelevant outliers.
&lt;br/&gt;
&lt;br/&gt;

I&#39;m &lt;b&gt;suggesting we don&#39;t need to make it that fancy&lt;/b&gt; and we can do much better by &lt;b&gt;injecting some domain knowledge&lt;/b&gt; into our monitoring system:
&lt;ul&gt;
&lt;li&gt;using minimal work of classifying metrics via metric meta-data or rules that parse metric id&#39;s, we can automatically infer knowledge of how the series is supposed to behave (e.g. assume that disk_mb_used looks like sawtooth, frontend_requests_per_s daily seasonal, etc) and apply fitting processing accordingly.
&lt;br/&gt;Any sysadmin or programmer can do this, it&#39;s a bit of work but should make a hands-off automatic system such as Kale more accurate.
&lt;br/&gt;Of course, adopting &lt;a href=&#34;http://metrics20.org/&#34;&gt;metrics 2.0&lt;/a&gt; will help with this as well. Another problem with machine learning is they would have to infer how metrics relate against each other, whereas with metric metadata this can easily be inferred (e.g.: what are the metrics for different machines in the same cluster, etc)&lt;/li&gt;
&lt;li&gt;hooking into service/configuration management: you probably already have a service, tool, or file that knows how your infrastructure looks like and which services run where.  We know where user-facing apps run, where crontabs run, where we store log files, where and when we run cleanup jobs.  We know in what ratios traffic is balanced across which nodes, and so on.  Alerting systems can leverage this information to apply better suited fault detection rules.  And you don&#39;t need a large machine learning infrastructure for it. (as an aside: I have a lot more ideas on cloud-monitoring integration)&lt;/li&gt;
&lt;li&gt;Many scientists are working on algorithms that find cause and effect when different series exhibit anomalies, so they can send more useful alerts.  But again here, a simple model of the infrastructure gives you service dependencies in a much easier way.&lt;/li&gt;
&lt;li&gt;hook into your event tracking. If you have something like &lt;a href=&#34;https://github.com/Dieterbe/anthracite/&#34;&gt;anthracite&lt;/a&gt; that lists upcoming press releases, then your monitoring system knows not to alert if suddenly traffic is a bit higher.  In fact, you might want to alert if your announcement did not create a sudden increase in traffic.  If you have a large scale infrastructure, you might go as far as tagging upcoming maintenance windows with metadata so the monitoring knows which services or hosts will be affected (and which shouldn&#39;t).
&lt;/ul&gt;
&lt;br/&gt;
Anomaly detection is useful if you don&#39;t know what you&#39;re looking for, or providing an extra watching eye on your log data.  Which is why it&#39;s commonly used for detecting fraud in security logs and such.
For operational metrics of which admins know what they mean, should and should not look like, and how they relate to each other, we can build more simple and more effective solutions.


&lt;h2&gt;The trap of complex event processing... no need to abandon familiar tools&lt;/h2&gt;
On your quest into better alerting, you soon read and hear about real-time stream processing, and CEP (complex event processing) systems.
It&#39;s not hard to be convinced on their merits:  who wouldn&#39;t want real-time as-soon-as-the-data-arrives-you-can-execute-logic-and-fire-alerts?
&lt;br/&gt;They also come with a fairly extensive and flexible language that lets you program or compose monitoring rules using your domain knowledge.
I believe I&#39;ve heard of &lt;a href=&#34;https://storm.apache.org/&#34;&gt;storm&lt;/a&gt; for monitoring, but &lt;a href=&#34;http://riemann.io/&#34;&gt;Riemann&lt;/a&gt; is the best known of these tools that focus on open source monitoring.
It is a nice, powerful tool and probably the easiest of the CEP tools to adopt.  It can also produce very useful dashboards.
However, these tools come with their own API or language, and programming against real-time streams is quite a paradigm shift which can be hard to justify.  And while their architecture and domain specificity works well for large scale situations, these benefits aren&#39;t worth it for most (medium and small) shops I know:  it&#39;s a lot easier (albeit less efficient) to just query a datastore over and over and program in the language you&#39;re used to.  With a decent timeseries store (or one written to hold the most recent data in memory such as &lt;a href=&#34;https://github.com/dgryski/carbonmem&#34;&gt;carbonmem&lt;/a&gt;) this is not an issue, and the difference in timeliness of alerts becomes negligible!


&lt;h2&gt;An example: finding spikes&lt;/h2&gt;
Like many places, we were stuck with static thresholds, which don&#39;t cover some common failure scenarios.
So I started asking myself some questions:
&lt;br&gt;
&lt;br&gt;
&lt;center&gt;
    &lt;i&gt;which behavioral categories of timeseries do we have, what kind of issues can arise in each category,
        &lt;br/&gt;how does that look like in the data, and what&#39;s the simplest way I can detect each scenario?&lt;/i&gt;
&lt;/center&gt;
&lt;br/&gt;
Our most important data falls within the user-driven category from above where various timeseries from across the stack are driven by, and reflect user activity.  And within this category, the most common problem (at least in my experience) is spikes in the data.  I.e. a sudden drop in requests/s or a sudden spike in response time.  As it turned out, this is much easier to detect than one might think:
&lt;br/&gt;
&lt;img style=&#34;float:left; margin:15px;&#34; src=&#34;https://dieter.plaetinck.be/files/poor-mans-fault-detection.png&#34;&gt;
&lt;br/&gt;
In this example I just track the standard deviation of a moving window of 10 points.  &lt;a href=&#34;http://en.wikipedia.org/wiki/Standard_deviation&#34;&gt;Standard deviation&lt;/a&gt; is simply a measure of how much numerical values differ from each other.  Any sudden spike bumps the standard deviation.   We can then simply set a threshold on the deviation.  Fairly trivial to set up, but has been highly effective for us.
&lt;br/&gt;
&lt;br/&gt;You do need to manually declare what is an acceptable standard deviation value to be compared against, which you will typically deduce from previous data.  This can be annoying until you build an interface to speed up, or a tool to automate this step.
&lt;br/&gt;In fact, it&#39;s trivial to collect previous deviation data (e.g. from the same time of the day, yesterday, or the same time of the week, last week) and automatically use that to guide a threshold.  (&lt;a href=&#34;http://bosun.org/&#34;&gt;Bosun&lt;/a&gt; - see the following section - has &#34;band&#34; and &#34;graphiteBand&#34; functions to assist with this).  This is susceptible to previous outliers, but you can easily select multiple previous timeframes to minimize this issue in practice.
&lt;br/&gt;
&lt;a href=&#34;https://groups.google.com/forum/#!topic/it-telemetry/Zb2H4DP6qtk&#34;&gt;it-telemetry thread&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
So without requiring fancy anomaly detection, machine learning, advanced math, or event processing, we are able to reliably detect faults using simple, familiar tools.  Some basic statistical concepts (standard deviation, moving average, etc) are a must, but nothing that requires getting a PhD.  In this case I&#39;ve been using &lt;a href=&#34;http://graphite.readthedocs.org/en/0.9.10/functions.html#graphite.render.functions.stdev&#34;&gt;Graphite&#39;s stdev function&lt;/a&gt; and &lt;a href=&#34;http://vimeo.github.io/graph-explorer/&#34;&gt;Graph-Explorer&#39;s&lt;/a&gt; alerting feature to manage these kinds of rules, but it doesn&#39;t allow for a very practical iterative workflow, so the non-trivial rules will be going into &lt;a href=&#34;http://bosun.org/&#34;&gt;Bosun&lt;/a&gt;.
&lt;br/&gt;BTW, you can also &lt;a href=&#34;http://obfuscurity.com/2012/05/Polling-Graphite-with-Nagios&#34;&gt;use a script to query Graphite from a Nagios check and do your logic&lt;/a&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;

&lt;!--
divideSeries(stdev(avg(keepLastValue(collectd.dfvimeopweb*.cpu.*.cpu.idle)),10),avg(keepLastValue(collectd.dfvimeopweb*.cpu.*.cpu.idle)))

why keepLastValue?
* sumSeries -&gt; none counts as 0, so you can experience big drops which would trigger anomaly detection or failover
* averageSeries -&gt; effectively ignores none values, so your accuracy can drop a lot in light of none values.

of course this masks when your monitoring breaks, so you still need something else to detect anomalies in the &#34;out-of-date-ness&#34; of your points.
--&gt;

&lt;h2&gt;Workflow is key.  A closer look at bosun&lt;/h2&gt;
One of the reasons we&#39;ve been chasing self-learning algorithms is that we have lost faith in the feasibility of a more direct approach.  We can no longer imagine building and maintaining alerting rules because we have no system that provides powerful alerting, helps us keep oversight and streamlines the process of maintaining and iteratively developing alerting.
&lt;br/&gt;I recently discovered &lt;a href=&#34;http://bosun.org/&#34;&gt;bosun&lt;/a&gt;, an alerting frontend (&#34;IDE&#34;) by Stack Exchange, &lt;a href=&#34;https://www.usenix.org/conference/lisa14/conference-program/presentation/brandt&#34;&gt;presented at Lisa14&lt;/a&gt;.  I highly recommend watching the video.  They have identified various issues that made alerting a pain, and built a solution that makes human-controlled alerting much more doable.  We&#39;ve been using it for a month now with good results (I also gave it support for Graphite).

I&#39;ll explain its merits, and it&#39;ll also become apparent how this ties into some of the things I brought up above:
&lt;img style=&#34;float:left; margin:35px;&#34; src=&#34;http://bosun.org/public/ss_rule_timeline.png&#34; width=&#34;15%&#34;&gt;
&lt;ul&gt;
&lt;li&gt;in each rule you can query any data you need from any of your datasources (currently graphite, openTSDB, and elasticsearch).  You can call various &lt;a href=&#34;http://bosun.org/configuration.html&#34;&gt;functions, boolean logic, and math&lt;/a&gt;.  Although it doesn&#39;t expose you a full programming language, the bosun language as it stands is fairly complete, and can be extended to cover
new needs.  You choose your own alerting granularity (it can automatically instantiate alerts for every host/service/$your_dimension/... it finds within your metrics, but you can also trivially aggregate across dimensions, or both).  This makes it easy to create advanced alerts that cover a lot of ground, making sure you don&#39;t get overloaded by multiple smaller alerts.  And you can incorporate data of other entities within the system, to simply make better alerting decisions.&lt;/li&gt;
&lt;li&gt;you can define your own templates for alert emails, which can contain any html code.  You can trivially plot graphs, build tables, use colors and so on.  Clear, context-rich alerts which contain all information you need!&lt;/li&gt;
&lt;li&gt;As alluded to, the bosun authors spent a lot of time &lt;a href=&#34;https://www.usenix.org/conference/lisa14/conference-program/presentation/brandt&#34;&gt;thinking about, and solving&lt;/a&gt; the workflow of alerting.  As you work on advanced fault detection and alerting rules you need to be able to see the value of all data (including intermediate computations) and visualize it.  Over time, you will iteratively adjust the rules to become better and more precise.  Bosun supports all of this.  You can execute your rules on historical data and see exactly how the rule performs over time, by displaying the status in a timeline view and providing intermediate values.  And finally, you can see how the alert emails will be rendered &lt;i&gt;as you work on the rule and the templates&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

The &lt;a href=&#34;http://bosun.org/examples.html&#34;&gt;examples&lt;/a&gt; section gives you an idea of the things you can do.
&lt;br/&gt;I haven&#39;t seen anything solve a pragmatic alerting workflow like bosun (hence their name &#34;alerting IDE&#34;), and its ability to not hold you back as you work on your alerts is refreshing. Furthermore, the built-in processing functions are very &lt;b&gt;complimentary to graphite&lt;/b&gt;:
Graphite has a decent API which works well at aggregating and transforming one or more series into one new series; the bosun language is great at reducing series to single numbers, providing boolean logic, and so on, which you need to declare alerting expressions.  This makes them a great combination.
&lt;br/&gt;Of course Bosun isn&#39;t perfect either.  Plenty of things can be done to make it (and alerting in general) better.  But it does exemplify many of my points, and it&#39;s a nice leap forward in our monitoring toolkit.

&lt;h2&gt;Conclusion&lt;/h2&gt;
Many of us aren&#39;t ready for some of the new technologies, and some of the technology isn&#39;t - and perhaps never will be - ready for us.
As an end-user investigating your options, it&#39;s easy to get lured in a direction that promotes over-complication and stimulates your inner scientist but just isn&#39;t realistic.
&lt;br/&gt;Taking a step back, it becomes apparent we &lt;b&gt;can&lt;/b&gt; setup automated fault detection.  But instead of using machine learning, use metadata, instead of trying to come up with all-encompassing holy grail of math, use several rules of code that you prototype and iterate over, then reuse for similar cases.  Instead of requiring a paradigm shift, use a language you&#39;re familiar with.  Especially by polishing up the workflow, we can make many &#34;manual&#34; tasks much easier and quicker.  I believe we can keep polishing up the workflow, distilling common patterns into macros or functions that can be reused, leveraging metric metadata and other sources of truth to configure fault detection, and perhaps even introducing &#34;metrics coverage&#34;, akin to &#34;code coverage&#34;: verify how much, and which of the metrics are adequately represented in alerting rules, so we can easily spot which metrics have yet to be included in alerting rules.  I think there&#39;s a lot of things we can do to make fault detection work better for us, but we have to look in the right direction.

&lt;h2&gt;PS: leveraging metrics 2.0 for anomaly detection&lt;/h2&gt;
In my last &lt;a href=&#34;https://www.usenix.org/conference/lisa14/conference-program/presentation/plaetinck&#34;&gt;metrics 2.0 talk, at LISA14&lt;/a&gt; I explored a few ideas on leveraging metrics 2.0 metadata for alerting and fault detection, such as automatically discovering error metrics across the stack, getting high level insights via tags, correlation, etc. If you&#39;re interested, it&#39;s in the video from 24:55 until 29:40
&lt;br/&gt;
&lt;br/&gt;
&lt;center&gt;
&lt;img src=&#34;https://dieter.plaetinck.be/files/metrics20-alerting.png&#34; width=&#34;50%&#34;&gt;
&lt;/center&gt;

&lt;!--
It&#39;s not about alerts anyway.

alerts are an immensely crude approach to raising operator awareness.
They are basically boolean: either they interrupt your workflow or they don&#39;t.  There&#39;s no in between.
Yes, you can just check your alert emails &#34;once in a while&#34;, but then realize that after an email or text is sent,
there is no way to update them with new information.  Which is really limiting once you start thinking about it.
Updates have to be provided via new &#34;alerts&#34;, or they are available in the monitoring interface but there&#39;s no way to tell
by just glancing at your alert overview.  You might be looking at very out of date information.
-&gt; only sent alerts for critical things.
--&gt;
</description>
      
    </item>
    
  </channel>
</rss>
