| name | mistral-observability |
| description | Set up comprehensive observability for Mistral AI integrations with metrics, traces, and alerts.
Use when implementing monitoring for Mistral AI operations, setting up dashboards,
or configuring alerting for Mistral AI integration health.
Trigger with phrases like "mistral monitoring", "mistral metrics",
"mistral observability", "monitor mistral", "mistral alerts", "mistral tracing".
|
| allowed-tools | Read, Write, Edit |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Mistral AI Observability
Overview
Set up comprehensive observability for Mistral AI integrations.
Prerequisites
- Prometheus or compatible metrics backend
- OpenTelemetry SDK installed (optional)
- Grafana or similar dashboarding tool
- AlertManager or similar alerting system
Instructions
Step 1: Define Key Metrics
| Metric | Type | Description |
|---|
mistral_requests_total | Counter | Total API requests |
mistral_request_duration_seconds | Histogram | Request latency |
mistral_tokens_total | Counter | Tokens used (input/output) |
mistral_errors_total | Counter | Error count by type |
mistral_cost_usd | Counter | Estimated cost |
mistral_cache_hits_total | Counter | Cache hit count |
Step 2: Implement Prometheus Metrics
import { Registry, Counter, Histogram, Gauge } from 'prom-client';
const registry = new Registry();
const requestCounter = new Counter({
name: 'mistral_requests_total',
help: 'Total Mistral AI API requests',
labelNames: ['model', 'status', 'endpoint'],
registers: [registry],
});
const requestDuration = new Histogram({
name: 'mistral_request_duration_seconds',
help: 'Mistral AI request duration in seconds',
labelNames: ['model', 'endpoint'],
buckets: [0.1, 0.25, 0.5, 1, 2.5, 5, 10],
registers: [registry],
});
const tokenCounter = new Counter({
name: 'mistral_tokens_total',
help: 'Total tokens used',
labelNames: [, ],
: [registry],
});
errorCounter = ({
: ,
: ,
: [, , ],
: [registry],
});
costCounter = ({
: ,
: ,
: [],
: [registry],
});
{ registry, requestCounter, requestDuration, tokenCounter, errorCounter, costCounter };
Step 3: Create Instrumented Client Wrapper
import Mistral from '@mistralai/mistralai';
import {
requestCounter,
requestDuration,
tokenCounter,
errorCounter,
costCounter,
} from './metrics';
const PRICING: Record<string, { input: number; output: number }> = {
'mistral-small-latest': { input: 0.20, output: 0.60 },
'mistral-large-latest': { input: 2.00, output: 6.00 },
'mistral-embed': { input: 0.10, output: 0 },
};
export async function instrumentedChat(
client: Mistral,
model: string,
messages: any[],
options?: { temperature?: number; maxTokens?: number }
): Promise<any> {
const timer = requestDuration.startTimer({ model, endpoint: 'chat.complete' });
try {
response = client..({
model,
messages,
...options,
});
requestCounter.({ model, : , : });
(response.) {
tokenCounter.({ model, : }, response.. || );
tokenCounter.({ model, : }, response.. || );
pricing = [model] || [];
cost =
((response.. || ) / ) * pricing. +
((response.. || ) / ) * pricing.;
costCounter.({ model }, cost);
}
response;
} (: ) {
requestCounter.({ model, : , : });
errorCounter.({
model,
: error. || ,
: error.?.() || ,
});
error;
} {
();
}
}
Step 4: OpenTelemetry Distributed Tracing
import { trace, SpanStatusCode, Span } from '@opentelemetry/api';
const tracer = trace.getTracer('mistral-client');
export async function tracedChat<T>(
operationName: string,
operation: () => Promise<T>,
attributes?: Record<string, string>
): Promise<T> {
return tracer.startActiveSpan(`mistral.${operationName}`, async (span: Span) => {
if (attributes) {
Object.entries(attributes).forEach(([key, value]) => {
span.setAttribute(key, value);
});
}
try {
const result = await operation();
if ((result as any).usage) {
span.setAttribute('mistral.input_tokens', (result as any).usage.promptTokens);
span.(, (result )..);
}
span.({ : . });
result;
} (: ) {
span.({
: .,
: error.,
});
span.(error);
error;
} {
span.();
}
});
}
response = (
,
client..({ model, messages }),
{ model, : userId }
);
Step 5: Structured Logging
import pino from 'pino';
const logger = pino({
name: 'mistral',
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label }),
},
});
interface MistralLogContext {
requestId: string;
model: string;
operation: string;
durationMs: number;
inputTokens?: number;
outputTokens?: number;
cached?: boolean;
error?: string;
}
export function logMistralOperation(context: MistralLogContext): void {
const { error, ...rest } = context;
if (error) {
logger.error({ ...rest, error }, 'Mistral operation failed');
} else {
logger.info(rest, 'Mistral operation completed');
}
}
logMistralOperation({
requestId: 'req-123',
: ,
: ,
: ,
: ,
: ,
});
Step 6: Alert Configuration
groups:
- name: mistral_alerts
rules:
- alert: MistralHighErrorRate
expr: |
rate(mistral_errors_total[5m]) /
rate(mistral_requests_total[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "Mistral AI error rate > 5%"
description: "Error rate is {{ $value | humanizePercentage }}"
- alert: MistralHighLatency
expr: |
histogram_quantile(0.95,
rate(mistral_request_duration_seconds_bucket[5m])
) > 5
for: 5m
labels:
severity: warning
annotations:
summary: "Mistral AI P95 latency > 5s"
- alert: MistralRateLimitWarning
expr: |
rate(mistral_errors_total{error_type="rate_limit"}[5m]) > 0
for: 2m
labels:
severity: warning
Step 7: Grafana Dashboard
{
"title": "Mistral AI Monitoring",
"panels": [
{
"title": "Request Rate",
"type": "timeseries",
"targets": [{
"expr": "rate(mistral_requests_total[5m])",
"legendFormat": "{{model}} - {{status}}"
}]
},
{
"title": "Latency P50/P95/P99",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.5, rate(mistral_request_duration_seconds_bucket[5m]))",
"legendFormat": "P50"
},
{
Output
- Prometheus metrics collection
- OpenTelemetry tracing
- Structured logging
- Alert rules configured
Error Handling
| Issue | Cause | Solution |
|---|
| Missing metrics | No instrumentation | Wrap client calls |
| Trace gaps | Missing propagation | Check context headers |
| Alert storms | Wrong thresholds | Tune alert rules |
| High cardinality | Too many labels | Reduce label values |
Examples
Metrics Endpoint (Express)
import express from 'express';
import { registry } from './metrics';
const app = express();
app.get('/metrics', async (req, res) => {
res.set('Content-Type', registry.contentType);
res.send(await registry.metrics());
});
Resources
Next Steps
For incident response, see mistral-incident-runbook.