Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/metrico/distributed-clickhouse-prometheus
Distributed Metrics for ClickHouse + URL Engine (How-To)
https://github.com/metrico/distributed-clickhouse-prometheus
clickhouse clickhouse-server deta deta-base distributed metrics prometheus serverless timeseries url-engine
Last synced: 6 days ago
JSON representation
Distributed Metrics for ClickHouse + URL Engine (How-To)
- Host: GitHub
- URL: https://github.com/metrico/distributed-clickhouse-prometheus
- Owner: metrico
- Created: 2022-07-31T12:06:36.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-08-04T09:11:36.000Z (over 2 years ago)
- Last Synced: 2024-11-07T15:06:10.837Z (about 2 months ago)
- Topics: clickhouse, clickhouse-server, deta, deta-base, distributed, metrics, prometheus, serverless, timeseries, url-engine
- Homepage: https://urleng.com
- Size: 72.3 KB
- Stars: 7
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# _"Frugal Metrics"_
_Metrics can be lots fun, until you have to share them between a bunch of distributed servers... but fear not!_
## Distributed timeseries/metrics endpoint with [UrlEng](https://urleng.com) + [ClickHouse](https://clickhouse.com/docs)
Let's build a serverless prometheus metrics store & publisher for ClickHouse using [urleng.com](https://urleng.com)
* no coding, no signups, no logins - batteries included! :battery:
* zero config distributed table, simply accessible from anywhere
* custom HTTP prometheus /metrics scraping endpoint w/ auto-expiration
* persistent storage courtesy of [deta cloud](https://deta.sh)
## Let's get started!
### Storing metrics in [UrlEng](https://urleng.com)
[UrlEng](https://urleng.com) is a _free serverless pastie_ made for ClickHouse tables.
Let's use it to store a distributed table with a simple schema for our metrics:
| key | help | value | tags | __expires |
|--- |--- |--- |--- |--- |
| metric name | metric help text | metric value | optional json tags | optional expiration unix ts |To begin we will keep things basic - performance is not the challenge here but rather flexibiity. A few notes:
* _INSERTs for the same key are considered UPDATEs in URL tables_
* _JSON Tags must be present or empty stringed_
* _Metrics can auto-expire using the `__expires` column and a future unix timestamp_
* **REPLACE `/metrixxx` WITH YOUR OWN UNIQUE STRING OR BE DOOMED**
Simple it is! Let's **INSERT** our first little metric:
```sql
INSERT INTO FUNCTION url('https://urleng.com/metrixxx', JSONEachRow, 'key String, help String, value Float64, __expire UInt64, tags String') VALUES ('mygauge', 'my little metric', 100, toUnixTimestamp(now()+300), '{"le":"0.05"}')
```
That's easy. Let's take a closer look at our serverless URL table:
```sql
SELECT * FROM url('https://urleng.com/metrixxx', JSONEachRow)┌─__expires──┬─help──────────────────┬─key──────┬─tags──────────┬─value─┐
│ 1659015366 │ my little metric │ mygauge │ {"le":"0.05"} │ 100 │
└────────────┴───────────────────────┴──────────┴───────────────┴───────┘```
Looking good! Our distributed metrics table is ready. _Get a materialized view up to insert some fun data._
:tooth: ... but the output is still a bit boring and can't be scraped, so its time to change the output format!
### FORMAT Prometheus
ClickHouse comes with a built in suport for the Prometheus format - its a little strict, but it works, so let's use it!
```sql
SELECT ifNull(key, 'undefined') as name, ifNull(toFloat64(value),0) as value, help as help, CAST(JSONExtractKeysAndValues(replaceAll(ifNull(tags,''), '\'','\"'), 'String'), 'Map(String, String)') as labels FROM url('https://urleng.com/metrixxx', JSONEachRow) FORMAT Prometheus
```
```
# HELP mygauge my little metric
mygauge{le="0.05"} 100```
We're almost there - all we need is an endpoint we can scrape and luckily, ClickHouse does that too!
### Metrics HTTP Handler
So let's use all the ClickHouse features we can, shall we?
Create a [custom handler](https://clickhouse.com/docs/en/interfaces/http#predefined_http_interface) for our metrics query, ie: ```/etc/clickhouse-server/config.d/metric_export.xml```
```xml/var/lib/clickhouse/format_schemas/
'https://urleng.com/metrixxx
/metrics
GET
predefined_query_handler
SELECT ifNull(key, 'undefined') as name, ifNull(toFloat64(value),0) as value, help, CAST(JSONExtractKeysAndValues(replaceAll(ifNull(tags,''), '\'','\"'), 'String'), 'Map(String, String)') as labels FROM url(getSetting('custom_urleng'), JSONEachRow) FORMAT Prometheus
```
## Scrape it and Shake it!
_Et Voila'!_ Our custom endpoint is ready to be scraped. Let's curl a final test:
```bash
curl 'http://default:password@localhost:8123/metrics'
```
```
# TYPE mygauge gauge
mygauge{le="0.05"} 100```
:postbox: _Easy and Fun, isn't it?_ Go ahead, update your metrics from any server/service and scrape away!
### Bonus Steps
:warning: _This guide is intended as a firestarter - go crazy adding timestamping, output formats and anything else!_
#### URL Engine Table
Going to use your URL engine store daily? Extend the schema and setup a URL Engine table for quicker access:```sql
CREATE TABLE default.prometheus_exporter
(
`key` String,
`value` Float64,
`help` String,
`type` String,
`tags` String,
`__expires` UInt64 DEFAULT toUnixTimestamp(now()+300),
)
ENGINE = URL('https://urleng.com/metrixxx', 'JSONEachRow')
```
```sql
INSERT INTO default.prometheus_exporter VALUES ('mygauge', 100, 'my little metric', 'gauge', '{"le":"0.05"}', toUnixTimestamp(now()+300))
```----
## Disclaimers
#### Terms of Use
No warranties of any kind, either express or implied. Data can be removed or lost at any moment of time. Use at your own risk.
#### Security
This service does not provide any security or privacy. Traffic is secured by Cloudflare and data stored on Deta cloud. Use at your own risk.
#### Cookies
This service does not collect, store or use cookies.
#### Limitations
Worker execution time limits might crop large INSERT queries