Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/iii-hq/iii/llms.txt

Use this file to discover all available pages before exploring further.

iii provides comprehensive observability through OpenTelemetry integration, metrics collection, distributed tracing, and structured logging.

Configuration

Configure observability in config.yaml:
modules:
  - class: modules::observability::OtelModule
    config:
      # Tracing configuration
      enabled: true
      service_name: my-service
      service_version: 1.0.0
      service_namespace: production
      
      # Exporter: otlp, memory, or both
      exporter: otlp
      endpoint: http://localhost:4317
      
      # Sampling (0.0 to 1.0)
      sampling_ratio: 1.0
      
      # Memory storage (for 'memory' or 'both' exporters)
      memory_max_spans: 1000
      
      # Metrics configuration
      metrics_enabled: true
      metrics_exporter: otlp  # or 'memory'
      metrics_retention_seconds: 3600
      metrics_max_count: 10000
      
      # Logs configuration
      logs_enabled: true
      logs_exporter: memory  # or 'otlp', 'both'
      logs_retention_seconds: 3600
      logs_max_count: 10000

OpenTelemetry Traces

Exporters

iii supports multiple trace exporters:

OTLP (Production)

Export traces to OpenTelemetry collectors (Jaeger, Grafana Tempo, etc.).
exporter: otlp
endpoint: http://localhost:4317
Collector setup (Docker Compose):
services:
  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"  # UI
      - "4317:4317"    # OTLP gRPC
      - "4318:4318"    # OTLP HTTP

Memory (Development)

Store traces in-memory for API querying.
exporter: memory
memory_max_spans: 1000
Query via REST API:
curl http://localhost:3111/api/traces/list

Both (Hybrid)

Export to OTLP and store in memory (enables trace-based triggers).
exporter: both
endpoint: http://localhost:4317
memory_max_spans: 1000

Distributed Tracing

iii automatically propagates W3C trace context across function invocations. Trace context format:
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
             ││  │                                │                  │
             ││  └─ trace-id (128-bit)            │                  └─ flags
             ││                                    └─ parent-id (64-bit)
             │└─ version
             └─ version
Manual trace injection:
import { init } from 'iii-sdk';

const iii = init('ws://localhost:49134');

await iii.invoke('my.function', 
  { data: 'value' },
  {
    traceparent: '00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01',
    baggage: 'user_id=123,session_id=abc'
  }
);

Trace API

List traces:
curl -X POST http://localhost:3111/api/traces/list \
  -H "Content-Type: application/json" \
  -d '{
    "service_name": "my-service",
    "min_duration_ms": 100,
    "limit": 50
  }'
Filter options:
interface TracesListInput {
  trace_id?: string;              // Specific trace ID
  offset?: number;                // Pagination offset
  limit?: number;                 // Pagination limit (default: 100)
  service_name?: string;          // Filter by service
  name?: string;                  // Filter by span name
  status?: string;                // Filter by status
  min_duration_ms?: number;       // Minimum duration
  max_duration_ms?: number;       // Maximum duration
  start_time?: number;            // Unix timestamp (ms)
  end_time?: number;              // Unix timestamp (ms)
  sort_by?: "duration" | "start_time" | "name";
  sort_order?: "asc" | "desc";
  attributes?: [string, string][]; // Exact attribute matches
  include_internal?: boolean;     // Include engine.* traces
}
Get trace tree:
curl -X POST http://localhost:3111/api/traces/tree \
  -H "Content-Type: application/json" \
  -d '{"trace_id": "0af7651916cd43dd8448eb211c80319c"}'

Metrics

Metrics Exporters

Memory (Default)

Store metrics in-memory for API querying.
metrics_enabled: true
metrics_exporter: memory
metrics_retention_seconds: 3600
metrics_max_count: 10000

OTLP (Production)

Export metrics to OpenTelemetry collectors.
metrics_enabled: true
metrics_exporter: otlp
endpoint: http://localhost:4317

Prometheus Metrics

