Skip to content

Monitoring Guide ​

This comprehensive guide covers monitoring strategies, tools, and best practices for applications and infrastructure built with Trae.

Overview ​

Effective monitoring is crucial for maintaining application performance, reliability, and user experience. This guide covers:

  • Monitoring fundamentals
  • Application performance monitoring (APM)
  • Infrastructure monitoring
  • Log management
  • Alerting strategies
  • Observability best practices
  • Monitoring tools and platforms

Monitoring Fundamentals ​

Key Concepts ​

The Three Pillars of Observability ​

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│     Metrics     │    │      Logs       │    │     Traces      │
│                 │    │                 │    │                 │
│  • Counters     │    │  • Events       │    │  • Requests     │
│  • Gauges       │    │  • Errors       │    │  • Spans        │
│  • Histograms   │    │  • Debug Info   │    │  • Dependencies │
│  • Summaries    │    │  • Audit Trail  │    │  • Performance │
└─────────────────┘    └─────────────────┘    └─────────────────┘

Monitoring Types ​

  • Synthetic Monitoring: Proactive testing with simulated transactions
  • Real User Monitoring (RUM): Actual user experience tracking
  • Infrastructure Monitoring: System resources and health
  • Application Monitoring: Code-level performance and errors
  • Business Monitoring: KPIs and business metrics

Monitoring Strategy ​

SLI, SLO, and SLA Framework ​

yaml
# Service Level Indicators (SLIs)
slis:
  availability:
    description: "Percentage of successful requests"
    measurement: "(successful_requests / total_requests) * 100"
    target: "> 99.9%"
  
  latency:
    description: "95th percentile response time"
    measurement: "response_time_95th_percentile"
    target: "< 200ms"
  
  error_rate:
    description: "Percentage of failed requests"
    measurement: "(failed_requests / total_requests) * 100"
    target: "< 0.1%"

# Service Level Objectives (SLOs)
slos:
  - name: "API Availability"
    sli: "availability"
    target: "99.9% over 30 days"
    error_budget: "0.1%"
  
  - name: "Response Time"
    sli: "latency"
    target: "95% of requests < 200ms"
    measurement_window: "5 minutes"

# Service Level Agreements (SLAs)
slas:
  - name: "Service Uptime"
    commitment: "99.5% monthly uptime"
    penalty: "Service credits for downtime"
    measurement: "External monitoring"

Application Performance Monitoring ​

APM Implementation ​

Node.js Application Monitoring ​

javascript
// app.js - APM setup
const apm = require('elastic-apm-node').start({
  serviceName: 'my-app',
  secretToken: process.env.ELASTIC_APM_SECRET_TOKEN,
  serverUrl: process.env.ELASTIC_APM_SERVER_URL,
  environment: process.env.NODE_ENV,
  captureBody: 'errors',
  captureHeaders: true,
  logLevel: 'info'
});

const express = require('express');
const prometheus = require('prom-client');
const app = express();

// Prometheus metrics
const register = new prometheus.Registry();
prometheus.collectDefaultMetrics({ register });

// Custom metrics
const httpRequestDuration = new prometheus.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status'],
  buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10]
});

const httpRequestTotal = new prometheus.Counter({
  name: 'http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'route', 'status']
});

register.registerMetric(httpRequestDuration);
register.registerMetric(httpRequestTotal);

// Middleware for metrics collection
app.use((req, res, next) => {
  const start = Date.now();
  
  res.on('finish', () => {
    const duration = (Date.now() - start) / 1000;
    const route = req.route ? req.route.path : req.path;
    
    httpRequestDuration
      .labels(req.method, route, res.statusCode)
      .observe(duration);
    
    httpRequestTotal
      .labels(req.method, route, res.statusCode)
      .inc();
  });
  
  next();
});

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'healthy',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    version: process.env.npm_package_version
  });
});

// Metrics endpoint
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});

// Error handling with APM
app.use((err, req, res, next) => {
  apm.captureError(err);
  console.error('Error:', err);
  res.status(500).json({ error: 'Internal Server Error' });
});

module.exports = app;

