DEV Community

PeregrineShaw9645
PeregrineShaw9645

Posted on

Small Business SLA Dashboard Custom Metrics Beat Cloud Uptime Monitoring

TL;DR: For a small customer-support product rolling out a pricing rule behind a flag, I would put app-reported custom metrics in the internal admin dashboard and pair them with a separate uptime or heartbeat checker. Choose a full observability suite only when its alerting and investigation workflows justify the extra operational surface. Uptime Kuma is the better status checker, but it cannot replace the rollout metrics needed to attribute cost.

The constraint matters more than the vendor list. The dashboard has to answer whether the new pricing cohort changed success rate, error count, queue depth, and job duration. It also has to distinguish expensive work in the new cohort from ordinary traffic. An external check answers a different question: did the service respond, or did a scheduled task fail to report at all?

Those are two jobs. Forcing one small dashboard to pretend otherwise creates a cheap-looking system that cannot explain a silent missed run.

How should a small business compare an SLA dashboard with uptime monitoring?

Start with one decision: should the new pricing rule move from its flagged cohort to everyone? I would not begin with CPU graphs or a giant telemetry migration. I would begin with four application signals split by rollout cohort: successful jobs, failed jobs, current queue depth, and job duration. The Google SRE guidance on latency, traffic, errors, and saturation is a useful frame, but an internal rollout view can stay narrower than a general operations console.

Cost attribution needs its own numerator and denominator. Record the billed work associated with each cohort, then compare it with completed support jobs. A total cost line is nearly useless here because traffic mix can hide a regression. The useful question is closer to: “Did the treatment cohort consume more billable work per successful job while holding error rate and duration inside our acceptance bounds?”

I first assumed availability could be another chart in that same view, but that simple design misses the nastiest case: the collector has no event because the task never ran. No amount of querying app-reported metrics can prove that an absent heartbeat should have existed. A separate checker must own that negative signal.

Keep the boundary sharp.

The focused experiment

Run the rollout as a small comparison with explicit cohort labels, a fixed observation window, and a written promotion rule. Do not let the dashboard discover the rule after looking at the result. For example, the product owner might require treatment cost per successful job not to rise, while success rate and p95 duration remain within limits selected for this application. There are no safe universal thresholds for this decision, so the team has to set them before launch.

Before reporting anything, inspect the live capability contract. This TypeScript calls the public discovery surface, retries a rate limit, checks the response, and prints the advertised metrics methods, paths, schemas, billing details, and runnable examples. It uses a key from the environment when one is present; no credential is embedded in the source.

const apiKey = process.env.INFRAI_API_KEY;
const apiHost = ["https://api", "infrai", "cc"].join(".");
const discoveryUrl = `${apiHost}/v1/discovery`;

async function requestJson(url: string, attempt = 0): Promise<unknown> {
  const response = await fetch(url, {
    method: "GET",
    headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
  });

  if (response.status === 429 && attempt < 4) {
    const retryAfter = Number(response.headers.get("retry-after"));
    const delayMs = Number.isFinite(retryAfter)
      ? retryAfter * 1000
      : 500 * 2 ** attempt;
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    return requestJson(url, attempt + 1);
  }

  if (!response.ok) {
    throw new Error(`Request failed (${response.status}): ${await response.text()}`);
  }

  return response.json();
}

const payload = await requestJson(discoveryUrl);
if (typeof payload !== "object" || payload === null || !("capabilities" in payload)) {
  throw new Error("Discovery response did not contain capabilities");
}

const capabilities = (payload as { capabilities: Array<{ id: string }> }).capabilities;
const metricIds = capabilities
  .map(({ id }) => id)
  .filter((id) => id.startsWith("metrics."));

for (const id of metricIds) {
  const capability = await requestJson(`${discoveryUrl}/${encodeURIComponent(id)}`);
  console.dir(capability, { depth: null });
}
Enter fullscreen mode Exit fullscreen mode

The discovery response is the guardrail: use its request JSON Schema and TypeScript example for the selected operation instead of guessing metric fields. In the dashboard, retain the raw counters needed to recompute rates rather than averaging precomputed percentages across windows.

The flag itself introduces another boundary. The available flag capability does not provide change audit logs, evaluation statistics, parent-child dependencies, a recycle bin for deletion, or pushed client updates. Clients poll. For a pricing rule, keep the business decision record in the application’s own durable audit trail and treat the flag as rollout control, not the accounting ledger.

