| name | maintainx-observability |
| description | Implement comprehensive observability for MaintainX integrations.
Use when setting up monitoring, logging, tracing, and alerting
for MaintainX API integrations.
Trigger with phrases like "maintainx monitoring", "maintainx logging",
"maintainx metrics", "maintainx observability", "maintainx alerts".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
MaintainX Observability
Overview
Implement comprehensive observability (metrics, logging, tracing) for MaintainX integrations to ensure reliability and quick issue resolution.
Prerequisites
- MaintainX integration deployed
- Monitoring platform (Datadog, Prometheus, CloudWatch)
- Log aggregation solution
Three Pillars of Observability
┌─────────────────────────────────────────────────────────────────────┐
│ Observability Stack │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ METRICS │ │ LOGGING │ │ TRACING │ │
│ │ │ │ │ │ │ │
│ │ - API latency │ │ - Request logs │ │ - Request flow │ │
│ │ - Error rates │ │ - Error details │ │ - Dependencies │ │
│ │ - Throughput │ │ - Audit trail │ │ - Bottlenecks │ │
│ │ - Cache hits │ │ - Debug info │ │ - Service map │ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ └────────────────────┼────────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ DASHBOARDS │ │
│ │ & ALERTS │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Instructions
Step 1: Metrics Collection
import { Counter, Histogram, Gauge, Registry } from 'prom-client';
const registry = new Registry();
const apiRequestsTotal = new Counter({
name: 'maintainx_api_requests_total',
help: 'Total number of MaintainX API requests',
labelNames: ['endpoint', 'method', 'status'],
registers: [registry],
});
const apiRequestDuration = new Histogram({
name: 'maintainx_api_request_duration_seconds',
help: 'MaintainX API request duration in seconds',
labelNames: ['endpoint', 'method'],
buckets: [0.1, 0.25, 0.5, 1, 2, 5, 10],
registers: [registry],
});
const apiErrorsTotal = new Counter({
name: 'maintainx_api_errors_total',
help: 'Total number of MaintainX API errors',
: [, , ],
: [registry],
});
cacheHitsTotal = ({
: ,
: ,
: [],
: [registry],
});
cacheMissesTotal = ({
: ,
: ,
: [],
: [registry],
});
rateLimitRemaining = ({
: ,
: ,
: [registry],
});
workOrdersCreated = ({
: ,
: ,
: [],
: [registry],
});
{
: ;
() {
timer = apiRequestDuration.({
: ,
: ,
});
{
response = ..(params);
apiRequestsTotal.({
: ,
: ,
: ,
});
response;
} (: ) {
status = error.?. || ;
apiRequestsTotal.({
: ,
: ,
: (status),
});
apiErrorsTotal.({
: ,
: error.,
: (status),
});
error;
} {
();
}
}
() {
response = ..(data);
workOrdersCreated.({
: data. || ,
});
response;
}
}
() {
(: , : ) => {
res.(, registry.);
res.( registry.());
};
}
Step 2: Structured Logging
import winston from 'winston';
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: {
service: 'maintainx-integration',
environment: process.env.NODE_ENV,
},
transports: [
new winston.transports.Console(),
],
});
interface LogContext {
requestId: string;
userId?: string;
tenantId?: string;
operation: string;
}
class ContextLogger {
private context: LogContext;
() {
. = context;
}
() {
logger.(message, { ...., ...meta });
}
() {
logger.(message, { ...., ...meta });
}
() {
logger.(message, {
....,
...meta,
: error ? {
: error.,
: error.,
: error.,
} : ,
});
}
() {
.(, {
endpoint,
method,
: .(params),
});
}
() {
.(, {
endpoint,
status,
: duration,
});
}
() {
.(, error, {
endpoint,
status,
});
}
(: ): {
(!obj) obj;
redacted = { ...obj };
sensitiveFields = [, , , ];
sensitiveFields.( {
(redacted[field]) {
redacted[field] = ;
}
});
redacted;
}
}
{ logger, };
Step 3: Distributed Tracing
import { trace, SpanKind, SpanStatusCode } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
const provider = new NodeTracerProvider({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'maintainx-integration',
[SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version,
}),
});
provider.register();
const tracer = trace.getTracer('maintainx-integration');
class TracedMaintainXClient {
private client: MaintainXClient;
async getWorkOrders(params?: any) {
return tracer.(, {
: .,
: {
: ,
: ,
: params?.,
},
}, (span) => {
{
response = ..(params);
span.({
: response..,
: !!response.,
});
span.({ : . });
response;
} (: ) {
span.({
: .,
: error.,
});
span.(error);
error;
} {
span.();
}
});
}
() {
tracer.(, {
: .,
: {
: ,
: ,
: data.,
},
}, (span) => {
{
response = ..(data);
span.({
: response.,
});
span.({ : . });
response;
} (: ) {
span.({
: .,
: error.,
});
span.(error);
error;
} {
span.();
}
});
}
}
Step 4: Health Checks
interface HealthCheck {
name: string;
check: () => Promise<boolean>;
critical: boolean;
}
interface HealthStatus {
status: 'healthy' | 'degraded' | 'unhealthy';
timestamp: string;
checks: Record<string, { status: boolean; latencyMs: number }>;
}
class HealthChecker {
private checks: HealthCheck[] = [];
register(check: HealthCheck) {
this.checks.push(check);
}
async getStatus(): Promise<HealthStatus> {
const results: Record<string, { status: boolean; latencyMs: number }> = {};
let hasCriticalFailure = false;
let hasAnyFailure = ;
( check .) {
start = .();
status = ;
{
status = check.();
} (error) {
status = ;
}
results[check.] = {
status,
: .() - start,
};
(!status) {
hasAnyFailure = ;
(check.) {
hasCriticalFailure = ;
}
}
}
{
: hasCriticalFailure ? : hasAnyFailure ? : ,
: ().(),
: results,
};
}
}
healthChecker = ();
healthChecker.({
: ,
: ,
: () => {
client = ();
client.({ : });
;
},
});
healthChecker.({
: ,
: ,
: () => {
redis = ();
redis.();
;
},
});
{ healthChecker, };
Step 5: Alerting Rules
groups:
- name: maintainx-alerts
rules:
- alert: MaintainXHighErrorRate
expr: |
sum(rate(maintainx_api_errors_total[5m])) /
sum(rate(maintainx_api_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: High MaintainX API error rate
description: "Error rate is {{ $value | humanizePercentage }} (threshold: 5%)"
- alert: MaintainXHighLatency
expr: |
histogram_quantile(0.95, rate(maintainx_api_request_duration_seconds_bucket[5m])) > 2
for: 5m
labels:
severity: warning
annotations:
summary: High MaintainX API latency
description: "P95 latency is {{ $value }}s (threshold: 2s)"
-
Step 6: Dashboard Configuration
{
"dashboard": {
"title": "MaintainX Integration Dashboard",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "sum(rate(maintainx_api_requests_total[5m])) by (endpoint)",
"legendFormat": "{{endpoint}}"
}
]
},
{
"title": "Error Rate",
"type": "graph",
"targets": [
{
"expr": "sum(rate(maintainx_api_errors_total[5m])) by (status_code)",
"legendFormat":
Output
- Prometheus metrics collection
- Structured JSON logging
- Distributed tracing setup
- Health check endpoints
- Alerting rules configured
- Dashboard definition
Key Metrics to Monitor
| Metric | Threshold | Action |
|---|
| Error rate | >5% | Investigate API issues |
| P95 latency | >2s | Check network/caching |
| Rate limit remaining | <10 | Reduce request rate |
| Cache hit rate | <50% | Review caching strategy |
Resources
Next Steps
For incident response, see maintainx-incident-runbook.