Python Application Monitoring ​

python
# app.py - APM setup
import os
import time
from flask import Flask, request, jsonify
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
import elasticapm
from elasticapm.contrib.flask import ElasticAPM

app = Flask(__name__)

# Elastic APM configuration
app.config['ELASTIC_APM'] = {
    'SERVICE_NAME': 'my-python-app',
    'SECRET_TOKEN': os.environ.get('ELASTIC_APM_SECRET_TOKEN'),
    'SERVER_URL': os.environ.get('ELASTIC_APM_SERVER_URL'),
    'ENVIRONMENT': os.environ.get('FLASK_ENV', 'production'),
    'CAPTURE_BODY': 'errors',
    'CAPTURE_HEADERS': True
}

apm = ElasticAPM(app)

# Prometheus metrics
REQUEST_COUNT = Counter(
    'http_requests_total',
    'Total HTTP requests',
    ['method', 'endpoint', 'status']
)

REQUEST_LATENCY = Histogram(
    'http_request_duration_seconds',
    'HTTP request latency',
    ['method', 'endpoint'],
    buckets=[0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10]
)

@app.before_request
def before_request():
    request.start_time = time.time()

@app.after_request
def after_request(response):
    request_latency = time.time() - request.start_time
    
    REQUEST_COUNT.labels(
        method=request.method,
        endpoint=request.endpoint or 'unknown',
        status=response.status_code
    ).inc()
    
    REQUEST_LATENCY.labels(
        method=request.method,
        endpoint=request.endpoint or 'unknown'
    ).observe(request_latency)
    
    return response

@app.route('/health')
def health_check():
    return jsonify({
        'status': 'healthy',
        'timestamp': time.time(),
        'version': os.environ.get('APP_VERSION', 'unknown')
    })

@app.route('/metrics')
def metrics():
    return generate_latest(), 200, {'Content-Type': CONTENT_TYPE_LATEST}

@app.errorhandler(Exception)
def handle_exception(e):
    apm.capture_exception()
    return jsonify({'error': 'Internal Server Error'}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Custom Metrics Implementation ​

Business Metrics ​

javascript
// business-metrics.js
const prometheus = require('prom-client');

class BusinessMetrics {
  constructor() {
    this.userRegistrations = new prometheus.Counter({
      name: 'user_registrations_total',
      help: 'Total number of user registrations',
      labelNames: ['source', 'plan']
    });
    
    this.orderValue = new prometheus.Histogram({
      name: 'order_value_dollars',
      help: 'Order value in dollars',
      labelNames: ['product_category'],
      buckets: [10, 50, 100, 500, 1000, 5000]
    });
    
    this.activeUsers = new prometheus.Gauge({
      name: 'active_users_current',
      help: 'Current number of active users',
      labelNames: ['session_type']
    });
    
    this.featureUsage = new prometheus.Counter({
      name: 'feature_usage_total',
      help: 'Total feature usage count',
      labelNames: ['feature_name', 'user_tier']
    });
  }
  
  recordUserRegistration(source, plan) {
    this.userRegistrations.labels(source, plan).inc();
  }
  
  recordOrder(value, category) {
    this.orderValue.labels(category).observe(value);
  }
  
  updateActiveUsers(count, sessionType) {
    this.activeUsers.labels(sessionType).set(count);
  }
  
  recordFeatureUsage(featureName, userTier) {
    this.featureUsage.labels(featureName, userTier).inc();
  }
}

module.exports = new BusinessMetrics();

Performance Metrics ​

javascript
// performance-metrics.js
const prometheus = require('prom-client');

class PerformanceMetrics {
  constructor() {
    this.databaseQueryDuration = new prometheus.Histogram({
      name: 'database_query_duration_seconds',
      help: 'Database query duration',
      labelNames: ['query_type', 'table'],
      buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5]
    });
    
    this.cacheHitRate = new prometheus.Gauge({
      name: 'cache_hit_rate',
      help: 'Cache hit rate percentage',
      labelNames: ['cache_type']
    });
    
    this.queueSize = new prometheus.Gauge({
      name: 'queue_size_current',
      help: 'Current queue size',
      labelNames: ['queue_name']
    });
    
    this.externalApiCalls = new prometheus.Counter({
      name: 'external_api_calls_total',
      help: 'Total external API calls',
      labelNames: ['service', 'endpoint', 'status']
    });
  }
  
  recordDatabaseQuery(queryType, table, duration) {
    this.databaseQueryDuration.labels(queryType, table).observe(duration);
  }
  
  updateCacheHitRate(cacheType, hitRate) {
    this.cacheHitRate.labels(cacheType).set(hitRate);
  }
  
  updateQueueSize(queueName, size) {
    this.queueSize.labels(queueName).set(size);
  }
  
  recordExternalApiCall(service, endpoint, status) {
    this.externalApiCalls.labels(service, endpoint, status).inc();
  }
}

