Skip to main content

Observability overview

Reqon provides comprehensive observability features for monitoring and debugging mission execution. The observability system includes:

  • Structured Logging - Context-rich logs with multiple output formats
  • Event System - Fine-grained events for every pipeline operation
  • OpenTelemetry Integration - Distributed tracing and OTLP export

Architecture​

┌─────────────────────────────────────────────────────────┐
│ Mission Execution │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Fetch │ │ Map │ │Validate │ │ Store │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └────────────┴────────────┴────────────┘ │
│ │ │
│ Event Emitter │
└─────────────────────────┬───────────────────────────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Console │ │JSON Lines│ │ OTLP │
│ Output │ │ Output │ │Exporter │
└─────────┘ └─────────┘ └─────────┘

Quick start​

Basic logging​

import { execute, createStructuredLogger } from 'reqon-dsl';

const logger = createStructuredLogger({
prefix: 'MyApp',
level: 'debug',
console: true
});

const result = await execute(source, {
logger
});

Event listeners​

createEmitter takes an execution ID and a mission name. Each handler receives an event whose data lives on event.payload:

import { execute, createEmitter } from 'reqon-dsl';

const emitter = createEmitter('my-run', 'SyncCustomers');

emitter.on('fetch.complete', (event) => {
console.log(`Fetched ${event.payload.path}: ${event.payload.recordCount} records`);
});

emitter.on('data.store', (event) => {
console.log(`Stored ${event.payload.itemCount} items to ${event.payload.storeName}`);
});

const result = await execute(source, {
eventEmitter: emitter
});

OpenTelemetry export​

createOTelListener takes an OTLP config and returns a handler you subscribe to the emitter, plus a flush:

import { execute, createEmitter, createOTelListener } from 'reqon-dsl';

const otel = createOTelListener({
endpoint: 'http://localhost:4318/v1/traces',
serviceName: 'reqon-sync'
});

const emitter = createEmitter('my-run', 'SyncCustomers');
emitter.onAll(otel.handler);

await execute(source, { eventEmitter: emitter });
await otel.flush();

Event types​

Reqon emits events for every significant operation:

CategoryEvents
Missionmission.start, mission.complete, mission.failed, mission.paused
Stagestage.start, stage.complete
Stepstep.start, step.complete
HTTPfetch.start, fetch.complete, fetch.retry, fetch.error, fetch.heartbeat
Datadata.transform, data.validate, data.store
Loopsloop.start, loop.iteration, loop.complete, loop.heartbeat
Matchmatch.attempt, match.result
Webhookwebhook.register, webhook.event, webhook.complete
Statecheckpoint.save, checkpoint.resume, sync.checkpoint
Resilienceratelimit.wait, ratelimit.resume, circuit.open, circuit.halfopen, circuit.close

Output formats​

Console output​

Human-readable logs for development:

[Reqon] INFO mission.start mission="SyncCustomers"
[Reqon] DEBUG fetch.start url="/customers" method="GET"
[Reqon] INFO fetch.complete url="/customers" status=200 duration=234ms
[Reqon] INFO data.store store="customers" count=50
[Reqon] INFO mission.complete mission="SyncCustomers" duration=1234ms

JSON lines​

Machine-readable logs for log aggregation:

{"level":"info","message":"mission.start","timestamp":"2025-01-20T10:00:00Z","context":{"mission":"SyncCustomers"}}
{"level":"debug","message":"fetch.start","timestamp":"2025-01-20T10:00:01Z","context":{"url":"/customers","method":"GET"}}
{"level":"info","message":"fetch.complete","timestamp":"2025-01-20T10:00:02Z","context":{"url":"/customers","status":200,"duration":234}}

OpenTelemetry​

Export spans to observability platforms:

  • Jaeger
  • Zipkin
  • Grafana Tempo
  • AWS X-Ray
  • Datadog
  • Honeycomb

Use cases​

Debugging pipelines​

const emitter = createEmitter('debug-run', 'SyncCustomers');

emitter.on('fetch.error', (event) => {
console.error(`Failed: ${event.payload.path}`, event.payload.error);
});

Performance monitoring​

const metrics = {
fetchCount: 0,
recordsFetched: 0,
errors: 0
};

emitter.on('fetch.complete', (event) => {
metrics.fetchCount++;
metrics.recordsFetched += event.payload.recordCount;
});

emitter.on('fetch.error', () => {
metrics.errors++;
});

Audit logging​

emitter.on('data.store', (event) => {
auditLog.write({
action: 'store',
store: event.payload.storeName,
count: event.payload.itemCount,
timestamp: new Date()
});
});

Configuration​

Log levels​

LevelDescription
debugDetailed debugging information
infoGeneral operational information
warnWarning conditions
errorError conditions

Set the log level and outputs when you create the logger, and configure the OTLP endpoint when you create the listener. Reqon doesn't read observability settings from environment variables.

Next steps​