Skip to main content

Observability matrix

Operating a Titan app means knowing what to grep for and what to alert on. This page lists — per module — the events emitted, notable log keys, and metric/health signals you can rely on.

All claims here are verified against module source. If a row is empty, the module is deliberately quiet at that layer.

At-a-glance

Official@omnitron-dev/titan-*

Maintained by the Omnitron team. Independent npm package.

ModuleEmits eventsNotable logsPushes metricsHealth indicator
titan-authJWT verify failures
titan-cacheL2 fallback / errorshit/miss/evict
titan-databaseslow query, retriesyes (via titan-health)
titan-discoverydiscovery:eventregister, heartbeat, dereg
titan-eventsproxydispatch errors
titan-healthindicator failurescheck msn/a (itself)
titan-lockfailure-tracker windows
titan-metricsflush errorsown counters
titan-notificationsnotification.sentsend + DLQper-channelyes
titan-pmmany (below)spawn / crash / restartprocess statsyes (via titan-health)
titan-ratelimitreject reasonsallow/deny
titan-redisreconnect / errorsyes (via titan-health)
titan-schedulerjob start / finishruns / failures
titan-telemetry-relayWAL eventsself-instrumented
Built-in@omnitron-dev/titan

Ships inside @omnitron-dev/titan. No additional install required.

ModuleEmits eventsNotable logsPushes metrics
configconfig:changedsource load order
logger(the logger itself)

Per-module reference

titan-pm — the most chatty module

Official@omnitron-dev/titan-pm

Maintained by the Omnitron team. Independent npm package.

Process manager is the loudest module by design — every supervised process / pool / worker raises events you can subscribe to.

EventArgsMeaning
process:spawnprocessInfoChild process started
process:readyprocessInfoChild responded to ready handshake
process:stopprocessInfoChild exited cleanly
process:crashprocessInfo, errorChild died unexpectedly
child:startednameSupervised child entry started
child:stoppednameSupervised child stopped
child:start-failedname, errorInitial start raised before ready
child:crashname, errorSupervised child crashed mid-run
child:restartname, countChild restarted; count = total restarts
pool:initialized{ size, class }Worker pool warmed up
pool:scaled{ from, to, class }Pool grew / shrank
pool:drained{ class }Pool finished draining queued work
pool:destroyed{ class }Pool released
pool:memory{ workerId, rssMB }Memory limit exceeded
worker:spawned{ workerId, class }Pool worker forked
worker:shutdown{ workerId, class }Pool worker reaped
worker:unhealthy{ workerId }Worker missed a ping
worker:unresponsive{ workerId }Worker still silent after retries
worker:replaced{ workerId }Unresponsive worker replaced
request:queued{ poolClass, queueSize }Pool saturated; work queued
circuitbreaker:openBreaker tripped
circuitbreaker:halfopenProbe window started
circuitbreaker:closeBreaker reset
escalatename, errorRestart limit exceeded; failure escalated upstream
shutdownSupervisor shutdown
exitinfoProcess exited
health:changeprocessId, IHealthStatusPer-process health flipped
health:criticalprocessId, IHealthStatusPer-process health became critical

Subscribe with the standard event emitter API:

pmService.on('process:crash', (info, error) => {
logger.error({ pid: info.id, error }, 'child crashed');
});

titan-notifications

Official@omnitron-dev/titan-notifications

Maintained by the Omnitron team. Independent npm package.

EventArgsMeaning
notification.sent{ id, channel, recipient }Delivery completed (per channel)

Failures route through the dead-letter queue (listDLQ(channel)), not through events.

Health: the module registers NotificationsHealthIndicator (NOTIFICATIONS_HEALTH) — automatically picked up by titan-health if both modules are loaded.

titan-discovery

Official@omnitron-dev/titan-discovery

Maintained by the Omnitron team. Independent npm package.

EventPayloadMeaning
discovery:event{ type, node, service?, ts }Node added / removed / updated

type is one of node.added, node.removed, node.updated.