module.exports = new PerformanceMetrics();

Infrastructure Monitoring ​

Prometheus Configuration ​

yaml
# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: 'production'
    region: 'us-west-2'

rule_files:
  - "alert_rules.yml"
  - "recording_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

scrape_configs:
  # Application metrics
  - job_name: 'app'
    static_configs:
      - targets: ['app:3000']
    metrics_path: '/metrics'
    scrape_interval: 10s
    scrape_timeout: 5s
    
  # Node exporter for system metrics
  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']
    
  # Database metrics
  - job_name: 'postgres'
    static_configs:
      - targets: ['postgres-exporter:9187']
    
  # Redis metrics
  - job_name: 'redis'
    static_configs:
      - targets: ['redis-exporter:9121']
    
  # Nginx metrics
  - job_name: 'nginx'
    static_configs:
      - targets: ['nginx-exporter:9113']
    
  # Kubernetes metrics
  - job_name: 'kubernetes-apiservers'
    kubernetes_sd_configs:
      - role: endpoints
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
        action: keep
        regex: default;kubernetes;https

Alert Rules ​

yaml
# alert_rules.yml
groups:
  - name: application.rules
    rules:
      - alert: HighErrorRate
        expr: |
          (
            rate(http_requests_total{status=~"5.."}[5m]) /
            rate(http_requests_total[5m])
          ) * 100 > 5
        for: 5m
        labels:
          severity: critical
          team: backend
        annotations:
          summary: "High error rate detected"
          description: "Error rate is {{ $value }}% for {{ $labels.instance }}"
          runbook_url: "https://runbooks.example.com/high-error-rate"
      
      - alert: HighLatency
        expr: |
          histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 0.5
        for: 10m
        labels:
          severity: warning
          team: backend
        annotations:
          summary: "High latency detected"
          description: "95th percentile latency is {{ $value }}s for {{ $labels.instance }}"
      
      - alert: DatabaseConnectionsHigh
        expr: |
          pg_stat_database_numbackends / pg_settings_max_connections * 100 > 80
        for: 5m
        labels:
          severity: warning
          team: database
        annotations:
          summary: "Database connections high"
          description: "Database connections are at {{ $value }}% of maximum"
  
  - name: infrastructure.rules
    rules:
      - alert: HighCPUUsage
        expr: |
          100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 10m
        labels:
          severity: warning
          team: infrastructure
        annotations:
          summary: "High CPU usage"
          description: "CPU usage is {{ $value }}% on {{ $labels.instance }}"
      
      - alert: HighMemoryUsage
        expr: |
          (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 5m
        labels:
          severity: critical
          team: infrastructure
        annotations:
          summary: "High memory usage"
          description: "Memory usage is {{ $value }}% on {{ $labels.instance }}"
      
      - alert: DiskSpaceLow
        expr: |
          (1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100 > 85
        for: 5m
        labels:
          severity: warning
          team: infrastructure
        annotations:
          summary: "Disk space low"
          description: "Disk usage is {{ $value }}% on {{ $labels.instance }} {{ $labels.mountpoint }}"

Recording Rules ​

yaml
# recording_rules.yml
groups:
  - name: application.recording
    interval: 30s
    rules:
      - record: app:http_request_rate
        expr: |
          rate(http_requests_total[5m])
      
      - record: app:http_error_rate
        expr: |
          rate(http_requests_total{status=~"5.."}[5m]) /
          rate(http_requests_total[5m])
      
      - record: app:http_latency_p95
        expr: |
          histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
      
      - record: app:http_latency_p99
        expr: |
          histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
  
  - name: business.recording
    interval: 60s
    rules:
      - record: business:revenue_per_hour
        expr: |
          increase(order_value_dollars_sum[1h])
      
      - record: business:user_growth_rate
        expr: |
          rate(user_registrations_total[1h])
      
      - record: business:feature_adoption_rate
        expr: |
          rate(feature_usage_total[1h]) by (feature_name)

Log Management ​

Structured Logging ​

Node.js Logging ​

javascript
// logger.js
const winston = require('winston');
const { ElasticsearchTransport } = require('winston-elasticsearch');

const esTransportOpts = {
  level: 'info',
  clientOpts: {
    node: process.env.ELASTICSEARCH_URL || 'http://localhost:9200'
  },
  index: 'app-logs',
  indexTemplate: {
    name: 'app-logs-template',
    pattern: 'app-logs-*',
    settings: {
      number_of_shards: 1,
      number_of_replicas: 1
    },
    mappings: {
      properties: {
        '@timestamp': { type: 'date' },
        level: { type: 'keyword' },
        message: { type: 'text' },
        service: { type: 'keyword' },
        trace_id: { type: 'keyword' },
        span_id: { type: 'keyword' },
        user_id: { type: 'keyword' },
        request_id: { type: 'keyword' }
      }
    }
  }
};

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: process.env.SERVICE_NAME || 'app',
    version: process.env.APP_VERSION || 'unknown',
    environment: process.env.NODE_ENV || 'development'
  },
  transports: [
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple()
      )
    }),
    new ElasticsearchTransport(esTransportOpts)
  ]
});

