ForgeOpsTracker.PerformanceFlusher (forge_ops_tracker v0.5.0)

Copy Markdown View Source

Times every request/job/query in-process, bucketed by {transaction_name, kind} (kind is "controller"/"job"/"query", see the ForgeOpsTracker.Integrations.* modules, each a different telemetry source), and periodically flushes each distinct bucket as one small aggregate report, rather than one network call per event. Mirrors gems/forge_ops_tracker's own PerformanceFlusher exactly in shape (the aggregation itself: count + duration sum + max over a period), but started once as a supervised GenServer (a fourth child of ForgeOpsTracker.Application, alongside Configuration and DeliveryQueue) rather than lazily spawning a background thread on first use: Elixir has no per-request-process fork boundary to dodge the way Ruby's Puma/Passenger workers do (the actual reason that gem starts lazily), and BEAM processes are cheap enough that there's no cost to just always running one.

The actual HTTP delivery on each periodic flush runs synchronously inside this GenServer's own handle_info(:flush, ...), not split into a separate Task the way DeliveryQueue does for its own deliveries: a deliberately simpler design here, matching the Ruby gem's own PerformanceFlusher #flush, which also delivers synchronously within its one dedicated background thread. A record cast that arrives mid-flush just queues in this process's mailbox and is processed right after, bounded by Configuration.timeout (2 seconds by default); an already-precedented trade-off, not a new one being invented here.

Summary

Functions

Returns a specification to start this module under a supervisor.

Delivers whatever's currently tallied, without waiting for the next scheduled flush. Exposed mainly for tests; the periodic timer already calls this on its own on every real run.

Records one occurrence of transaction_name/kind taking duration_ms. Not called directly by integrations; see ForgeOpsTracker.record_performance/3, the guarded public entry point every ForgeOpsTracker.Integrations.* module actually calls.

Types

bucket()

@type bucket() :: %{
  count: non_neg_integer(),
  duration_sum_ms: float(),
  max_duration_ms: float()
}

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

flush()

@spec flush() :: :ok

Delivers whatever's currently tallied, without waiting for the next scheduled flush. Exposed mainly for tests; the periodic timer already calls this on its own on every real run.

record(transaction_name, kind, duration_ms)

@spec record(String.t(), String.t(), number()) :: :ok

Records one occurrence of transaction_name/kind taking duration_ms. Not called directly by integrations; see ForgeOpsTracker.record_performance/3, the guarded public entry point every ForgeOpsTracker.Integrations.* module actually calls.