{"id":2257,"date":"2013-07-13T18:29:40","date_gmt":"2013-07-14T01:29:40","guid":{"rendered":"https:\/\/mathpirate.net\/log\/?p=2257"},"modified":"2013-07-13T18:29:40","modified_gmt":"2013-07-14T01:29:40","slug":"overwriting-anomalous-data-in-graphite","status":"publish","type":"post","link":"https:\/\/mathpirate.net\/log\/2013\/07\/13\/overwriting-anomalous-data-in-graphite\/","title":{"rendered":"Overwriting Anomalous Data in Graphite"},"content":{"rendered":"<p>Recently, I&#8217;ve been setting up a home sensor array using Arduino modules, which feed data into a Graphite instance running on a Raspberry Pi.\u00c2\u00a0 Along the way, through faulty wiring, faulty coding, or the effects of sunspots, I&#8217;ve ended up with some bad data ending up in Graphite.<\/p>\n<p>And by bad data, I mean that my living room sensor once reported that it was 289,268 degrees C one day.\u00c2\u00a0 Since my house and the surrounding neighborhood show no signs of having been\u00c2\u00a0vaporized, I am forced to believe that reading is incorrect.<\/p>\n<p><a href=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite250K1.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-2261\" title=\"Graphite250K\" src=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite250K1.png\" alt=\"\" width=\"586\" height=\"308\" srcset=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite250K1.png 586w, https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite250K1-300x157.png 300w\" sizes=\"(max-width: 586px) 100vw, 586px\" \/><\/a><\/p>\n<p>Since having a temperature reading of several hundred thousand degrees throws off the range of the graph somewhat, I wanted to get rid of that errant data point. \u00c2\u00a0I looked around for a Whisper DB editor, but didn&#8217;t find anything. \u00c2\u00a0Graphite&#8217;s all open source, so I probably could build one myself, but I really didn&#8217;t feel like going that far. \u00c2\u00a0Then I remembered the &#8220;Feeding in Your Data&#8221; page in the Graphite docs, where it talks about using the command line to send data values. \u00c2\u00a0Maybe if you can write datapoints using this method, you can overwrite datapoints using this method, too. \u00c2\u00a0So, I figured I&#8217;d give it a shot.<\/p>\n<p>The example they gave on the page is this:<\/p>\n<pre>echo \"local.random.diceroll 4 `date +%s`\" | nc ${SERVER} ${PORT};<\/pre>\n<p>The &#8220;local.random.diceroll&#8221; part is your counter name.<\/p>\n<p>The &#8220;4&#8221; part is the data you want to write.<\/p>\n<p>And the &#8220;date +%s&#8221; is just a fancy way of saying the Unix Epoch Timestamp of Now.<\/p>\n<p>So, in my case, I&#8217;d overwrite the counter &#8220;stats.gauges.Temperature.LivingRoom&#8221; with a comfortable room temparature value of somewhere between 20 and 25. \u00c2\u00a0But what about the timestamp? \u00c2\u00a0I can&#8217;t just go in and hope I get the timestamp. \u00c2\u00a0I can guess from that graph that it happened sometime around 00:32:30, but who knows if I&#8217;m right. \u00c2\u00a0And what timezone is Whisper using? \u00c2\u00a0Local time? \u00c2\u00a0UTC? \u00c2\u00a0And if it&#8217;s UTC, is that + 8 hours or +7 hours this time of year&#8230;? \u00c2\u00a0I needed a better way to get the exact timestamp.<\/p>\n<p>Fortunately, Graphite makes that relatively easy. \u00c2\u00a0You see, you can get the data in json format if you want. \u00c2\u00a0While it&#8217;s not as pretty as the graph, it does have the exact values of the timestamp you&#8217;re looking for. \u00c2\u00a0Getting the json is fairly straightforward. \u00c2\u00a0First, you go to the Graphite Browser and find the data you want to fix. \u00c2\u00a0Once you have it in the window, right click and open the graph in a new tab (Or copy\/paste the graph URL, either way works). \u00c2\u00a0From there, edit the URL of the graph, by adding &#8220;&amp;format=json&#8221; to the end. \u00c2\u00a0Load that page and your screen will fill with json datapoints. \u00c2\u00a0Like so:<\/p>\n<p><a href=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/2013-07-13-180644_1824x984_scrot.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-2263\" title=\"2013-07-13-180644_1824x984_scrot\" src=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/2013-07-13-180644_1824x984_scrot.png\" alt=\"\" width=\"807\" height=\"240\" srcset=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/2013-07-13-180644_1824x984_scrot.png 807w, https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/2013-07-13-180644_1824x984_scrot-300x89.png 300w\" sizes=\"(max-width: 807px) 100vw, 807px\" \/><\/a><\/p>\n<p>In that sea of numbers, find the value you want to replace. \u00c2\u00a0In my case, it&#8217;s easy to find, because it&#8217;s the one claiming that my living room jumped up to 6 times hotter than the surface of the sun for a moment. \u00c2\u00a0The second value in that datapoint is the timestamp I need to wipe out the errant temperature spike. \u00c2\u00a0Now that I have it, I can run the following command to put things right:<\/p>\n<pre>echo \"stats.gauges.Temperature.LivingRoom 22.8 1373614500\" | nc localhost 2003<\/pre>\n<p>And now my living room is back to a comfortable 22.8 degrees.<\/p>\n<p><a href=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite228.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-2264\" title=\"Graphite228\" src=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite228.png\" alt=\"\" width=\"586\" height=\"308\" srcset=\"https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite228.png 586w, https:\/\/mathpirate.net\/log\/wp-content\/uploads\/2013\/07\/Graphite228-300x157.png 300w\" sizes=\"(max-width: 586px) 100vw, 586px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, I&#8217;ve been setting up a home sensor array using Arduino modules, which feed data into a Graphite instance running on a Raspberry Pi.\u00c2\u00a0 Along the way, through faulty wiring, faulty coding, or the effects of sunspots, I&#8217;ve ended up with some bad data ending up in Graphite. And by bad data, I mean that [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[7,1],"tags":[218,217],"_links":{"self":[{"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/posts\/2257"}],"collection":[{"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/comments?post=2257"}],"version-history":[{"count":3,"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/posts\/2257\/revisions"}],"predecessor-version":[{"id":2265,"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/posts\/2257\/revisions\/2265"}],"wp:attachment":[{"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/media?parent=2257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/categories?post=2257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mathpirate.net\/log\/wp-json\/wp\/v2\/tags?post=2257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}