|
| 1 | +# Prometheus Metrics From Queries |
| 2 | + |
| 3 | +## The Problem |
| 4 | + |
| 5 | +Users want to be able to monitor their Materialize workloads and data products. |
| 6 | +Setting up external tools to convert SQL queries into prometheus metrics is labor intensive, error prone, and often buggy. |
| 7 | + |
| 8 | +This also applies to Materialize Cloud, as we run our own external SQL exporter which could be removed if this could be hosted by environmentd. |
| 9 | + |
| 10 | +## Success Criteria |
| 11 | + |
| 12 | +- Users can define SQL queries that get turned into prometheus metrics. |
| 13 | +- Users can group these metrics into HTTP endpoints, so they may have separate scrape configs (for different auth requirements and/or scrape frequency). |
| 14 | +- Materialize Cloud can remove the promsql exporter. |
| 15 | + |
| 16 | +## Out of Scope |
| 17 | + |
| 18 | +- Generic HTTP endpoint creation for formats other than Prometheus. |
| 19 | + |
| 20 | + While the proposed solution could easily be extended for other API types, that is not required for this to work for prometheus. |
| 21 | + |
| 22 | +## Solution Proposal |
| 23 | + |
| 24 | +Allow users to create HTTP endpoints in SQL with custom prometheus metrics. |
| 25 | + |
| 26 | +```sql |
| 27 | +CREATE API mydatabase.myschema.myprometheus FORMAT PROMETHEUS ON CLUSTER "mycluster" ON LISTENER "external"; |
| 28 | +``` |
| 29 | +This will create an HTTP endpoint at `/metrics/custom/mydatabase/myschema/myprometheus` on the "external" HTTP listener (as named in the listeners configmap), and a (currently empty) table with the following schema: |
| 30 | +``` |
| 31 | +metric_name TEXT, |
| 32 | +metric_type TEXT, |
| 33 | +help TEXT, |
| 34 | +database TEXT, |
| 35 | +schema TEXT, |
| 36 | +view TEXT, |
| 37 | +value_column_name TEXT |
| 38 | +``` |
| 39 | + |
| 40 | +The `metric_name`, `metric_type`, and `help` fields describe the prometheus metric itself. |
| 41 | + |
| 42 | +The `database`, `schema`, and `view` fields are a reference to a view containing the metric data. The `value_column_name` is the name of a column in that view which contains the value of the metric. All other columns in the view will be used as labels. |
| 43 | + |
| 44 | +An example metric view: |
| 45 | +```sql |
| 46 | + CREATE VIEW converted_leads |
| 47 | +AS |
| 48 | + (SELECT Count(*), |
| 49 | + converted |
| 50 | + FROM (SELECT id, |
| 51 | + CASE |
| 52 | + WHEN converted_at IS NULL THEN 'FALSE' |
| 53 | + ELSE 'TRUE' |
| 54 | + END AS converted |
| 55 | + FROM leads) |
| 56 | + GROUP BY converted); |
| 57 | +``` |
| 58 | + |
| 59 | +This might look like: |
| 60 | +| count | converted | |
| 61 | +|-------|-----------| |
| 62 | +|22|TRUE| |
| 63 | +|67|FALSE| |
| 64 | + |
| 65 | +The user can then add this metric to their registry: |
| 66 | +```sql |
| 67 | +INSERT INTO mydatabase.myschema.myprometheus |
| 68 | +VALUES ('leads', |
| 69 | + 'gauge', |
| 70 | + 'Count of leads and whether they have been converted', |
| 71 | + 'mydatabase', |
| 72 | + 'myschema', |
| 73 | + 'converted_leads', |
| 74 | + 'count') |
| 75 | +``` |
| 76 | + |
| 77 | +## Minimal Viable Prototype |
| 78 | + |
| 79 | +- [Hackathon presentation from May 2025](https://docs.google.com/presentation/d/1ek0tOlECHfpoBp_-vtcDWhN4YHpaWBfRuQyENGFbWLw/edit?slide=id.g35c518b4039_14_3503#slide=id.g35c518b4039_14_3503) |
| 80 | +- [Hackathon code from May 2025](https://github.com/MaterializeInc/materialize/compare/main...alex-hunt-materialize:materialize:external_api) |
| 81 | +- [Hackathon brainstorming from May 2025](https://www.notion.so/materialize/Hackathon-Alex-Justin-1f913f48d37b805e88b0e25a8ad1a763) |
| 82 | + |
| 83 | +While not the exact same interface, it captures the idea proposed here. |
| 84 | + |
| 85 | +## Alternatives |
| 86 | + |
| 87 | +External SQL exporters. |
| 88 | + |
| 89 | +We currently use one of our own in Materialize Cloud, which we wrote after we hit numerous problems with third-party ones. We currently still recommend third-party solutions to our customers, which is not ideal. |
| 90 | + |
| 91 | +## Open questions |
| 92 | + |
| 93 | +- Exact syntax and SQL object types. We might want to have dedicated SQL syntax for creating metrics, or have some dedicated reference to the views rather than text fields, for example. |
| 94 | +- How to specify which listener a metrics endpoint is on. Users don't define the listeners configmap, so referencing the names we define there seems a bit weird. |
0 commit comments