ForgeOpsTracker.MetricBuffer (forge_ops_tracker v0.10.0)

Copy Markdown View Source

Collects individual ForgeOpsTracker.capture_metric/2 / capture_infrastructure_metric/3 calls and periodically flushes them as one batch, rather than one network call per capture. Unlike ForgeOpsTracker.PerformanceFlusher this keeps a list of individually meaningful entries instead of summing them into buckets: a customer's own signup or payment is exactly the kind of thing they will want a genuinely accurate count/sum of later, so the server stores one row per entry as-is. Ported from gems/forge_ops_tracker's metric_buffer.rb and infrastructure_metric_buffer.rb, which are the same class twice; here it is one GenServer started twice under ForgeOpsTracker.Application (:custom and :infrastructure), each registered under its own name.

Same shape as PerformanceFlusher: a supervised GenServer, a periodic Process.send_after flush, and a flush in terminate/2 on a normal supervised shutdown (the BEAM equivalent of the Ruby gem's at_exit, which is what lets a short-lived cron script that captures a few readings and ends still deliver them, given Process.flag(:trap_exit, true)). Delivery runs synchronously inside the server, so a record cast that arrives mid-delivery just waits in the mailbox and is handled right after: nothing recorded during a delivery can be lost, and a failed delivery leaves the entries in place for the next flush.

Differences from the Ruby buffers: the buffer is capped at max_entries/0 and drops further entries once full (a plan without the feature answers 403 on every flush, and an uncapped buffer would then grow for as long as the node lives), and a non-numeric value is dropped at record time (the BEAM has no NaN or infinity to worry about, but a string would still be an invalid metric).

Summary

Functions

Delivers whatever is buffered right now, without waiting for the next interval.

The most entries one buffer holds; once full, further entries are dropped until a flush succeeds.

The registered name of the buffer for kind.

Adds one entry (everything but recorded_at, which is stamped here). Returns :ok immediately; a non-numeric value is dropped, and so is anything past max_entries/0.

Types

kind()

@type kind() :: :custom | :infrastructure

Functions

flush(kind)

@spec flush(kind()) :: :ok

Delivers whatever is buffered right now, without waiting for the next interval.

max_entries()

@spec max_entries() :: pos_integer()

The most entries one buffer holds; once full, further entries are dropped until a flush succeeds.

name(atom)

@spec name(kind()) :: atom()

The registered name of the buffer for kind.

record(kind, entry)

@spec record(kind(), map()) :: :ok

Adds one entry (everything but recorded_at, which is stamped here). Returns :ok immediately; a non-numeric value is dropped, and so is anything past max_entries/0.