iii exposes Prometheus-compatible metrics on port 9464.
curl http://localhost:9464/metrics
Key metrics:
# Invocation metrics
iii_invocations_total{function_id="math.add"} 1234
iii_invocation_duration_seconds{function_id="math.add"} 0.042
iii_invocation_errors_total{function_id="math.add"} 5

# Worker metrics
iii_workers_active 3
iii_workers_spawns_total 10
iii_workers_deaths_total 2
iii_workers_by_status{status="connected"} 3

# Worker resource metrics
iii_worker_memory_heap_bytes{worker_id="w1"} 45678912
iii_worker_memory_rss_bytes{worker_id="w1"} 89123456
iii_worker_cpu_percent{worker_id="w1"} 12.5
iii_worker_event_loop_lag_ms{worker_id="w1"} 2.3
iii_worker_uptime_seconds{worker_id="w1"} 3600
See src/modules/observability/metrics.rs:244 for full metric definitions.

Metrics API

List metrics:
curl -X POST http://localhost:3111/api/metrics/list \
  -H "Content-Type: application/json" \
  -d '{
    "metric_name": "iii.invocations.total",
    "start_time": 1640000000000,
    "end_time": 1640100000000,
    "aggregate_interval": 300
  }'
Query options:
interface MetricsListInput {
  start_time?: number;        // Unix timestamp (ms)
  end_time?: number;          // Unix timestamp (ms)
  metric_name?: string;       // Filter by metric name
  aggregate_interval?: number; // Aggregation interval (seconds)
}

Worker Metrics

Workers automatically report resource metrics:
// Node.js SDK auto-reports these metrics
interface WorkerMetrics {
  memory_heap_used: number;    // Heap memory used (bytes)
  memory_heap_total: number;   // Total heap (bytes)
  memory_rss: number;          // Resident set size (bytes)
  memory_external: number;     // External memory (bytes)
  
  cpu_user_micros: number;     // User CPU time (μs)
  cpu_system_micros: number;   // System CPU time (μs)
  cpu_percent: number;         // Current CPU %
  
  event_loop_lag_ms: number;   // Event loop lag (ms)
  uptime_seconds: number;      // Worker uptime (s)
  
  timestamp_ms: number;        // Metric timestamp
  runtime: string;             // "node", "rust", "python"
}
Query worker metrics:
curl http://localhost:3111/api/workers/list
Response includes latest_metrics for each worker.

Structured Logging

Log Levels

Configure via environment or YAML:
modules:
  - class: modules::observability::LoggingModule
    config:
      level: info  # trace, debug, info, warn, error
      format: json # or 'pretty'

Log Exporters

Memory

Store logs in-memory for querying.
logs_enabled: true
logs_exporter: memory
logs_retention_seconds: 3600
logs_max_count: 10000

OTLP

Export logs to OpenTelemetry collectors.
logs_enabled: true
logs_exporter: otlp
endpoint: http://localhost:4317

Logs API

List logs:
curl -X POST http://localhost:3111/api/logs/list \
  -H "Content-Type: application/json" \
  -d '{
    "level": "error",
    "limit": 100
  }'

Alerting

Configure metric-based alerts:
modules:
  - class: modules::observability::OtelModule
    config:
      alerts:
        - name: high_error_rate
          metric: iii.invocations.error
          threshold: 10
          operator: ">"
          window_seconds: 60
          cooldown_seconds: 300
          action:
            type: webhook
            url: https://hooks.slack.com/...
        
        - name: worker_memory_high
          metric: worker.memory.rss
          threshold: 1073741824  # 1GB
          operator: ">="
          window_seconds: 30
          action:
            type: function
            path: alerts.worker_memory
Alert operators:
  • > (greater than)
  • >= (greater than or equal)
  • < (less than)
  • <= (less than or equal)
  • == (equal)
  • != (not equal)
Alert actions:
# Log alert (default)
action:
  type: log

# Webhook notification
action:
  type: webhook
  url: https://example.com/webhook

# Function invocation
action:
  type: function
  path: my.alert.handler

Advanced Sampling