// Request logging middleware
const requestLogger = (req, res, next) => {
  const start = Date.now();
  const requestId = req.headers['x-request-id'] || generateRequestId();
  
  req.logger = logger.child({
    request_id: requestId,
    user_id: req.user?.id,
    ip: req.ip,
    user_agent: req.get('User-Agent')
  });
  
  req.logger.info('Request started', {
    method: req.method,
    url: req.url,
    headers: req.headers
  });
  
  res.on('finish', () => {
    const duration = Date.now() - start;
    req.logger.info('Request completed', {
      method: req.method,
      url: req.url,
      status: res.statusCode,
      duration,
      content_length: res.get('Content-Length')
    });
  });
  
  next();
};

function generateRequestId() {
  return Math.random().toString(36).substring(2, 15) +
         Math.random().toString(36).substring(2, 15);
}

module.exports = { logger, requestLogger };

Python Logging ​

python
# logger.py
import logging
import json
import time
import uuid
from datetime import datetime
from flask import request, g
from pythonjsonlogger import jsonlogger

class CustomJsonFormatter(jsonlogger.JsonFormatter):
    def add_fields(self, log_record, record, message_dict):
        super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
        
        if not log_record.get('timestamp'):
            log_record['timestamp'] = datetime.utcnow().isoformat()
        
        if hasattr(g, 'request_id'):
            log_record['request_id'] = g.request_id
        
        if hasattr(g, 'user_id'):
            log_record['user_id'] = g.user_id
        
        log_record['service'] = 'my-python-app'
        log_record['version'] = os.environ.get('APP_VERSION', 'unknown')
        log_record['environment'] = os.environ.get('FLASK_ENV', 'development')

def setup_logging():
    formatter = CustomJsonFormatter(
        '%(timestamp)s %(level)s %(name)s %(message)s'
    )
    
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)
    
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    logger.addHandler(handler)
    
    return logger

