| name | deepgram-observability |
| description | Set up comprehensive observability for Deepgram integrations with metrics, traces, and alerts.
Use when implementing monitoring for Deepgram operations, setting up dashboards,
or configuring alerting for Deepgram integration health.
Trigger with phrases like "deepgram monitoring", "deepgram metrics",
"deepgram observability", "monitor deepgram", "deepgram alerts", "deepgram tracing".
|
| allowed-tools | Read, Write, Edit, Bash(kubectl:*), Bash(curl:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Deepgram Observability
Overview
Implement comprehensive observability for Deepgram integrations including metrics, distributed tracing, logging, and alerting.
Prerequisites
- Prometheus or compatible metrics backend
- OpenTelemetry SDK installed
- Grafana or similar dashboarding tool
- AlertManager configured
Observability Pillars
| Pillar | Tool | Purpose |
|---|
| Metrics | Prometheus | Performance & usage tracking |
| Traces | OpenTelemetry | Request flow visibility |
| Logs | Structured JSON | Debugging & audit |
| Alerts | AlertManager | Incident notification |
Instructions
Step 1: Set Up Metrics Collection
Implement Prometheus counters, histograms, and gauges for key operations.
Step 2: Add Distributed Tracing
Integrate OpenTelemetry for end-to-end request tracing.
Step 3: Configure Structured Logging
Set up JSON logging with consistent field names.
Step 4: Create Alert Rules
Define alerting rules for error rates and latency.
Examples
Prometheus Metrics
import { Registry, Counter, Histogram, Gauge, collectDefaultMetrics } from 'prom-client';
export const registry = new Registry();
collectDefaultMetrics({ register: registry });
export const transcriptionRequests = new Counter({
name: 'deepgram_transcription_requests_total',
help: 'Total number of transcription requests',
labelNames: ['status', 'model', 'type'],
registers: [registry],
});
export const transcriptionLatency = new Histogram({
name: 'deepgram_transcription_latency_seconds',
help: 'Transcription request latency in seconds',
labelNames: ['model', 'type'],
buckets: [0.1, 0.5, 1, 2, 5, 10, 30, 60, 120],
registers: [registry],
});
audioProcessed = ({
: ,
: ,
: [],
: [registry],
});
activeConnections = ({
: ,
: ,
: [],
: [registry],
});
rateLimitHits = ({
: ,
: ,
: [registry],
});
estimatedCost = ({
: ,
: ,
: [],
: [registry],
});
(): <> {
registry.();
}
Instrumented Transcription Client
import { createClient, DeepgramClient } from '@deepgram/sdk';
import {
transcriptionRequests,
transcriptionLatency,
audioProcessed,
estimatedCost,
} from './metrics';
import { trace, context, SpanStatusCode } from '@opentelemetry/api';
import { logger } from './logger';
const tracer = trace.getTracer('deepgram-client');
const modelCosts: Record<string, number> = {
'nova-2': 0.0043,
'nova': 0.0043,
'base': 0.0048,
};
export class InstrumentedDeepgramClient {
private client: DeepgramClient;
constructor(apiKey: string) {
this.client = createClient(apiKey);
}
async transcribeUrl(url: string, options: { model?: string } = {}) {
const model = options. || ;
startTime = .();
tracer.(, (span) => {
span.(, model);
span.(, url);
{
{ result, error } = ....(
{ url },
{ model, : }
);
duration = (.() - startTime) / ;
(error) {
transcriptionRequests.(, model, ).();
span.({ : ., : error. });
logger.(, {
model,
: error.,
duration,
});
error;
}
transcriptionRequests.(, model, ).();
transcriptionLatency.(model, ).(duration);
audioDuration = result..;
audioProcessed.(model).(audioDuration);
cost = (audioDuration / ) * (modelCosts[model] || );
estimatedCost.(model).(cost);
span.(, result..);
span.(, audioDuration);
span.(, duration);
span.({ : . });
logger.(, {
: result..,
model,
audioDuration,
: duration,
cost,
});
result;
} (err) {
duration = (.() - startTime) / ;
transcriptionRequests.(, model, ).();
transcriptionLatency.(model, ).(duration);
span.({
: .,
: err ? err. : ,
});
logger.(, {
model,
: err ? err. : ,
duration,
});
err;
} {
span.();
}
});
}
}
OpenTelemetry Configuration
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'deepgram-service',
[SemanticResourceAttributes.SERVICE_VERSION]: process.env.VERSION || '1.0.0',
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV || 'development',
}),
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317',
}),
instrumentations: [
getNodeAutoInstrumentations({
: {
: [, ],
},
}),
],
});
(): {
sdk.();
process.(, {
sdk.()
.( .())
.( .(, error))
.( process.());
});
}
Structured Logging
import pino from 'pino';
export const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label }),
},
base: {
service: 'deepgram-service',
version: process.env.VERSION || '1.0.0',
environment: process.env.NODE_ENV || 'development',
},
timestamp: pino.stdTimeFunctions.isoTime,
});
export const transcriptionLogger = logger.child({ component: 'transcription' });
export const metricsLogger = logger.child({ component: 'metrics' });
export const alertLogger = logger.child({ component: 'alerts' });
Grafana Dashboard Configuration
{
"dashboard": {
"title": "Deepgram Transcription Service",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "sum(rate(deepgram_transcription_requests_total[5m])) by (status)",
"legendFormat": "{{status}}"
}
]
},
{
"title": "Latency (P95)",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(deepgram_transcription_latency_seconds_bucket[5m])) by (le, model))",
"legendFormat"
AlertManager Rules
groups:
- name: deepgram-alerts
rules:
- alert: DeepgramHighErrorRate
expr: |
sum(rate(deepgram_transcription_requests_total{status="error"}[5m])) /
sum(rate(deepgram_transcription_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
service: deepgram
annotations:
summary: "High Deepgram error rate (> 5%)"
description: "Error rate is {{ $value | humanizePercentage }}"
runbook: "https://wiki.example.com/runbooks/deepgram-errors"
- alert: DeepgramHighLatency
expr: |
histogram_quantile(0.95,
sum(rate(deepgram_transcription_latency_seconds_bucket[5m])) by (le)
) > 30
for: 5m
labels:
severity: warning
service: deepgram
annotations:
summary: "High Deepgram latency (P95 > 30s)"
description: "P95 latency is {{ $value | humanizeDuration }}"
- alert:
Health Check Endpoint
import express from 'express';
import { createClient } from '@deepgram/sdk';
import { getMetrics } from '../lib/metrics';
const router = express.Router();
interface HealthCheck {
status: 'healthy' | 'degraded' | 'unhealthy';
timestamp: string;
checks: Record<string, {
status: 'pass' | 'fail';
latency?: number;
message?: string;
}>;
}
router.get('/health', async (req, res) => {
const health: HealthCheck = {
status: 'healthy',
timestamp: new Date().toISOString(),
checks: {},
};
const startTime = Date.now();
try {
const client = createClient(process.env.DEEPGRAM_API_KEY!);
{ error } = client..();
health.. = {
: error ? : ,
: .() - startTime,
: error?.,
};
} (err) {
health.. = {
: ,
: .() - startTime,
: err ? err. : ,
};
}
failedChecks = .(health.).( c. === );
(failedChecks. > ) {
health. = ;
}
statusCode = health. === ? : ;
res.(statusCode).(health);
});
router.(, (req, res) => {
res.(, );
res.( ());
});
router;
Resources
Next Steps
Proceed to deepgram-incident-runbook for incident response procedures.