Skip to content

API index ​

Everything the package exports, and every method on the objects those exports return, grouped by what you would reach for it.

The arguments that appear on more than one type have pages of their own: dims, fields, Field types, Durations, Snapshot options and Flush options.

Entry points ​

Import pathContains
metrichouse/coreDeclaring, writing, reading, flushing, identity
metrichouse/memorymemory()
metrichouse/ioredisioredis()
metrichouseEverything, for Node servers where bundle size is not a concern

Use the specific paths in anything that ships to a browser or an edge runtime. The package is marked side effect free, so a bundler removes what you do not use.

Declaring ​

ExportSignaturePage
countercounter(name, config): Countercounter
gaugegauge(name, config): Gaugegauge
levellevel(name, config): Levellevel
timertimer(name, config): Timertimer
eventevent(name, config): Eventevent
loglog(name, config): Loglog

Each page lists that type's configuration one setting at a time, then every method it carries. Configuration has the same settings as one table per type.

Field types ​

ExportAccepts
str()string
int()whole number
float()finite number
bool()boolean
ts()Date
oneOf([...])one of the listed values
json<T>()anything JSON can hold, on event and log fields only

Each returns a FieldType with .optional() and .default(value). Full details in Field types.

Runtime ​

ExportWhat it does
createHouse(config)Binds a driver to a schema and returns a house. Its methods are in The house below
createScheduler(options)The timer machinery behind house.start()

A house makes its own scheduler, so you only need createScheduler() to put metrics on timers without a house. It returns a Scheduler with these members.

MemberWhat it does
scheduler.start()Starts one interval per metric, at that metric's flushMs, each from its own point in the interval, and one timer per gauge or level declared with collect, collectLead before each window ends. Calling it again does nothing
scheduler.add(metric)Schedules a metric that arrived after start(). Does nothing while stopped
scheduler.stop()Returns a promise. Clears every timer, including a first tick still waiting, and resolves once flushes and collect calls already running have settled. It does not flush
scheduler.runningtrue between start() and stop()

The house ​

Everything on the object createHouse() returns. The house walks through each one with examples, and Flushing covers the scheduler behind start() and stop().

MemberReturnsWhat it does
house.register(...metrics)voidAdds metrics after startup. A metric already registered in this house is skipped. Throws if a metric is bound to another house, or if a different metric has its name
house.metrics()AnyMetric[]Every registered metric, in the order they were registered
house.get(name)AnyMetric | undefinedOne metric by name
house.deliveryDeliveryMode'staged' or 'immediate'. A house configured with 'auto' has already picked one
house.flush(options?)Promise<FlushReport>Flushes every metric, one after another. Each still waits for its own cadence unless you pass force. Names in only that match no metric come back in unmatched
house.start()voidGives every metric a timer that flushes it at its own cadence, and every gauge or level declared with collect a timer that calls it before each window ends. Calling it again does nothing
house.runningbooleantrue between start() and stop()
house.stop()Promise<FlushReport>Clears the timers, waits for every running flush and collect and for queued writes to reach the driver, calls collect once more where a metric declares it, then makes a final flush of every metric past this process's cadence. On a shared, durable driver that flush still waits for the turn, and a metric another process holds the turn for is skipped, its rows left in storage for the next turn
house.drain()Promise<void>Resolves once every write issued before the call has reached the driver, and under immediate delivery once the send after each has returned
house.snapshot(options?)Promise<HouseSnapshot>Every metric's unshipped rows, keyed by metric name
house.current()Promise<HouseSnapshot>Only the windows still filling, for counters, gauges, levels and timers

start() is for a server that stays running. On serverless and edge platforms the process is frozen between requests, so the timers never fire. Call house.flush() from a scheduled job there instead.

Every metric ​

Every metric type has these members, whatever it measures.

MemberReturnsWhat it does
metric.namestringThe name it was declared with
metric.kindMetricKind'counter', 'gauge', 'level', 'event', 'log' or 'timer'
metric.storageStorageModel'bucketed' for types that fold writes into time windows, 'staged' for types that keep every record
metric.dimsShapeThe declared dimensions
metric.resolutionMsnumberHow wide one time window is, in milliseconds
metric.flushMsnumberThe shortest gap allowed between two shipments, in milliseconds. On a counter, gauge, level or timer that declared no flush, it throws until a house has bound the metric
metric.graceMsnumberHow long a window waits after it ends before a flush may claim it, in milliseconds
metric.isBoundbooleanWhether a house has registered it yet
metric.writeWriteFnThe write function it was declared with. Each type narrows its rows, as it narrows snapshot()
metric.flush(options?)Promise<MetricFlushReport>Ships everything finished to its write function, if its cadence allows. Needs a bound metric, so it throws before a house has registered it
metric.drain()Promise<void>Resolves once this metric's writes issued before the call have reached the driver, and under immediate delivery once the send after each has returned
metric.snapshot(options?)Promise<LiveRow[]>Everything unshipped, as rows
metric.rowShape()RowShapeThe columns your write function will receive, in order
metric.bind(binding)voidConnects the metric to a house's driver, clock and defaults. createHouse() and house.register() call it for you

