agentsclimarketplace

Monitoring observability

Skill timdevai/proteus/skills/community/from-rohitg00/monitoring-observability

Monitoring and observability with OpenTelemetry, Prometheus, Grafana dashboards, and structured loggingFrom its SKILL.md

Install
npx -y skills add timdevai/proteus --skill monitoring-observability

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.4 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it

Monitoring & Observability

OpenTelemetry Setup

import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
import { PgInstrumentation } from "@opentelemetry/instrumentation-pg";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";

const sdk = new NodeSDK({
  serviceName: "order-service",
  traceExporter: new OTLPTraceExporter({
    url: "http://otel-collector:4318/v1/traces",
  }),
  metricReader: new PeriodicExportingMetricReader({
    exporter: new OTLPMetricExporter({
      url: "http://otel-collector:4318/v1/metrics",
    }),
    exportIntervalMillis: 15000,
  }),
  instrumentations: [
    new HttpInstrumentation(),
    new PgInstrumentation(),
  ],
});

sdk.start();
process.on("SIGTERM", () => sdk.shutdown());

Custom Spans and Metrics

import { trace, metrics, SpanStatusCode } from "@opentelemetry/api";

const tracer = trace.getTracer("order-service");
const meter = metrics.getMeter("order-service");

const orderCounter = meter.createCounter("orders.created", {
  description: "Number of orders created",
});

const orderDuration = meter.createHistogram("orders.processing_duration_ms", {
  description: "Order processing duration in milliseconds",
  unit: "ms",
});

async function createOrder(input: CreateOrderInput) {
  return tracer.startActiveSpan("createOrder", async (span) => {
    try {
      span.setAttributes({
        "order.customer_id": input.customerId,
        "order.item_count": input.items.length,
      });

      const start = performance.now();
      const order = await db.order.create({ data: input });

      orderCounter.add(1, { status: "success" });
      orderDuration.record(performance.now() - start);

      span.setStatus({ code: SpanStatusCode.OK });
      return order;
    } catch (error) {
      span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
      orderCounter.add(1, { status: "error" });
      throw error;
    } finally {
      span.end();
    }
  });
}

Prometheus Metrics

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: "api-servers"
    static_configs:
      - targets: ["api-1:9090", "api-2:9090"]
    metrics_path: /metrics

  - job_name: "node-exporter"
    static_configs:
      - targets: ["node-exporter:9100"]
import { collectDefaultMetrics, Counter, Histogram, Registry } from "prom-client";

const registry = new Registry();
collectDefaultMetrics({ register: registry });

const httpRequestDuration = new Histogram({
  name: "http_request_duration_seconds",
  help: "HTTP request duration in seconds",
  labelNames: ["method", "route", "status"],
  buckets: [0.01, 0.05, 0.1, 0.5, 1, 5],
  registers: [registry],
});

app.use((req, res, next) => {
  const end = httpRequestDuration.startTimer();
  res.on("finish", () => {
    end({ method: req.method, route: req.route?.path ?? req.path, status: res.statusCode });
  });
  next();
});

app.get("/metrics", async (req, res) => {
  res.set("Content-Type", registry.contentType);
  res.end(await registry.metrics());
});

Structured Logging

import pino from "pino";

const logger = pino({
  level: process.env.LOG_LEVEL ?? "info",
  formatters: {
    level: (label) => ({ level: label }),
  },
  redact: ["req.headers.authorization", "password", "token"],
});

function requestLogger(req, res, next) {
  const start = Date.now();
  res.on("finish", () => {
    logger.info({
      method: req.method,
      url: req.url,
      status: res.statusCode,
      duration_ms: Date.now() - start,
      trace_id: req.headers["x-trace-id"],
    });
  });
  next();
}

Alerting Rules

groups:
  - name: api-alerts
    rules:
      - alert: HighErrorRate
        expr: rate(http_request_duration_seconds_count{status=~"5.."}[5m]) / rate(http_request_duration_seconds_count[5m]) > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Error rate above 5% for {{ $labels.route }}"

      - alert: HighLatency
        expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 2
        for: 10m
        labels:
          severity: warning

Anti-Patterns

  • Logging sensitive data (passwords, tokens, PII) without redaction
  • Using string interpolation in log messages instead of structured fields
  • Creating unbounded cardinality in metric labels (e.g., user IDs as labels)
  • Not correlating logs and traces with a shared trace ID
  • Alerting on symptoms (high CPU) without understanding root cause
  • Missing SLO definitions before building dashboards

Checklist

  • OpenTelemetry SDK initialized with auto-instrumentation for HTTP, DB, and messaging
  • Custom spans added for business-critical operations
  • Metrics use bounded label cardinality
  • Structured logging with JSON output and secret redaction
  • Trace context propagated across service boundaries
  • Alerting rules based on SLOs (error rate, latency percentiles)
  • Dashboards show RED metrics (Rate, Errors, Duration) per service
  • Log retention and rotation policies configured

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 2 of the 12 instructions most monitoring observability skills give in ~1.3k tokens

Counted across 530 of the 532 authors here whose files we hold, read 2026-09-06

  • Use structured JSON logginghere, and in 40 of 530, across 36 files
  • Link every alert to a runbookin 29 of 530, across 27 files
  • Attach correlation IDs to every log linein 19 of 530, across 16 files
  • Alert on symptoms rather than causesin 19 of 530, across 17 files
  • Use OpenTelemetry for distributed tracingin 15 of 530, across 14 files
  • Alert on symptoms users feelin 15 of 530, across 13 files
  • Implement health check endpointsin 14 of 530, across 10 files
  • Inspect existing dashboards firstin 12 of 530, across 4 files
  • Build the minimum useful boardin 12 of 530, across 4 files
  • Start from operator questionsin 12 of 530, across 4 files
  • Propagate trace context across boundarieshere, and in 11 of 530, across 10 files
  • Include trace id in all log entriesin 10 of 530, across 9 files

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.