def request_logging_middleware():
    @app.before_request
    def before_request():
        g.start_time = time.time()
        g.request_id = request.headers.get('X-Request-ID', str(uuid.uuid4()))
        g.user_id = getattr(request, 'user_id', None)
        
        logger.info('Request started', extra={
            'method': request.method,
            'url': request.url,
            'remote_addr': request.remote_addr,
            'user_agent': request.headers.get('User-Agent')
        })
    
    @app.after_request
    def after_request(response):
        duration = time.time() - g.start_time
        
        logger.info('Request completed', extra={
            'method': request.method,
            'url': request.url,
            'status': response.status_code,
            'duration': duration,
            'content_length': response.content_length
        })
        
        return response

logger = setup_logging()

Log Aggregation with ELK Stack ​

Logstash Configuration ​

ruby
# logstash.conf
input {
  beats {
    port => 5044
  }
  
  http {
    port => 8080
    codec => json
  }
}

filter {
  if [fields][service] {
    mutate {
      add_field => { "service" => "%{[fields][service]}" }
    }
  }
  
  # Parse JSON logs
  if [message] =~ /^\{.*\}$/ {
    json {
      source => "message"
    }
  }
  
  # Parse timestamp
  if [timestamp] {
    date {
      match => [ "timestamp", "ISO8601" ]
    }
  }
  
  # Extract error information
  if [level] == "error" {
    mutate {
      add_tag => [ "error" ]
    }
  }
  
  # Grok patterns for unstructured logs
  if ![level] {
    grok {
      match => { 
        "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" 
      }
    }
  }
  
  # GeoIP enrichment
  if [ip] {
    geoip {
      source => "ip"
      target => "geoip"
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "logs-%{service}-%{+YYYY.MM.dd}"
    template_name => "logs"
    template => "/usr/share/logstash/templates/logs.json"
    template_overwrite => true
  }
  
  # Debug output
  if [level] == "debug" {
    stdout {
      codec => rubydebug
    }
  }
}

Filebeat Configuration ​

yaml
# filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/app/*.log
  fields:
    service: my-app
    environment: production
  fields_under_root: true
  multiline.pattern: '^\d{4}-\d{2}-\d{2}'
  multiline.negate: true
  multiline.match: after

- type: docker
  enabled: true
  containers.ids:
    - '*'
  processors:
    - add_docker_metadata:
        host: "unix:///var/run/docker.sock"

processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_kubernetes_metadata:
      host: ${NODE_NAME}
      matchers:
      - logs_path:
          logs_path: "/var/log/containers/"

output.logstash:
  hosts: ["logstash:5044"]

logging.level: info
logging.to_files: true
logging.files:
  path: /var/log/filebeat
  name: filebeat
  keepfiles: 7
  permissions: 0644

Alerting Strategies ​

Alertmanager Configuration ​

yaml
# alertmanager.yml
global:
  smtp_smarthost: 'smtp.gmail.com:587'
  smtp_from: 'alerts@example.com'
  smtp_auth_username: 'alerts@example.com'
  smtp_auth_password: 'password'

route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'default'
  routes:
    - match:
        severity: critical
      receiver: 'critical-alerts'
      group_wait: 0s
      repeat_interval: 5m
    
    - match:
        team: database
      receiver: 'database-team'
    
    - match:
        team: frontend
      receiver: 'frontend-team'

receivers:
  - name: 'default'
    email_configs:
      - to: 'team@example.com'
        subject: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
        body: |
          {{ range .Alerts }}
          Alert: {{ .Annotations.summary }}
          Description: {{ .Annotations.description }}
          Labels: {{ range .Labels.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}
          {{ end }}
  
  - name: 'critical-alerts'
    email_configs:
      - to: 'oncall@example.com'
        subject: '[CRITICAL] {{ .GroupLabels.alertname }}'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
        channel: '#alerts'
        title: 'Critical Alert'
        text: |
          {{ range .Alerts }}
          *Alert:* {{ .Annotations.summary }}
          *Description:* {{ .Annotations.description }}
          *Runbook:* {{ .Annotations.runbook_url }}
          {{ end }}
    pagerduty_configs:
      - routing_key: 'YOUR_PAGERDUTY_INTEGRATION_KEY'
        description: '{{ .GroupLabels.alertname }}'
  
  - name: 'database-team'
    email_configs:
      - to: 'database-team@example.com'
        subject: '[DB Alert] {{ .GroupLabels.alertname }}'
  
  - name: 'frontend-team'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
        channel: '#frontend-alerts'

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'instance']

Alert Runbooks ​

markdown
# Alert Runbooks

## High Error Rate

### Symptoms
- Error rate > 5% for 5 minutes
- Users experiencing failures

### Investigation Steps
1. Check application logs for error patterns
2. Verify database connectivity
3. Check external service dependencies
4. Review recent deployments

### Resolution
1. If deployment related: rollback
2. If database issue: check connections and queries
3. If external service: implement circuit breaker

### Prevention
- Implement proper error handling
- Add circuit breakers for external services
- Improve deployment testing

## High Latency

### Symptoms
- 95th percentile latency > 500ms
- Slow user experience

### Investigation Steps
1. Check database query performance
2. Review application performance metrics
3. Check system resources (CPU, memory)
4. Analyze slow query logs

### Resolution
1. Optimize slow queries
2. Scale application instances
3. Add caching layers
4. Review code performance

### Prevention
- Regular performance testing
- Query optimization
- Proper indexing
- Caching strategy

Observability Best Practices ​

Distributed Tracing ​

OpenTelemetry Implementation ​

javascript
// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');

const jaegerExporter = new JaegerExporter({
  endpoint: process.env.JAEGER_ENDPOINT || 'http://localhost:14268/api/traces'
});

const sdk = new NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'my-app',
    [SemanticResourceAttributes.SERVICE_VERSION]: process.env.APP_VERSION || '1.0.0',
    [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV || 'development'
  }),
  traceExporter: jaegerExporter,
  instrumentations: [getNodeAutoInstrumentations()]
});

