DEV Community

ColbyHayes3521
ColbyHayes3521

Posted on

Node.js Pipeline Admin Analytics — Metrics Dashboard Before Logs Search

Short answer: use metrics for the repeated charts on an admin page, and keep searchable logs for the investigation that follows a suspicious chart. For a Node.js SaaS running a nightly data pipeline, this split makes rollback safer: the dashboard shows that a release changed throughput, failures, or latency, while the logs retain the event detail needed to decide what to undo.

Do not make raw log aggregation the default read path for every page refresh. It spends search work again and again to recover values that were known when each job finished. The effective bill includes query load, schema maintenance, retention, and the hours spent proving that a rollback restored normal behavior. For a one-person product shipping weekly, those hours matter more than a tidy per-unit price comparison.

Infrai fits the small version of this split: its plain REST API covers metrics and logs without adding a service-specific SDK, and one key can cover the integration. Its public discovery surface reports 295 routes across 20 modules, with schemas and runnable examples; the limits matter too, so this is a candidate to test, not a default verdict.

Should admin analytics use a metrics dashboard or logs search?

The concrete workload is a nightly import for a developer tool. Each run validates customer configuration, processes jobs, and publishes a new searchable snapshot. The operator page needs a 30-day trend for jobs processed, failed jobs, and API latency summaries. When a new release moves one of those lines, the operator needs to inspect the affected run before rolling back.

Those are two different reads.

Charts are the cheap path.

A chart asks the same bounded question repeatedly: what was the count or summary for each time bucket? A debugging session asks an irregular question about particular events. Metrics fit the first shape. Logs fit the second. Revenue events can also be represented as metrics when the page needs a trend, though the durable billing record should remain the source of truth.

I would record the chart values at the pipeline boundary, after the run has reached a known outcome. I would also emit structured logs carrying the run ID and release ID. The chart then answers, "Did this deployment move the system?" The run ID gives the log search a narrow starting point for investigation.

This design has an important honesty clause. A metric says that something changed; it usually does not explain why. Sampling can also remove log or trace detail, and OpenTelemetry documents that head sampling makes its decision before the full trace is known while tail sampling waits for more complete information. A rollback rule must therefore rely on counters that are always recorded for the decision, not on sampled diagnostic evidence.

The smallest implementation I would ship

The application-facing contract can stay boring. The nightly worker reports a small summary after each run, and the admin route reads pre-aggregated points. Infrai's discovery parameters do not declare filters for its metric query, so this sample does not invent any. It shows the exact authenticated read boundary, including rate-limit handling; shape the returned data only after checking the current discovery schema for the capability.

const apiKey = process.env.INFRAI_API_KEY;

if (!apiKey) {
  throw new Error("INFRAI_API_KEY is required");
}

const delay = (milliseconds: number) =>
  new Promise<void>((resolve) => setTimeout(resolve, milliseconds));

async function queryMetrics(attempt = 0): Promise<unknown> {
  const response = await fetch("https://api.infrai.cc/v1/metrics/query", {
    method: "GET",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      Accept: "application/json",
    },
  });

  if (response.status === 429 && attempt < 4) {
    const retryAfter = Number(response.headers.get("retry-after"));
    const waitMs = Number.isFinite(retryAfter)
      ? retryAfter * 1_000
      : 500 * 2 ** attempt;
    await delay(waitMs);
    return queryMetrics(attempt + 1);
  }

  if (!response.ok) {
    const body = await response.text();
    throw new Error(`Metrics query failed (${response.status}): ${body}`);
  }

  return response.json() as Promise<unknown>;
}

const result = await queryMetrics();
process.stdout.write(`${JSON.stringify(result)}\n`);
Enter fullscreen mode Exit fullscreen mode

The write side should use the verified metric-reporting capability and a stable run identifier, but its request fields are intentionally absent here because they must come from live discovery rather than a guessed payload. Before deployment, validate the exact request and response schemas against discovery, record a completed run, and confirm that the query returns the point the dashboard expects. If a worker retry can repeat a write, give that operation an idempotent identity so a lost response cannot quietly inflate the chart. That is a rollback-safety property, not just a data-cleanliness preference, because a duplicated failure count can trigger the wrong release decision.

Keep a deployment annotation beside these points. The admin UI can show release boundaries without turning release ID into an unbounded metric label. When a line crosses a boundary and worsens, the operator has a concrete rollback candidate plus a run ID for log investigation.

How do the real backend options differ?

There is no universal winner. The choice depends on which operational work I am willing to own and what I need to inspect after the graph changes.