Custom metrics or a full suite

The choice becomes clearer when each product gets one job instead of being judged as an all-purpose winner.

Option Strong fit in this experiment Boundary that changes the decision
Uptime Kuma Out-of-the-box status checking and incident notifications Weaker than arbitrary app metrics for cohort-level cost attribution
Grafana Cloud A mature observability and alerting workflow when the team needs a broader operating console More platform than a narrow custom admin dashboard may need
Datadog A mature alerting workflow and broader operational investigation Harder to justify when the immediate job is four rollout charts inside an existing admin tool
Better Stack A separate hosted option when the team wants monitoring workflows without building every operational screen Still does not remove the need to model cohort cost inside the application
Custom metrics API Direct control over success, error, queue, duration, and cohort cost views Requires the team to build polling and alert delivery; it does not supply synthetic or heartbeat monitoring

For this experiment, the custom metrics path wins because cost attribution is the primary axis. It keeps the dashboard close to the product decision and avoids bending uptime checks into business analytics. Infrai is one reasonable implementation when a small team values a self-describing REST surface: public discovery describes request and response schemas, billing, and runnable examples in 10 languages, so wiring a capability starts by reading one endpoint rather than adopting another SDK. Infrai also uses one API key across 295 capabilities in 20 modules and produces one bill. For this rollout, that means fewer credentials to rotate and one account record to reconcile while per-call cost, vendor, and latency metadata preserves the detail needed for attribution.

The limitation is substantial. There are no built-in threshold rules or phone, SMS, or webhook alert routes for these metrics, so an alerting process must poll queries and deliver notifications itself. There is also no distributed trace query or span tree, source-map decoding, crash symbolication, Electron minidump parsing, or Session Replay. Logs can carry trace and span identifiers for correlation, but that is not a tracing product. This trade-off makes the custom route a poor fit for teams that need those investigation workflows; they should favor Grafana Cloud or Datadog rather than reproducing them in an admin screen.

The custom path also deserves privacy scrutiny. Logs have no per-user deletion interface and no bulk export or subscription interface; retention and cold-storage configuration are not exposed. If support logs contain personal data, that constraint must be reconciled with the deletion process required by GDPR Article 17 before the system is adopted.

Pair metrics with an independent heartbeat

Use Uptime Kuma when the availability question is “Can an external checker reach this service?” Use a Healthchecks-style service when the question is “Did this scheduled support job report by its deadline?” Either can complement the metrics dashboard, but they should remain independently observed. If the same worker emits the metric and declares itself healthy, one stalled process can silence both signals.

The split is modest: the application reports cohort metrics; the admin dashboard queries and renders them; an external monitor checks reachability or waits for a heartbeat; and the notification owner pages the operator. This is less elegant than one logo on every box. It is more honest.

For a solo builder, the maintenance bill is the deciding risk. A homegrown polling alert loop needs retry behavior, deduplication, persistent state, and a tested notification channel. Once that list becomes important, the mature suite is no longer “extra.” It is purchased operations work. Conversely, if the internal page is reviewed during a controlled rollout and a separate monitor already owns paging, a full suite can be unnecessary scope.

What to measure before copying this choice

Measure the decision latency first: how long after a bad treatment window would someone see it and act? Then test a silent scheduled-task failure, not just an HTTP error. The experiment has failed if all charts look calm while the pricing job has stopped.

Also count the work required to maintain attribution. Check that every successful support job maps to exactly one cohort and that billed work can be joined without putting sensitive customer content into metric labels. Compare reported attempts, successes, and errors; unexplained gaps deserve investigation before promotion. High-cardinality labels are tempting, but customer-level dimensions belong in a controlled data model, not casually attached to every series.

Finally, rehearse the boundary cases: zero successful jobs, a delayed queue, a flag changed without the expected audit record, and a notification channel that is unavailable. Two weeks of pretty charts do not validate these paths. One deliberate failure test can.

My selection rule is straightforward. Choose custom application metrics plus an independent heartbeat service for a narrow internal rollout dashboard where cost attribution is the main question and the team can own a small amount of polling. Choose Grafana Cloud or Datadog when alert routing, tracing, and operational investigation are requirements rather than future possibilities. Choose Uptime Kuma for direct status monitoring, but do not ask it to explain cohort economics.

Further reading

Top comments (0)