sdk.start();

// Custom tracing
const { trace } = require('@opentelemetry/api');

function createCustomSpan(name, operation) {
  const tracer = trace.getTracer('my-app');
  
  return tracer.startSpan(name, {
    kind: 1, // SpanKind.INTERNAL
    attributes: {
      'operation.name': operation
    }
  });
}

module.exports = { createCustomSpan };

Correlation IDs ​

javascript
// correlation.js
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();

function correlationMiddleware(req, res, next) {
  const correlationId = req.headers['x-correlation-id'] || 
                       req.headers['x-request-id'] || 
                       generateCorrelationId();
  
  res.setHeader('x-correlation-id', correlationId);
  
  asyncLocalStorage.run({ correlationId }, () => {
    req.correlationId = correlationId;
    next();
  });
}

function getCorrelationId() {
  const store = asyncLocalStorage.getStore();
  return store?.correlationId;
}

function generateCorrelationId() {
  return `${Date.now()}-${Math.random().toString(36).substring(2)}`;
}

module.exports = {
  correlationMiddleware,
  getCorrelationId
};

Monitoring Tools and Platforms ​

Grafana Dashboards ​

json
{
  "dashboard": {
    "title": "Application Overview",
    "tags": ["application", "overview"],
    "timezone": "browser",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total[5m])",
            "legendFormat": "{{instance}} - {{method}}"
          }
        ],
        "yAxes": [
          {
            "label": "Requests/sec",
            "min": 0
          }
        ]
      },
      {
        "title": "Error Rate",
        "type": "singlestat",
        "targets": [
          {
            "expr": "rate(http_requests_total{status=~\"5..\"}[5m]) / rate(http_requests_total[5m]) * 100",
            "legendFormat": "Error Rate %"
          }
        ],
        "thresholds": "1,5",
        "colorBackground": true
      },
      {
        "title": "Response Time",
        "type": "graph",
        "targets": [
          {
            "expr": "histogram_quantile(0.50, rate(http_request_duration_seconds_bucket[5m]))",
            "legendFormat": "50th percentile"
          },
          {
            "expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
            "legendFormat": "95th percentile"
          },
          {
            "expr": "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))",
            "legendFormat": "99th percentile"
          }
        ]
      }
    ],
    "time": {
      "from": "now-1h",
      "to": "now"
    },
    "refresh": "30s"
  }
}