Notable logs (all under the service's own logger namespace):

LevelPattern
infoNode 'X' registered, DiscoveryService started
infoInitiating graceful shutdown for node 'X'
warnHeartbeat attempt failed
errorAll N heartbeat attempts failed
errorFailed to publish discovery event
debugReceived discovery event, Cleaned up inactive nodes

titan-events

Official@omnitron-dev/titan-events

Maintained by the Omnitron team. Independent npm package.

titan-events is the event bus; it doesn't emit framework-level events of its own. Per-emitter introspection is available via EventHistoryService if enableHistory: true.

titan-scheduler

Official@omnitron-dev/titan-scheduler

Maintained by the Omnitron team. Independent npm package.

Doesn't expose a hot event stream — IJobListener is the extension point. Implement one to observe job execution:

class MyJobListener implements IJobListener {
jobStarted(ctx) { /* ... */ }
jobCompleted(ctx) { /* ... */ }
jobFailed(ctx, e) { /* ... */ }
jobMissed(ctx) { /* ... */ }
}

Register the class via SCHEDULER_LISTENERS_TOKEN.

titan-cache

Official@omnitron-dev/titan-cache

Maintained by the Omnitron team. Independent npm package.

Cache hit/miss/eviction metrics are exposed through the @Cached decorator metadata and the CacheService.getStats() API.

const stats = cache.getStats();
// { hits, misses, evictions, size, hitRatio }

No native event stream — wrap calls if you need per-key observability.

titan-lock

Official@omnitron-dev/titan-lock

Maintained by the Omnitron team. Independent npm package.

Uses the framework's FailureTracker primitive: instead of logging every failure, it collapses repeated failures of the same operation into windowed "X failing" warnings. This keeps logs quiet when Redis briefly hiccups.

LevelPattern
warn[DistributedLock] X started failing
debug[DistributedLock] X still failing
info[DistributedLock] X recovered

titan-database

Official@omnitron-dev/titan-database

Maintained by the Omnitron team. Independent npm package.

LevelPattern
warnSlow query (over the configured threshold)
warnTransient error retried (via withRetry)
errorPool exhaustion / connection lost
infoMigration applied

The module exposes DatabaseHealthIndicator for k8s probes.

titan-redis

Official@omnitron-dev/titan-redis

Maintained by the Omnitron team. Independent npm package.

Inherits ioredis's event model (connect, ready, error, close, reconnecting, end). The manager logs reconnect attempts and surfaces a RedisHealthIndicator via titan-health.

titan-auth

Official@omnitron-dev/titan-auth

Maintained by the Omnitron team. Independent npm package.

Quiet by design — token-verification details should not be logged at info level (PII/tokens). Failures log at warn with error.code populated; successful verifications are silent.

titan-ratelimit

Official@omnitron-dev/titan-ratelimit

Maintained by the Omnitron team. Independent npm package.

Statistics are pull-based:

const stats = rate.getStats();
// { totalChecks, totalAllowed, totalDenied, deniedByTier, ... }

Denied requests are not logged automatically (volume would be high) — count them via metrics.recordTyped('counter', ...) from the caller if you need to.

titan-metrics

Official@omnitron-dev/titan-metrics

Maintained by the Omnitron team. Independent npm package.

Self-instruments three internal counters:

MetricType
titan_metrics_flush_totalcounter
titan_metrics_flush_errors_totalcounter
titan_metrics_buffer_sizegauge

Plus the system collectors collection: { process: true, system: true } populate: process_cpu, process_rss, process_heap_used, process_event_loop_lag_ms, system_load_avg, system_memory_free.

titan-telemetry-relay

Official@omnitron-dev/titan-telemetry-relay

Maintained by the Omnitron team. Independent npm package.

Self-instrumented via its internal relayLog() / relayMetric() calls. Exposes WAL queue depth, last-flush timestamp, transport errors. Surface through the metrics aggregator at the leader node.

titan-health

Official@omnitron-dev/titan-health

Maintained by the Omnitron team. Independent npm package.

LevelPattern
errorIndicator threw during check
warnIndicator returned degraded
debugProbe cache hit / refresh

Records its own check latency as a histogram when titan-metrics is loaded.

Built-in modules

config

Built-in@omnitron-dev/titan/module/config

Ships inside @omnitron-dev/titan. No additional install required.

EventPayloadMeaning
config:changed{ path, oldValue, newValue, source }Hot-reload detected a change at a path

Notable logs (info level):

  • Loaded N sources in M ms
  • Validation passed against AppConfigSchema
  • Source X changed; reloading

logger

Built-in@omnitron-dev/titan/module/logger

Ships inside @omnitron-dev/titan. No additional install required.

The logger doesn't log about itself except at fatal failures (e.g., transport open failed at boot). Use createNullLogger() in tests when you want absolute silence.

Cross-cutting recommendations

Subscribe instead of poll

The pm/discovery event streams are hot — subscribing is cheaper and more responsive than polling state. For per-process autoscaling or alerting, hook the events:

pm.on('pool:memory', handleMemorySpike);
pm.on('worker:unresponsive', handleWorkerHang);
pm.on('circuitbreaker:open', notifyOncall);

Tie metrics to events

For dashboards, route key events through titan-metrics:

pm.on('process:crash', (info, error) => {
metrics.recordTyped('counter', 'pm.process.crash.total',
{ class: info.processName }, 1);
});

Alert thresholds — common starting points

SignalSuggested alert
process_event_loop_lag_ms p95> 100 ms for 2 min
process_rss growth rate> +50 MB/min sustained
pool:scaled to/from limitrepeated within 5 min
worker:replaced count> 3 in 5 min for same pool
circuitbreaker:openany open lasting > 30 s
notification.sent failure ratio> 1 % over 10 min
titan_metrics_flush_errors_total> 0 in last minute
Health degraded/unhealthysustained > 1 probe window

Don't log per-call by default

Several modules (titan-ratelimit, titan-cache, titan-auth) intentionally stay quiet at info level. Per-call logging at request rate is a recipe for disk/SIEM saturation. Use counters and sampled debug logging instead.

See also