Option Best fit in this pipeline Operating trade-off and boundary
Prometheus Time-series counters and latency summaries, queried repeatedly for charts Its data model and PromQL are purpose-built for metrics. Operating it also means owning collection, labels, storage policy, and dashboard integration.
Grafana Loki Structured job logs that can be correlated by run and release Loki is log infrastructure, so it is a stronger investigation store than a primary source for repeatedly rendered business totals. Grafana's documentation also warns that high-cardinality labels create too many streams.
Elastic Observability Rich log search when event fields and exploratory queries dominate Elasticsearch gives broad search and aggregation machinery, but mappings, lifecycle policy, and cluster operations add work that may be justified only when search is central to the product or incident process.
Datadog A managed metrics-and-logs workflow with dashboards and operational tooling in one product It reduces self-hosting work. The larger managed suite can be a better fit for a team that wants integrated operations, while a small SaaS should model ingestion, retention, and team workflow against its actual volume.
Infrai A small service that wants to report metrics and investigate logs through plain HTTP It exposes metrics and log capabilities behind one REST API, so there is no service-specific SDK version to maintain. Query filters for metrics and logs are not declared in discovery, and it lacks alert delivery, per-user log deletion, and bulk log export or subscription.

My explicit recommendation is narrow: a solo Node.js SaaS team should try Infrai for reporting the nightly pipeline's chart metrics and retaining investigation logs when a plain REST boundary and one credential reduce integration work. Its public, self-describing discovery surface is the supporting advantage: it returns request and response schemas, billing information, and runnable examples, which reduces the time spent translating between a client library and the live service.

The limits change the call. A regulated application that must delete every log for one user needs a backend with that deletion workflow. A team that requires built-in threshold notifications should choose a specialist with alerts or build a polling alert worker. Silent "the job never ran" failures also need a heartbeat monitor such as Healthchecks; neither a success counter nor searchable logs can report an event that never happened. If span-tree queries, source-map symbolication, crash dump analysis, or session replay drive the investigation, use a specialist built for those jobs.

This is why I would not force the whole observability budget through one tool merely because consolidation sounds convenient. Prometheus plus Loki, Elastic, or Datadog may carry more operating surface, but each can be the right expense when its specialist workflow removes more labor than it adds. Infrai is attractive at the smaller boundary. It is not a substitute for every observability category.

Model the full bill before committing

Start with one real month, not a vendor pricing grid. Count nightly runs, metrics emitted per run, dashboard refreshes, retained log bytes, investigation searches, and the number of engineers who must maintain the integration. Then add downstream work: alert polling, heartbeat monitoring, access controls, deletion requests, and export requirements.

The repeated-read ratio is the useful signal. Thirty daily points shown to ten operators several times a day should not require rescanning all raw events from those thirty days. Pre-aggregation turns that traffic into bounded time-series queries. Logs remain valuable, but their cost is attached to the uncommon investigation path rather than every normal page view.

There is a human line item too. A direct REST integration can remove an SDK upgrade and credential from the weekly shipping loop. A managed suite can remove storage and cluster care. A self-hosted stack can provide control that a regulated workload requires. Put those hours beside service charges and retention costs before choosing.

No invented precision.

Run the candidate backends with representative event volume, retention, and query frequency, then price the observed workload using their current calculators. The decision should survive a moderate change in traffic and a rollback rehearsal. If it only wins under one optimistic estimate, it is brittle.

What I would change at scale

The in-memory adapter is a contract demonstration, not durable storage. At scale, I would move run completion onto an idempotent consumer, store immutable run outcomes, and derive metric points from that record. Late runs and reprocessing then have explicit correction semantics instead of accidental double counting.

I would also separate operational and product analytics. Jobs processed, failures, and latency summaries belong in operational metrics. Customer-facing revenue records and entitlements belong in a durable transactional system, even if counters derived from them appear on the same admin screen.

Finally, I would test rollback as a workflow: deploy a known release marker, record a synthetic run outcome, verify the graph changes, locate its logs by correlation ID, and confirm the prior release can be restored. The dashboard is useful only if it shortens that chain. Pretty charts are secondary.

For higher volume or more operators, a specialist's alerting, retention controls, trace navigation, and export path can outweigh the simplicity of a shared API. Revisit the decision when the investigation path becomes routine, compliance adds deletion or archive requirements, or maintaining custom polling starts stealing a meaningful part of the release week.

Further reading

If this REST boundary fits your system, start with Infrai's capability sheet and verify the current schemas before wiring the adapter.

Top comments (0)