|
| 1 | +--- |
| 2 | +title: Hosted Metrics - Graphite |
| 3 | +header: false |
| 4 | +--- |
| 5 | + |
| 6 | +# Hosted Metrics - Graphite |
| 7 | + |
| 8 | +Grafana Labs' Hosted metrics Graphite service offers a graphite-compatible monitoring backend as a service. |
| 9 | +It acts and behaves as a regular graphite datasource within Grafana (or other tools), but behind the scenes, it is a sophisticated platform run by a team of dedicated engineers. |
| 10 | + |
| 11 | +* [data ingestion](#data-ingestion) |
| 12 | +* [http api](#http-api) |
| 13 | +* [faq](#faq) |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## Data Ingestion |
| 18 | + |
| 19 | +We support: |
| 20 | +* [carbon-relay-ng](https://github.com/graphite-ng/carbon-relay-ng), which is a graphite carbon relay, which supports aggregations and sending data to our endpoint over a secure, robust transport. |
| 21 | +* custom tools that use our API. See our [golang, python and shell examples](https://github.com/grafana/hosted-metrics-sender-example) |
| 22 | +* direct carbon input. This is discouraged though, as it is not reliable over the internet and not secure. |
| 23 | + |
| 24 | +The recommended and most popular option is using carbon-relay-ng. |
| 25 | +Customers typically deploy using either of these 2 options: |
| 26 | + |
| 27 | +* run the relay as an extra component external to your existing graphite pipeline. Data can be directed to it from any existing carbon relay. |
| 28 | +* replace an existing carbon-relay with carbon-relay-ng |
| 29 | + |
| 30 | +If your Graphite stack does not currently contain any relay, then you can simply add carbon-relay-ng, have your clients (statsd, collectd, diamond, etc) send data to the relay, which in turn can send data to your existing graphite server *and* to our platform. |
| 31 | + |
| 32 | +When creating a Hosted Metrics Graphite instance, we provide a carbon-relay-ng config file that you can plug in and be ready to use out of the box. |
| 33 | +We also have Grafana Labs engineers ready to advise further on set up, if needed. |
| 34 | + |
| 35 | +--- |
| 36 | + |
| 37 | +## HTTP API |
| 38 | + |
| 39 | +The HTTP API is the same as that of Graphite, with the addition of ingestion, authentication and meta tags. |
| 40 | + |
| 41 | +First of all, there are two endpoints you will be talking to. They are provided in your grafana.com Hosted Metrics instance UI. |
| 42 | +They will look something like: |
| 43 | + |
| 44 | +* `<base_in>` : `https://tsdb-<id>.hosted-metrics.grafana.net/metrics` |
| 45 | +* `<base_out>` : `https://tsdb-<id>.hosted-metrics.grafana.net/graphite` |
| 46 | + |
| 47 | +Furthermore, you will need to provision API keys to talk to the API. Each key will be of one of these types: |
| 48 | + |
| 49 | +* Viewer |
| 50 | +* MetricsPublisher |
| 51 | +* Editor |
| 52 | +* Admin |
| 53 | + |
| 54 | + |
| 55 | +## Common Request Parameters |
| 56 | + |
| 57 | +Many of the API methods involve using Graphite patterns (queries), tag queries and the standard Graphite from/to syntax. |
| 58 | + |
| 59 | +### Graphite Patterns |
| 60 | + |
| 61 | +[Graphite patterns](https://graphite.readthedocs.io/en/latest/render_api.html#paths-and-wildcards) are queries that involve glob patterns (`*`, `{}`, `[]`, `?`). |
| 62 | + |
| 63 | +### Tag Expressions |
| 64 | + |
| 65 | +Tags expressions are strings, and may have the following formats: |
| 66 | + |
| 67 | +``` |
| 68 | +tag=spec tag value exactly matches spec |
| 69 | +tag!=spec tag value does not exactly match spec |
| 70 | +tag=~value tag value matches the regular expression spec |
| 71 | +tag!=~spec tag value does not match the regular expression spec |
| 72 | +``` |
| 73 | + |
| 74 | +Any tag spec that matches an empty value is considered to match series that don’t have that tag, and at least one tag spec must require a non-empty value. |
| 75 | +Regular expression conditions are treated as being anchored at the start of the value. |
| 76 | + |
| 77 | +### From/To (Until) |
| 78 | + |
| 79 | +[Graphite from/to](https://graphite.readthedocs.io/en/latest/render_api.html#from-until) |
| 80 | + |
| 81 | +## Endpoints |
| 82 | + |
| 83 | + |
| 84 | +### Adding New Data: Posting To `/metrics` |
| 85 | + |
| 86 | +The main entry point for any publisher to publish data to, be it [carbon-relay-ng](https://github.com/graphite-ng/carbon-relay-ng/), or any other script or application such as the [hosted-metrics-sender-example](https://github.com/grafana/hosted-metrics-sender-example) |
| 87 | + |
| 88 | +* Method: POST |
| 89 | +* API key type: any (including Viewer) |
| 90 | + |
| 91 | +#### Headers |
| 92 | + |
| 93 | +* `Authorization: Bearer <api-key>` required |
| 94 | +* `Content-Type`: supports 3 values: |
| 95 | + - `application/json`: the simplest one, and the one used here |
| 96 | + - `rt-metric-binary`: same datastructure, but messagepack encoded. (see [the MetricData Marshal/Encode methods](https://godoc.org/github.com/grafana/metrictank/schema#MetricData)) |
| 97 | + - `rt-metric-binary-snappy`: same as above, but snappy compressed. |
| 98 | + |
| 99 | +#### Data Format |
| 100 | + |
| 101 | +Each metricpoint message can have the following properties: |
| 102 | +``` |
| 103 | +name // graphite style name (required) |
| 104 | +interval // the resolution of the metric in seconds (required) |
| 105 | +value // float64 value (required) |
| 106 | +time // unix timestamp in seconds (required) |
| 107 | +tags // list of key=value pairs of tags (optional) |
| 108 | +``` |
| 109 | + |
| 110 | +#### Example |
| 111 | + |
| 112 | +```sh |
| 113 | +timestamp_now_rounded=$(($(date +%s) / 10 * 10)) |
| 114 | +timestamp_prev_rounded=$((timestamp_now_rounded - 10)) |
| 115 | + |
| 116 | +curl -X POST -H "Authorization: Bearer $key" -H "Content-Type: application/json" "$out" -d '[{ |
| 117 | + "name": "test.metric", |
| 118 | + "interval": 10, |
| 119 | + "value": 12.345, |
| 120 | + "time": '$timestamp_prev_rounded' |
| 121 | +}, |
| 122 | +{ |
| 123 | + "name": "test.metric", |
| 124 | + "interval": 10, |
| 125 | + "value": 12.345, |
| 126 | + "time": '$timestamp_now_rounded' |
| 127 | +}, |
| 128 | +{ |
| 129 | + "name": "test.metric.tagged", |
| 130 | + "interval": 10, |
| 131 | + "value": 1, |
| 132 | + "tags": ["foo=bar", "baz=quux"], |
| 133 | + "time": '$timestamp_prev_rounded' |
| 134 | +}, |
| 135 | +{ |
| 136 | + "name": "test.metric.tagged", |
| 137 | + "interval": 10, |
| 138 | + "value": 2, |
| 139 | + "tags": ["foo=bar", "baz=quux"], |
| 140 | + "time": '$timestamp_now_rounded' |
| 141 | +} |
| 142 | +]' |
| 143 | + |
| 144 | +``` |
| 145 | + |
| 146 | +### Deleting Metrics |
| 147 | +#### Non-tagged With `/metrics/delete` |
| 148 | + |
| 149 | +Deletes metrics which match the `query` and all child nodes. |
| 150 | + |
| 151 | +Note that unlike the find and render patterns, these queries are recursive. |
| 152 | +So if the delete query matches a branch, **every** series under that branch will be deleted. |
| 153 | + |
| 154 | +* Method: POST |
| 155 | +* API key type: |
| 156 | + |
| 157 | +##### Parameters |
| 158 | + |
| 159 | +* user name: api_key |
| 160 | +* password: Your Grafana.com API Key |
| 161 | +* query (required): [Graphite pattern] (#graphite-patterns) |
| 162 | + |
| 163 | +##### Example |
| 164 | + |
| 165 | +```sh |
| 166 | +curl -u "api_key:<Your Grafana.com API Key>" https://<tsdbgw>/metrics/delete -d query=some.series.to.delete.* |
| 167 | +``` |
| 168 | + |
| 169 | +### Finding Metrics |
| 170 | +#### Non-tagged With `/metrics/find` |
| 171 | + |
| 172 | +Returns metrics which match the `query` and have received an update since `from`. |
| 173 | + |
| 174 | +* Method: GET or POST |
| 175 | +* API key type: any (including MetricsPublisher) |
| 176 | + |
| 177 | +##### Headers |
| 178 | + |
| 179 | +* `Authorization: Bearer <api-key>` required |
| 180 | + |
| 181 | +##### Parameters |
| 182 | + |
| 183 | +* query (required): [Graphite pattern](#graphite-patterns) |
| 184 | +* format: json, treejson, completer, pickle, or msgpack. (defaults to json) |
| 185 | +* jsonp: true/false: enables jsonp |
| 186 | +* from: Graphite from time specification (defaults to now-24hours) |
| 187 | + |
| 188 | +##### Output formats |
| 189 | + |
| 190 | +* json, treejson (default/unspecified): the standard format |
| 191 | +* completer: used for graphite-web's completer UI |
| 192 | +* msgpack: optimized transfer format |
| 193 | +* pickle: deprecated |
| 194 | + |
| 195 | + |
| 196 | +##### Example |
| 197 | + |
| 198 | +```sh |
| 199 | +curl -H "Authorization: Bearer $key" "$base_out/metrics/find?query=metrictank" |
| 200 | +[ |
| 201 | + { |
| 202 | + "allowChildren": 1, |
| 203 | + "expandable": 1, |
| 204 | + "leaf": 0, |
| 205 | + "id": "metrictank", |
| 206 | + "text": "metrictank", |
| 207 | + "context": {} |
| 208 | + } |
| 209 | +] |
| 210 | +``` |
| 211 | + |
| 212 | +The response indicates that there are metric names that live under the "metrictank" term (it is expandable) |
| 213 | +and there is no data under the name "metrictank" (it is not a leaf node). |
| 214 | + |
| 215 | +So we update the query to see what we can expand to: |
| 216 | + |
| 217 | +```sh |
| 218 | +curl -H "Authorization: Bearer $key" "$base_out/metrics/find?query=metrictank.*" |
| 219 | +[ |
| 220 | + { |
| 221 | + "allowChildren": 1, |
| 222 | + "expandable": 1, |
| 223 | + "leaf": 0, |
| 224 | + "id": "metrictank.aggstats", |
| 225 | + "text": "aggstats", |
| 226 | + "context": {} |
| 227 | + } |
| 228 | +] |
| 229 | +``` |
| 230 | + |
| 231 | +The response for the updated query shows which data lives under the "metrictank" name, in this case the tree extends under "metrictank.aggstats". |
| 232 | + |
| 233 | +As we continue to dig deeper into the tree, by updating our query based on what we get back, we eventually end up at the leaf: |
| 234 | + |
| 235 | +```sh |
| 236 | +curl -H "Authorization: Bearer $key" "$out/metrics/find?query=metrictank.aggstats.*.tank.metrics_active.gauge32" |
| 237 | +[ |
| 238 | + { |
| 239 | + "allowChildren": 0, |
| 240 | + "expandable": 0, |
| 241 | + "leaf": 1, |
| 242 | + "id": "metrictank.aggstats.us-east2-id-name.tank.metrics_active.gauge32", |
| 243 | + "text": "gauge32", |
| 244 | + "context": {} |
| 245 | + } |
| 246 | +] |
| 247 | +``` |
| 248 | + |
| 249 | +#### Tagged With `/tags/findSeries` |
| 250 | + |
| 251 | +Returns metrics which match tag queries and have received an update since `from`. |
| 252 | +Note: the returned results are not deduplicated and in certain cases it is possible |
| 253 | +that duplicate entries will be returned. |
| 254 | + |
| 255 | +* Method: GET or POST |
| 256 | +* API key type: any (including MetricsPublisher) |
| 257 | + |
| 258 | +##### Headers |
| 259 | + |
| 260 | +* `Authorization: Bearer <api-key>` required |
| 261 | + |
| 262 | +##### Parameters |
| 263 | + |
| 264 | +* expr (required): a list of [tag expressions](#tag-expressions) |
| 265 | +* from: Graphite [from time specification](#fromto) (optional. defaults to now-24hours) |
| 266 | + |
| 267 | +##### Example |
| 268 | + |
| 269 | +```sh |
| 270 | +curl -H "Authorization: Bearer $key" "$out/tags/findSeries?expr=datacenter=dc1&expr=server=web01" |
| 271 | + |
| 272 | +[ |
| 273 | + "disk.used;datacenter=dc1;rack=a1;server=web01" |
| 274 | +] |
| 275 | +``` |
| 276 | + |
| 277 | +--- |
| 278 | + |
| 279 | +## FAQ |
| 280 | + |
| 281 | +### Can I use tags? |
| 282 | + |
| 283 | +Yes, our platform supports graphite tags as well as [meta tags](https://grafana.com/blog/2019/04/09/metrictank-meta-tags/), allowing to add extra metadata tags your series. |
| 284 | + |
| 285 | +### Can I import my existing data? |
| 286 | + |
| 287 | +You can import pre-existing data into the hosted platform, from either a Graphite or metrictank installation. |
| 288 | +We either provide you with the tools and instructions, or if provided access, we offer this service for a hands-off experience. |
| 289 | +Grafana dashboards can also be imported if you choose to use a hosted Grafana instance. |
| 290 | + |
| 291 | +### How do I send data to the service? |
| 292 | + |
| 293 | +See [data ingestion](#data-ingestion) |
| 294 | + |
| 295 | +### How does this compare to stock graphite? |
| 296 | + |
| 297 | +The hosted platform is built on top of [metrictank](/oss/metrictank) and [graphite](/oss/graphite) |
| 298 | +Important differences with stock Graphite to be aware of: |
| 299 | + |
| 300 | +* support for meta tags |
| 301 | +* the platform is optimized for append-only workloads. While historical data can be imported, we generally don't support out of order writes. |
| 302 | +* timeseries can change resolution (interval) over time, they will be merged automatically. |
| 303 | + |
| 304 | +## Do I have to use hosted grafana or exclusively the hosted platform? |
| 305 | + |
| 306 | +No, the hosted platform is a datasource that you can use however you like. E.g. in combination with other datasources, and queried from any Grafana instance or other client. |
0 commit comments