Synthetic Monitoring ​

javascript
// synthetic-monitoring.js
const puppeteer = require('puppeteer');
const prometheus = require('prom-client');

const syntheticMetrics = {
  availability: new prometheus.Gauge({
    name: 'synthetic_check_availability',
    help: 'Synthetic check availability',
    labelNames: ['check_name', 'endpoint']
  }),
  
  responseTime: new prometheus.Histogram({
    name: 'synthetic_check_duration_seconds',
    help: 'Synthetic check duration',
    labelNames: ['check_name', 'endpoint'],
    buckets: [0.1, 0.5, 1, 2, 5, 10]
  })
};

class SyntheticMonitor {
  constructor() {
    this.checks = [];
  }
  
  addCheck(name, url, checkFunction) {
    this.checks.push({ name, url, checkFunction });
  }
  
  async runChecks() {
    const browser = await puppeteer.launch({ headless: true });
    
    for (const check of this.checks) {
      await this.runCheck(browser, check);
    }
    
    await browser.close();
  }
  
  async runCheck(browser, { name, url, checkFunction }) {
    const page = await browser.newPage();
    const startTime = Date.now();
    
    try {
      await page.goto(url, { waitUntil: 'networkidle2' });
      
      if (checkFunction) {
        await checkFunction(page);
      }
      
      const duration = (Date.now() - startTime) / 1000;
      
      syntheticMetrics.availability.labels(name, url).set(1);
      syntheticMetrics.responseTime.labels(name, url).observe(duration);
      
      console.log(`✓ Check ${name} passed in ${duration}s`);
      
    } catch (error) {
      const duration = (Date.now() - startTime) / 1000;
      
      syntheticMetrics.availability.labels(name, url).set(0);
      syntheticMetrics.responseTime.labels(name, url).observe(duration);
      
      console.error(`✗ Check ${name} failed:`, error.message);
    } finally {
      await page.close();
    }
  }
  
  startScheduler(intervalMs = 60000) {
    setInterval(() => {
      this.runChecks().catch(console.error);
    }, intervalMs);
  }
}

// Usage
const monitor = new SyntheticMonitor();

monitor.addCheck('homepage', 'https://example.com', async (page) => {
  await page.waitForSelector('h1');
  const title = await page.$eval('h1', el => el.textContent);
  if (!title.includes('Welcome')) {
    throw new Error('Homepage title incorrect');
  }
});

monitor.addCheck('login', 'https://example.com/login', async (page) => {
  await page.type('#username', 'test@example.com');
  await page.type('#password', 'password');
  await page.click('#login-button');
  await page.waitForNavigation();
  
  const url = page.url();
  if (!url.includes('/dashboard')) {
    throw new Error('Login failed');
  }
});

monitor.startScheduler(30000); // Run every 30 seconds

module.exports = monitor;

Best Practices Summary ​

Monitoring Strategy ​

  1. Define Clear SLIs/SLOs: Establish measurable service level indicators
  2. Implement Four Golden Signals: Latency, traffic, errors, saturation
  3. Use Structured Logging: Consistent, searchable log formats
  4. Correlation IDs: Track requests across services
  5. Distributed Tracing: Understand request flows

Alert Management ​

  1. Alert on Symptoms: Focus on user-impacting issues
  2. Reduce Alert Fatigue: Tune thresholds and group related alerts
  3. Actionable Alerts: Every alert should require action
  4. Runbook Documentation: Clear resolution steps
  5. Escalation Procedures: Define escalation paths

Performance Optimization ​

  1. Baseline Metrics: Establish performance baselines
  2. Continuous Monitoring: Monitor trends over time
  3. Capacity Planning: Proactive resource planning
  4. Performance Testing: Regular load and stress testing
  5. Optimization Cycles: Regular performance reviews

Tool Selection ​

  1. Standardization: Use consistent tools across teams
  2. Integration: Ensure tools work together
  3. Scalability: Choose tools that scale with growth
  4. Cost Management: Monitor tool costs and usage
  5. Training: Ensure team proficiency with tools

Your Ultimate AI-Powered IDE Learning Guide