Configure sampling strategies to reduce trace volume:
modules:
  - class: modules::observability::OtelModule
    config:
      sampling:
        # Default sampling ratio
        default: 0.1  # Sample 10% of traces
        
        # Per-operation sampling
        rules:
          - operation: "api.health"
            ratio: 0.01  # Sample 1% of health checks
          
          - operation: "auth.*"
            ratio: 1.0   # Sample 100% of auth operations
          
          - service: "critical-service"
            ratio: 1.0   # Sample all traces from this service
        
        # Rate limiting (traces per second)
        rate_limit: 100
See src/modules/observability/config.rs:142 for sampling configuration.

Production Setup

Full Observability Stack

docker-compose.yml:
services:
  iii:
    image: iiidev/iii:latest
    ports:
      - "3111:3111"
      - "49134:49134"
      - "9464:9464"
    environment:
      OTEL_EXPORTER_OTLP_ENDPOINT: http://tempo:4317
    volumes:
      - ./config.yaml:/app/config.yaml:ro
  
  # Traces: Grafana Tempo
  tempo:
    image: grafana/tempo:latest
    command: ["-config.file=/etc/tempo.yaml"]
    volumes:
      - ./tempo.yaml:/etc/tempo.yaml
      - tempo-data:/tmp/tempo
    ports:
      - "4317:4317"   # OTLP gRPC
      - "3200:3200"   # Tempo
  
  # Metrics: Prometheus
  prometheus:
    image: prom/prometheus:latest
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
  
  # Visualization: Grafana
  grafana:
    image: grafana/grafana:latest
    environment:
      GF_AUTH_ANONYMOUS_ENABLED: "true"
      GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin"
    volumes:
      - grafana-data:/var/lib/grafana
    ports:
      - "3000:3000"

volumes:
  tempo-data:
  prometheus-data:
  grafana-data:
prometheus.yml:
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'iii'
    static_configs:
      - targets: ['iii:9464']

Environment Variables

Override configuration via environment:
# Tracing
export OTEL_ENABLED=true
export OTEL_SERVICE_NAME=my-service
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_TRACES_SAMPLER_ARG=0.1

# Metrics
export OTEL_METRICS_ENABLED=true
export OTEL_METRICS_EXPORTER=otlp
export OTEL_METRICS_RETENTION_SECONDS=7200
export OTEL_METRICS_MAX_COUNT=50000

Best Practices

Sampling Strategy

  • Use lower sampling for high-traffic endpoints (health checks, static assets)
  • Use 100% sampling for critical operations (auth, payments)
  • Implement rate limiting to prevent trace storms
  • Monitor sampling effectiveness in production

Metric Cardinality

  • Limit unique label combinations to avoid cardinality explosion
  • Use metric aggregation for high-cardinality data
  • Set appropriate retention periods
  • Monitor memory usage for in-memory storage

Trace Context Propagation

  • Always propagate traceparent and baggage headers
  • Use baggage for cross-cutting concerns (user_id, request_id)
  • Avoid large baggage payloads (max ~8KB)

Performance

  • Use OTLP exporter for production (lower overhead than memory)
  • Batch metrics exports (default: 60s interval)
  • Configure appropriate buffer sizes
  • Monitor exporter queue depth

Security

  • Use TLS for OTLP endpoints in production
  • Sanitize sensitive data from traces/logs
  • Implement access controls for observability APIs
  • Rotate service credentials regularly

Troubleshooting

High Memory Usage

# Reduce in-memory retention
metrics_max_count: 5000
memory_max_spans: 500
logs_max_count: 5000

Missing Traces

  • Check sampling ratio (may be too low)
  • Verify OTLP endpoint connectivity
  • Check for trace export errors in logs

Prometheus Scrape Failures

# Verify metrics endpoint
curl http://localhost:9464/metrics

# Check Prometheus targets
curl http://localhost:9090/targets

High Cardinality

Metric cardinality limit reached, new metric names will be dropped.
Reduce label combinations or increase limit:
// In custom adapter
max_unique_names: 50000

References

  • OpenTelemetry implementation: src/modules/observability/otel.rs
  • Metrics implementation: src/modules/observability/metrics.rs
  • Sampling strategies: src/modules/observability/sampler.rs
  • Configuration: src/modules/observability/config.rs

Build docs developers (and LLMs) love