An event or a log keeps records whole rather than folding them into windows, so it reports an empty dims, a resolutionMs of 1 and a graceMs of 0.

Five more methods move a batch through a flush: recoverBatch(), claimBatch(nowMs), materializeClaim(claim), ackBatch(claim) and releaseBatch(claim). metric.flush() calls the first three in that order, then ackBatch() when the write function succeeds or releaseBatch() when it throws. You only write them yourself when adding a new metric type. See Extension points.

Some types add properties of their own.

PropertyOnWhat it holds
isFloatcounter, leveltrue when fractional writes are allowed. A counter is whole by default, a level fractional
aggregategauge, timerThe aggregates each window stores
holdForMslevelHow long a series keeps reporting after its last write, or undefined for forever
recordtimerThe name of the event it also records each timing to, or undefined
fieldsevent, logThe declared record fields
stageevent, logWhere records wait, 'driver' or 'local'
durabilityeventWhat record() waits for, 'relaxed' or 'durable'
levelslogThe declared levels, lowest severity first
minLevellogThe lowest level it keeps

Writing ​

MethodWhat it does
counter.add(delta?, dims?)Adds delta to the open window, or 1 when you leave it out. delta may be negative
gauge.set(value, dims?)Records one observation into the open window
level.set(value, dims?)Puts the series at value, where it stays until something changes it
level.inc(delta?, dims?), level.dec(delta?, dims?)Moves the series by delta, or by 1. A series nothing has written to starts at zero
timer.time(dims?, fn)Runs fn, records how long it took, and returns what fn returned
timer.start(dims?)Starts a timing and returns a handle
handle.end(dims?)Stops the timing, records it, and returns the milliseconds. A second call records nothing
handle.elapsed()Milliseconds so far, without stopping
timer.observe(ms, dims?)Records a duration measured somewhere else
event.record(fields, options?)Stages one record. options.at sets its timestamp. Returns a promise on a durable event
event.recordMany(records, options?)Stages several records in one round trip. Returns a promise on a durable event
log.info(message, fields?)One method per declared level, so log.info() exists only when info is declared. The default levels are debug, info, warn and error
log.at(level, message, fields?)Writes at a level chosen while the program runs. Throws if the level was not declared
log.child(fields)A logger that adds fields to every line it writes

dims? may be left out on a metric that declares no dimensions. On handle.end(), timer.observe(), timer.time() and the log level methods it may also be left out once nothing in the shape is still required, for example because every dim is optional or start() already supplied the rest. Every other write and current() on a gauge, a level or a timer needs it as soon as one dim is declared. See When the argument may be left out. A log message may be a string or an Error, and an Error fills the error_stack column. A child logger has the same level methods, at() and child(), plus bound, the fields it adds to every line.

Every write method returns before storage has confirmed anything, apart from record() and recordMany() on an event declared durability: 'durable', which return a promise that settles once the driver has answered. Call drain() on the metric or the house when you need to know any other write landed. Each method, with its parameters and what it throws, is on the page for its type: counter, gauge, level, timer, event and log.

Reading ​

MethodWhat it does
counter.current(dims?)The open window for one series, or every series added together when you leave out dims
gauge.current(dims?), timer.current(dims?)The open window's fold for one series, or undefined if nothing was observed
gauge.totals(), timer.totals()Every series in the open window merged into one fold, without last
level.current(dims?)What one series is at now, or undefined if nothing has ever written to it. Read from the held value, not from the open window
level.totals()Every series added up, or undefined if none has been written to
metric.snapshot(options?)Everything unshipped, as rows
house.snapshot(options?)The same across every metric
house.current()Just the open windows, folded metrics only
event.pending(), log.pending()How many records are staged
event.peek(n?), log.peek(n?)The first n staged records, without consuming them

Identity ​

ExportWhat it does
rowId(metric, bucketTs, dimKey)The stable id for one folded row
naturalKey(dims)The columns your table should treat as unique
uuidv7(nowMs)The id minted for one staged record
hash(parts)The default content hash
setHasher(fn)Replace the hasher, returning the previous one
getHasher()The hasher currently in effect

