{"id":1622,"date":"2014-06-23T18:00:59","date_gmt":"2014-06-23T16:00:59","guid":{"rendered":"http:\/\/www.unicoda.com\/?p=1622"},"modified":"2014-06-23T15:17:23","modified_gmt":"2014-06-23T13:17:23","slug":"magical-graphite","status":"publish","type":"post","link":"https:\/\/www.unicoda.com\/?p=1622","title":{"rendered":"Magical Graphite"},"content":{"rendered":"<p>Or, \u00ab\u00a0What I&rsquo;ve learned about Graphite configuration\u00a0\u00bb.<\/p>\n<p>Last week, I worked on configuring Graphite and had to understand how it stores and aggregates data. So here are a few facts.<\/p>\n<h3>Graphite Retention<\/h3>\n<p>The way our data will be stored is described in <em>\/opt\/graphite\/conf\/storage-schemas.conf<\/em>. As an example:<\/p>\n<pre>[default]\r\n pattern = .*\r\n retentions = 1s:30m,1m:1d,5m:2y<\/pre>\n<p>This worked great when I was looking at data from the last 30 minutes.<br \/>\nIf I was trying to display last hour metrics: nothing.<br \/>\nDrawing null as zero was giving me a horizontal line at the bottom of the graph.<\/p>\n<h3>The magic of aggregation<\/h3>\n<p>This behaviour comes from the file <em>\/opt\/graphite\/conf\/storage-aggregation.conf<\/em> where we find the following lines:<\/p>\n<pre>[99_default_avg]\r\n pattern = .*\r\n xFilesFactor = 0.5\r\n aggregationMethod = average<\/pre>\n<p>Our problem comes from<em> xFilesFactor<\/em>. It means that by default, we need at least 50% of the data to be non-null to store an average value. Think about it.<\/p>\n<p>So here, I&rsquo;m having a metric every second during 30 minutes. If Graphite doesn&rsquo;t have something for a given second, the value is set to null. Fine, let&rsquo;s move forward.<br \/>\nFor interval higher than 30 minutes (and lower than a day), Graphite will gather data based on the aggregation configured. So it will average data and set the value null if it has less than 50% usable values (not null).<\/p>\n<p>In our case, Graphite tries to average one minute of data (1m:1d) with the precision of 1s from the first retention rule (1s:30m). To understand why nothing is displayed, consider I&rsquo;m Collectd is sending data to Graphite. On average, metrics are arriving every 3s. On a one minute interval, we gather 20 values but Graphite is considering 60 values, 40 being null. We only have 33% (0.33) metrics usable which is lower than 50% Graphite is waiting for so the averaged value is set to null.<\/p>\n<h3>The art of confusion<\/h3>\n<p>Now that we updated our configuration, set <em>xFilesFactor<\/em> to 0 to be sure, restart carbon-cache, everything should work fine&#8230;<\/p>\n<p>But that&rsquo;s not the case; no change.<\/p>\n<p>In fact, previous configuration is still being used in wsp storage files. We can check it with <em>whisper-info.py<\/em>.<\/p>\n<pre>whisper-info.py \/opt\/graphite\/storage\/whisper\/collectd\/test-java01\/cpu-0\/cpu-user.wsp\r\n \r\n maxRetention: 63072000\r\n xFilesFactor: 0.5\r\n aggregationMethod: average\r\n fileSize: 2561812\r\n\r\nArchive 0\r\n retention: 1800\r\n secondsPerPoint: 1\r\n points: 1800\r\n size: 21600\r\n offset: 52\r\nArchive 1\r\n retention: 86400\r\n secondsPerPoint: 60\r\n points: 1440\r\n size: 17280\r\n offset: 21652\r\nArchive 2\r\n retention: 63072000\r\n secondsPerPoint: 300\r\n points: 210240\r\n size: 2522880\r\n offset: 38932<\/pre>\n<p>See, we still have <em>xFilesFactor<\/em>: 0.5.<br \/>\nIf you don&rsquo;t care about previous data, a good solution is to delete files so that the new parameters will be used (<em>rm -rf \/opt\/graphite\/storage\/whisper\/collectd\/<\/em>). Maybe it&rsquo;s a little bit overkill, (but easy and fast).<\/p>\n<p>The other solution consists in using <em>whisper-resize.py<\/em> to enforce the new configuration.<br \/>\n<em>whisper-resize.py \/opt\/graphite\/storage\/whisper\/collectd\/test-java01\/cpu-0\/cpu-user.wsp 3s:30m,1m:1d,5m:2y &#8211;xFilesFactor=0.1<\/em><\/p>\n<p>The above works fine, but this is the other way to configure how many metrics Graphite can keep. It has the format<em> n:i<\/em>, which means we store a measure every <em>n<\/em> seconds and we want <em>i<\/em> points to be stored (computed with interval \/ n).<\/p>\n<p style=\"text-align: center;\">\n<span style=\"text-decoration: underline;\">Example:<\/span> <em>3s:30m<\/em><br \/>\n30m = 1800s<br \/>\n1800 \/ 3 = 600<\/p>\n<p style=\"text-align: center;\">3:600<\/p>\n<p style=\"text-align: center;\">So 3s:30m,1m:1d,5m:2y gives us 3:600 60:1440 300:210380.<\/p>\n<blockquote>\n<p style=\"text-align: center;\">\u00ab\u00a0An average Gregorian year is 365.2425 days = 52.1775 weeks = 8765.82 hours = 525949.2 minutes = 31556952 seconds (mean solar, not SI).\u00a0\u00bb Wikipedia<\/p>\n<\/blockquote>\n<h3>Note<\/h3>\n<p>Thing to remember concerning storage-schemas.conf (taken from <a href=\"http:\/\/graphite.readthedocs.org\/\" target=\"_blank\">Graphite doc<\/a>):<\/p>\n<blockquote><p>\u00ab\u00a0Changing this file will not affect already-created .wsp files. Use whisper-resize.py to change those.\u00a0\u00bb<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Or, \u00ab\u00a0What I&rsquo;ve learned about Graphite configuration\u00a0\u00bb. Last week, I worked on configuring Graphite and had to understand how it stores and aggregates data. So here are a few facts. Graphite Retention The way our data will be stored is described in \/opt\/graphite\/conf\/storage-schemas.conf. As an example: [default] pattern = .* retentions = 1s:30m,1m:1d,5m:2y This worked &hellip; <a href=\"https:\/\/www.unicoda.com\/?p=1622\" class=\"more-link\">Continuer la lecture<span class=\"screen-reader-text\"> de &laquo;&nbsp;Magical Graphite&nbsp;&raquo;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[126],"tags":[187,92,188,184,189],"class_list":["post-1622","post","type-post","status-publish","format-standard","hentry","category-logiciellibre","tag-aggregation","tag-configuration","tag-graph","tag-graphite","tag-xfilesfactor"],"_links":{"self":[{"href":"https:\/\/www.unicoda.com\/index.php?rest_route=\/wp\/v2\/posts\/1622","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.unicoda.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.unicoda.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.unicoda.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.unicoda.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1622"}],"version-history":[{"count":8,"href":"https:\/\/www.unicoda.com\/index.php?rest_route=\/wp\/v2\/posts\/1622\/revisions"}],"predecessor-version":[{"id":1632,"href":"https:\/\/www.unicoda.com\/index.php?rest_route=\/wp\/v2\/posts\/1622\/revisions\/1632"}],"wp:attachment":[{"href":"https:\/\/www.unicoda.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.unicoda.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.unicoda.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}