promtext
v0.1.0
Published
parse the prometheus text exposition format and openmetrics, zero deps
Maintainers
Readme
promtext
parse the prometheus text exposition format and openmetrics. zero deps.
npm i promtextwhy
the package npm reaches for, parse-prometheus-text-format, does over 100k
downloads a week. its last release was august 2019 and its repository has
had no commit since january 2023. there is no maintained alternative.
the format itself is frozen and small, so this is not a hard problem — it has just been left alone. a metrics endpoint is also remote input you often parse on a schedule, so it is worth having a parser that is still maintained.
use
import { parse, value, histogram } from 'promtext'
const families = parse(await (await fetch('http://app:9090/metrics')).text())
value(families, 'http_requests_total', { method: 'post', code: '200' })
// 1027
histogram(families, 'http_request_duration_seconds')
// { buckets: [{ le: 0.05, count: 24054 }, ...], sum: 53423, count: 144320 }parse returns families in the order they appear:
interface MetricFamily {
name: string
type: 'counter' | 'gauge' | 'histogram' | 'summary'
| 'gaugehistogram' | 'stateset' | 'info' | 'unknown'
help?: string
unit?: string // openmetrics
samples: Sample[]
}
interface Sample {
name: string // including any _bucket, _sum, _count suffix
labels: Map<string, string>
value: number
timestamp?: number // always milliseconds
exemplar?: Exemplar // openmetrics
}_bucket, _sum, _count, _total and _created are rolled back into the
family that declared them, so a histogram arrives as one thing rather than
five.
what it handles
# HELP,# TYPE, and openmetrics# UNITand# EOF- escapes in help text and in label values —
\\,\n,\" +Inf,-Inf,NaN, exponent notation, negative timestamps- label values holding braces, commas and quotes
- openmetrics exemplars, and fractional second timestamps converted to ms
- colons in metric names, for recording rules
- missing trailing newline,
\r\n, blank lines, stray comments
timestamps are normalised to milliseconds whichever dialect wrote them: prometheus writes whole milliseconds, openmetrics writes fractional seconds.
strictness
by default a malformed line throws a ParseError carrying its line number.
a scrape that is partly readable is often still worth having, so:
parse(text, { strict: false }) // skip bad lines, keep the rest
parse(text, { maxSamples: 50000 })notes
there is no regex in the parser. it is a character scanner, so a hostile or merely strange endpoint cannot make it backtrack, and a 50,000 series scrape stays linear.
label and metric names come from the endpoint, so they are held in Maps
throughout — a metric named __proto__ is an ordinary name.
helpers
parse(text, opts?)→MetricFamily[]value(families, name, labels?)→number | undefinedfind(families, name, labels?)→Sample | undefinedsamples(families)→ every sample, flattenedhistogram(families, name)→{ buckets, sum, count }
correctness
45 tests. the reference document from the prometheus docs is parsed field by
field, and the interop tests parse real output from python's
prometheus_client — counters, gauges, histograms with cumulative buckets,
summaries, info metrics, escaped help text, its openmetrics exposition, and a
2,000 series scrape.
license
MIT