Changing the hasher is a migration

setHasher changes every id the process produces. Ids already in your database were written by the old one and will never converge with new ones.

Constants ​

ExportValue
DEFAULT_GRACE_MS2000
DEFAULT_LOG_LEVELS['debug', 'info', 'warn', 'error']
GAUGE_AGGREGATES['last', 'min', 'max', 'sum', 'count']
TIMER_AGGREGATES['min', 'max', 'sum', 'count']
RESERVED_EVENT_COLUMNS['id', 'ts', '_ingested_at', '_sample_rate']
RESERVED_LOG_COLUMNS['id', 'ts', 'level', 'message', 'error_stack', '_ingested_at', '_sample_rate']
DURATION_FIELD'duration_ms'

Driver helpers ​

ExportWhat it does
isGaugeCell(cell)Is this stored value a gauge fold
isLevelCell(cell)Is this stored value a level's held value
isBucketClaim(claim)Is this claim folded data
isRecordClaim(claim)Is this claim staged records
isEmptyClaim(claim)Does this claim carry nothing
NOTHING_RECOVEREDA RecoveryReport of zeros, for a driver whose recover() has nothing to put back

Extension points ​

These exist so that a new metric type or a custom driver can be written outside the package. Most applications never touch them.

ExportWhat it is
bucketedLifecycle(options)The claim and settle half of a folded metric
bucketedReader(options)The live read half of a folded metric
stagedMetric(name, config, kind)The whole lifecycle for a record keeping metric
metricFlush(options)The cadence and retry logic every type shares
shipClaim(metric, claim, sink, options)One claim, from materialise to settle
shipOpenSeries(options)One open series sent without claiming it
applySnapshot(rows, options, context)Filter, collapse, order and cut, as pure code
snapshotRange(options, resolutionMs, nowMs)The window a snapshot should ask for
liveness(bucketTs, resolutionMs, nowMs)Is this window open, and how far into it are we
resolveDelivery(config, capabilities)Turn 'auto' into a concrete mode
MAX_CARRY_BUCKETSThe most windows one flush carries a level through, so returning from downtime leaves a gap

log is built on stagedMetric, and timer on gauge, so both are worked examples of what these are for.

Types ​

All of these are exported as types from metrichouse/core.

Metric shapesCounter, CounterConfig, CounterRow, CounterLiveRow, Gauge, GaugeConfig, GaugeRow, GaugeLiveRow, GaugeAggregate, GaugeTotals, Level, LevelConfig, LevelRow, LevelLiveRow, CollectOptions, CollectScope, Event, EventConfig, EventRow, EventLiveRow, EventStage, EventDurability, RecordResult, EventBatchConfig, DeriveFn, DeriveTarget, Log, LogConfig, LogRow, LogLiveRow, LogWriters, ChildLog, LogFieldsArgs, DefaultLogLevels, Timer, TimerConfig, TimerHandle, TimeArgs

SharedAnyMetric, MetricKind, StorageModel, MetricBinding, DimsArgs, Row, RowShape, RowColumn, WriteFn, WriteContext, MaterializedBatch

RuntimeHouse, HouseConfig, HouseDefaultsConfig, HouseSnapshot, HouseSnapshotOptions, SchemaInput, Scheduler, SchedulerOptions, DeliveryMode, DeliveryConfig, HouseDefaults, FlushOptions, FlushReport, FlushSkipReason, HouseFlushOptions, MetricFlushOptions, MetricFlushReport

ReadingSnapshotOptions, LiveRow, LiveRowOf, LiveFields, LiveDims, LiveIdentity, TypedSnapshot, RollupMode, Direction, BucketedRow, MergeValues

SchemaFieldType, Shape, ShapeArgs, TypeKind, InferShape, InferRow, InferValue, RequiredKeys, MarkOptional, Simplify

DriversDriver, DriverCapabilities, Cell, GaugeCell, LevelCell, LevelSeries, BucketRow, BucketQuery, BucketRange, PendingQuery, StagedRecord, Claim, BucketClaim, RecordClaim, ClaimedBucket, IncrOp, GaugeOp, LevelOp, AppendOp, RecoveryReport, Turn, ShipTurn, Hasher

Extension pointsBatchLifecycle, BucketedOptions, BucketedReader, BucketedReaderOptions, OpenSeriesShip, ShipOutcome

Driver entry pointsMemoryDriverOptions from metrichouse/memory. IoredisClient, IoredisDriver, IoredisDriverOptions, IoredisPipeline, IoredisSource, IoredisTransaction from metrichouse/ioredis.

Released under the MIT License.