dspx 0.1.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/.github/workflows/ci.yml +185 -0
  2. package/.vscode/c_cpp_properties.json +17 -0
  3. package/.vscode/settings.json +68 -0
  4. package/.vscode/tasks.json +28 -0
  5. package/DISCLAIMER.md +32 -0
  6. package/LICENSE +21 -0
  7. package/README.md +1803 -0
  8. package/ROADMAP.md +192 -0
  9. package/TECHNICAL_DEBT.md +165 -0
  10. package/binding.gyp +65 -0
  11. package/docs/ADVANCED_LOGGER_FEATURES.md +598 -0
  12. package/docs/AUTHENTICATION_SECURITY.md +396 -0
  13. package/docs/BACKEND_IMPROVEMENTS.md +399 -0
  14. package/docs/CHEBYSHEV_BIQUAD_EQ_IMPLEMENTATION.md +405 -0
  15. package/docs/FFT_IMPLEMENTATION.md +490 -0
  16. package/docs/FFT_IMPROVEMENTS_SUMMARY.md +387 -0
  17. package/docs/FFT_USER_GUIDE.md +494 -0
  18. package/docs/FILTERS_IMPLEMENTATION.md +260 -0
  19. package/docs/FILTER_API_GUIDE.md +418 -0
  20. package/docs/FIR_SIMD_OPTIMIZATION.md +175 -0
  21. package/docs/LOGGER_API_REFERENCE.md +350 -0
  22. package/docs/NOTCH_FILTER_QUICK_REF.md +121 -0
  23. package/docs/PHASE2_TESTS_AND_NOTCH_FILTER.md +341 -0
  24. package/docs/PHASES_5_7_SUMMARY.md +403 -0
  25. package/docs/PIPELINE_FILTER_INTEGRATION.md +446 -0
  26. package/docs/SIMD_OPTIMIZATIONS.md +211 -0
  27. package/docs/TEST_MIGRATION_SUMMARY.md +173 -0
  28. package/docs/TIMESERIES_IMPLEMENTATION_SUMMARY.md +322 -0
  29. package/docs/TIMESERIES_QUICK_REF.md +85 -0
  30. package/docs/advanced.md +559 -0
  31. package/docs/time-series-guide.md +617 -0
  32. package/docs/time-series-migration.md +376 -0
  33. package/jest.config.js +37 -0
  34. package/package.json +42 -0
  35. package/prebuilds/linux-x64/dsp-ts-redis.node +0 -0
  36. package/prebuilds/win32-x64/dsp-ts-redis.node +0 -0
  37. package/scripts/test.js +24 -0
  38. package/src/build/dsp-ts-redis.node +0 -0
  39. package/src/native/DspPipeline.cc +675 -0
  40. package/src/native/DspPipeline.h +44 -0
  41. package/src/native/FftBindings.cc +817 -0
  42. package/src/native/FilterBindings.cc +1001 -0
  43. package/src/native/IDspStage.h +53 -0
  44. package/src/native/adapters/InterpolatorStage.h +201 -0
  45. package/src/native/adapters/MeanAbsoluteValueStage.h +289 -0
  46. package/src/native/adapters/MovingAverageStage.h +306 -0
  47. package/src/native/adapters/RectifyStage.h +88 -0
  48. package/src/native/adapters/ResamplerStage.h +238 -0
  49. package/src/native/adapters/RmsStage.h +299 -0
  50. package/src/native/adapters/SscStage.h +121 -0
  51. package/src/native/adapters/VarianceStage.h +307 -0
  52. package/src/native/adapters/WampStage.h +114 -0
  53. package/src/native/adapters/WaveformLengthStage.h +115 -0
  54. package/src/native/adapters/ZScoreNormalizeStage.h +326 -0
  55. package/src/native/core/FftEngine.cc +441 -0
  56. package/src/native/core/FftEngine.h +224 -0
  57. package/src/native/core/FirFilter.cc +324 -0
  58. package/src/native/core/FirFilter.h +149 -0
  59. package/src/native/core/IirFilter.cc +576 -0
  60. package/src/native/core/IirFilter.h +210 -0
  61. package/src/native/core/MovingAbsoluteValueFilter.cc +17 -0
  62. package/src/native/core/MovingAbsoluteValueFilter.h +135 -0
  63. package/src/native/core/MovingAverageFilter.cc +18 -0
  64. package/src/native/core/MovingAverageFilter.h +135 -0
  65. package/src/native/core/MovingFftFilter.cc +291 -0
  66. package/src/native/core/MovingFftFilter.h +203 -0
  67. package/src/native/core/MovingVarianceFilter.cc +194 -0
  68. package/src/native/core/MovingVarianceFilter.h +114 -0
  69. package/src/native/core/MovingZScoreFilter.cc +215 -0
  70. package/src/native/core/MovingZScoreFilter.h +113 -0
  71. package/src/native/core/Policies.h +352 -0
  72. package/src/native/core/RmsFilter.cc +18 -0
  73. package/src/native/core/RmsFilter.h +131 -0
  74. package/src/native/core/SscFilter.cc +16 -0
  75. package/src/native/core/SscFilter.h +137 -0
  76. package/src/native/core/WampFilter.cc +16 -0
  77. package/src/native/core/WampFilter.h +101 -0
  78. package/src/native/core/WaveformLengthFilter.cc +17 -0
  79. package/src/native/core/WaveformLengthFilter.h +98 -0
  80. package/src/native/utils/CircularBufferArray.cc +336 -0
  81. package/src/native/utils/CircularBufferArray.h +62 -0
  82. package/src/native/utils/CircularBufferVector.cc +145 -0
  83. package/src/native/utils/CircularBufferVector.h +45 -0
  84. package/src/native/utils/NapiUtils.cc +53 -0
  85. package/src/native/utils/NapiUtils.h +21 -0
  86. package/src/native/utils/SimdOps.h +870 -0
  87. package/src/native/utils/SlidingWindowFilter.cc +239 -0
  88. package/src/native/utils/SlidingWindowFilter.h +159 -0
  89. package/src/native/utils/TimeSeriesBuffer.cc +205 -0
  90. package/src/native/utils/TimeSeriesBuffer.h +140 -0
  91. package/src/ts/CircularLogBuffer.ts +87 -0
  92. package/src/ts/DriftDetector.ts +331 -0
  93. package/src/ts/TopicRouter.ts +428 -0
  94. package/src/ts/__tests__/AdvancedDsp.test.ts +585 -0
  95. package/src/ts/__tests__/AuthAndEdgeCases.test.ts +241 -0
  96. package/src/ts/__tests__/Chaining.test.ts +387 -0
  97. package/src/ts/__tests__/ChebyshevBiquad.test.ts +229 -0
  98. package/src/ts/__tests__/CircularLogBuffer.test.ts +158 -0
  99. package/src/ts/__tests__/DriftDetector.test.ts +389 -0
  100. package/src/ts/__tests__/Fft.test.ts +484 -0
  101. package/src/ts/__tests__/ListState.test.ts +153 -0
  102. package/src/ts/__tests__/Logger.test.ts +208 -0
  103. package/src/ts/__tests__/LoggerAdvanced.test.ts +319 -0
  104. package/src/ts/__tests__/LoggerMinor.test.ts +247 -0
  105. package/src/ts/__tests__/MeanAbsoluteValue.test.ts +398 -0
  106. package/src/ts/__tests__/MovingAverage.test.ts +322 -0
  107. package/src/ts/__tests__/RMS.test.ts +315 -0
  108. package/src/ts/__tests__/Rectify.test.ts +272 -0
  109. package/src/ts/__tests__/Redis.test.ts +456 -0
  110. package/src/ts/__tests__/SlopeSignChange.test.ts +166 -0
  111. package/src/ts/__tests__/Tap.test.ts +164 -0
  112. package/src/ts/__tests__/TimeBasedExpiration.test.ts +124 -0
  113. package/src/ts/__tests__/TimeBasedRmsAndMav.test.ts +231 -0
  114. package/src/ts/__tests__/TimeBasedVarianceAndZScore.test.ts +284 -0
  115. package/src/ts/__tests__/TimeSeries.test.ts +254 -0
  116. package/src/ts/__tests__/TopicRouter.test.ts +332 -0
  117. package/src/ts/__tests__/TopicRouterAdvanced.test.ts +483 -0
  118. package/src/ts/__tests__/TopicRouterPriority.test.ts +487 -0
  119. package/src/ts/__tests__/Variance.test.ts +509 -0
  120. package/src/ts/__tests__/WaveformLength.test.ts +147 -0
  121. package/src/ts/__tests__/WillisonAmplitude.test.ts +197 -0
  122. package/src/ts/__tests__/ZScoreNormalize.test.ts +459 -0
  123. package/src/ts/advanced-dsp.ts +566 -0
  124. package/src/ts/backends.ts +1137 -0
  125. package/src/ts/bindings.ts +1225 -0
  126. package/src/ts/easter-egg.ts +42 -0
  127. package/src/ts/examples/MeanAbsoluteValue/test-state.ts +99 -0
  128. package/src/ts/examples/MeanAbsoluteValue/test-streaming.ts +269 -0
  129. package/src/ts/examples/MovingAverage/test-state.ts +85 -0
  130. package/src/ts/examples/MovingAverage/test-streaming.ts +188 -0
  131. package/src/ts/examples/RMS/test-state.ts +97 -0
  132. package/src/ts/examples/RMS/test-streaming.ts +253 -0
  133. package/src/ts/examples/Rectify/test-state.ts +107 -0
  134. package/src/ts/examples/Rectify/test-streaming.ts +242 -0
  135. package/src/ts/examples/Variance/test-state.ts +195 -0
  136. package/src/ts/examples/Variance/test-streaming.ts +260 -0
  137. package/src/ts/examples/ZScoreNormalize/test-state.ts +277 -0
  138. package/src/ts/examples/ZScoreNormalize/test-streaming.ts +306 -0
  139. package/src/ts/examples/advanced-dsp-examples.ts +397 -0
  140. package/src/ts/examples/callbacks/advanced-router-features.ts +326 -0
  141. package/src/ts/examples/callbacks/benchmark-circular-buffer.ts +109 -0
  142. package/src/ts/examples/callbacks/monitoring-example.ts +265 -0
  143. package/src/ts/examples/callbacks/pipeline-callbacks-example.ts +137 -0
  144. package/src/ts/examples/callbacks/pooled-callbacks-example.ts +274 -0
  145. package/src/ts/examples/callbacks/priority-routing-example.ts +277 -0
  146. package/src/ts/examples/callbacks/production-topic-router.ts +214 -0
  147. package/src/ts/examples/callbacks/topic-based-logging.ts +161 -0
  148. package/src/ts/examples/chaining/test-chaining-redis.ts +113 -0
  149. package/src/ts/examples/chaining/test-chaining.ts +52 -0
  150. package/src/ts/examples/emg-features-example.ts +284 -0
  151. package/src/ts/examples/fft-example.ts +309 -0
  152. package/src/ts/examples/fft-examples.ts +349 -0
  153. package/src/ts/examples/filter-examples.ts +320 -0
  154. package/src/ts/examples/list-state-example.ts +131 -0
  155. package/src/ts/examples/logger-example.ts +91 -0
  156. package/src/ts/examples/notch-filter-examples.ts +243 -0
  157. package/src/ts/examples/phase5/drift-detection-example.ts +290 -0
  158. package/src/ts/examples/phase6-7/production-observability.ts +476 -0
  159. package/src/ts/examples/phase6-7/redis-timeseries-integration.ts +446 -0
  160. package/src/ts/examples/redis/redis-example.ts +202 -0
  161. package/src/ts/examples/redis-example.ts +202 -0
  162. package/src/ts/examples/simd-benchmark.ts +126 -0
  163. package/src/ts/examples/tap-debugging.ts +230 -0
  164. package/src/ts/examples/timeseries/comparison-example.ts +290 -0
  165. package/src/ts/examples/timeseries/iot-sensor-example.ts +143 -0
  166. package/src/ts/examples/timeseries/redis-streaming-example.ts +233 -0
  167. package/src/ts/examples/waveform-length-example.ts +139 -0
  168. package/src/ts/fft.ts +722 -0
  169. package/src/ts/filters.ts +1078 -0
  170. package/src/ts/index.ts +120 -0
  171. package/src/ts/types.ts +589 -0
  172. package/tsconfig.json +15 -0
@@ -0,0 +1,559 @@
1
+ # Advanced Features
2
+
3
+ This document covers advanced observability, monitoring, and debugging features for production deployments.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Pipeline Callbacks (Monitoring & Observability)](#pipeline-callbacks-monitoring--observability)
10
+ - [Topic-Based Logging (Kafka-Style Filtering)](#topic-based-logging-kafka-style-filtering)
11
+ - [Topic Router (Fan-Out to Multiple Backends)](#topic-router-fan-out-to-multiple-backends)
12
+ - [Priority-Based Routing (10-Level System)](#priority-based-routing-10-level-system)
13
+ - [Debugging with `.tap()`](#debugging-with-tap)
14
+
15
+ ---
16
+
17
+ ## Pipeline Callbacks (Monitoring & Observability)
18
+
19
+ Configure callbacks for monitoring, alerting, and observability. The library supports both **individual** and **pooled/batched** callbacks:
20
+
21
+ ### Basic Usage
22
+
23
+ ```typescript
24
+ import { createDspPipeline } from "dspx";
25
+ import type { PipelineCallbacks } from "dspx";
26
+
27
+ const callbacks: PipelineCallbacks = {
28
+ // Monitor individual samples (use sparingly - can impact performance)
29
+ onSample: (value, index, stage) => {
30
+ if (value > THRESHOLD) {
31
+ triggerAlert(index, stage);
32
+ }
33
+ },
34
+
35
+ // Track performance metrics
36
+ onStageComplete: (stage, durationMs) => {
37
+ metrics.record(`dsp.${stage}.duration`, durationMs);
38
+ },
39
+
40
+ // Handle errors gracefully
41
+ onError: (stage, error) => {
42
+ logger.error(`Stage ${stage} failed`, error);
43
+ },
44
+
45
+ // Structured logging (called immediately for each log)
46
+ onLog: (level, msg, context) => {
47
+ if (level === "debug") return; // Filter debug logs
48
+ console.log(`[${level}] ${msg}`, context);
49
+ },
50
+ };
51
+
52
+ // Configure callbacks before adding filters
53
+ const pipeline = createDspPipeline()
54
+ .pipeline(callbacks)
55
+ .MovingAverage({ windowSize: 10 })
56
+ .Rectify()
57
+ .Rms({ windowSize: 5 });
58
+ ```
59
+
60
+ ### Pooled/Batched Callbacks (Better Performance)
61
+
62
+ For high-throughput scenarios, use **pooled callbacks** to reduce overhead:
63
+
64
+ ```typescript
65
+ const callbacks: PipelineCallbacks = {
66
+ // Process samples in batches (more efficient than onSample)
67
+ onBatch: (batch) => {
68
+ console.log(`Stage: ${batch.stage}`);
69
+ console.log(`Samples: ${batch.count}`);
70
+
71
+ // Process entire batch efficiently (SIMD-friendly)
72
+ for (let i = 0; i < batch.samples.length; i++) {
73
+ if (batch.samples[i] > THRESHOLD) {
74
+ triggerAlert(batch.startIndex + i, batch.stage);
75
+ }
76
+ }
77
+ },
78
+
79
+ // Receive all logs at once (pooled during processing)
80
+ onLogBatch: (logs) => {
81
+ // Send all logs to external system in one request
82
+ await loggingService.sendBatch(
83
+ logs.map((log) => ({
84
+ level: log.level,
85
+ message: log.message,
86
+ timestamp: log.timestamp,
87
+ ...log.context,
88
+ }))
89
+ );
90
+ },
91
+
92
+ onStageComplete: (stage, durationMs) => {
93
+ metrics.record(`dsp.${stage}.duration`, durationMs);
94
+ },
95
+ };
96
+ ```
97
+
98
+ ### Callback Comparison
99
+
100
+ | Callback Type | Best For | Throughput | Production Safety |
101
+ | ----------------- | ------------------------------------------------------------- | ---------------- | --------------------------------------- |
102
+ | `onSample` | Peak detection, threshold alerts, individual value monitoring | ~6M samples/sec | ⚠️ **RISKY** - Blocks event loop |
103
+ | `onBatch` | Batch aggregation, efficient sample processing | ~23M samples/sec | ✅ **SAFE** - Non-blocking |
104
+ | `onLog` | Real-time logging, immediate output | Variable | ⚠️ **RISKY** - Synchronous I/O per call |
105
+ | `onLogBatch` | External logging services, log aggregation | ~3M samples/sec | ✅ **SAFE** - Batched, non-blocking |
106
+ | `onStageComplete` | Performance metrics, timing | ✅ Minimal | ✅ **SAFE** - 1 call per process |
107
+ | `onError` | Error handling | ✅ Minimal | ✅ **SAFE** - Only on error |
108
+
109
+ ### Critical Performance & Safety Notes
110
+
111
+ - **🚨 Individual callbacks (`onSample`, `onLog`) are fast but dangerous**:
112
+
113
+ - Higher raw throughput in microbenchmarks (~6M samples/sec)
114
+ - **Block the Node.js event loop** with millions of synchronous function calls
115
+ - Synchronous I/O operations in callbacks can stall entire pipeline
116
+ - Unpredictable GC pressure from per-call allocations
117
+ - **NOT recommended for production servers**
118
+
119
+ - **✅ Pooled callbacks (`onBatch`, `onLogBatch`) are production-safe**:
120
+
121
+ - Stable, predictable throughput (~3M samples/sec sustained)
122
+ - **Non-blocking**: Batched operations prevent event loop starvation
123
+ - **Backpressure-friendly**: Aligns with real-world telemetry systems (Kafka, Loki, Prometheus)
124
+ - Fixed memory footprint via circular buffer (no unbounded growth)
125
+ - **Recommended for high-throughput production environments**
126
+
127
+ - **Architecture trade-off**:
128
+
129
+ - Individual mode: 2x faster in synthetic benchmarks, but impractical for live servers
130
+ - Pooled mode: Slight raw speed reduction, but guarantees non-blocking safety
131
+ - **Industry standard**: Pooled/batched callbacks match production observability patterns (Kafka producers, OpenTelemetry exporters, Loki agents)
132
+
133
+ - **Circular buffer implementation**:
134
+ - Fixed capacity: 32 log entries (typical: 2-3 logs per process call)
135
+ - Zero reallocations after initialization
136
+ - Cache-friendly memory access pattern
137
+ - Graceful overflow: Overwrites oldest entries (prevents memory leaks)
138
+
139
+ See `src/ts/examples/callbacks/` for complete examples including performance comparisons.
140
+
141
+ ---
142
+
143
+ ## Topic-Based Logging (Kafka-Style Filtering)
144
+
145
+ Filter logs using **Kafka-style hierarchical topics** for efficient, selective subscription:
146
+
147
+ ### Topic Structure
148
+
149
+ ```
150
+ pipeline.debug # General debug logs
151
+ pipeline.info # General info logs
152
+ pipeline.warn # General warnings
153
+ pipeline.error # General errors
154
+ pipeline.stage.<stageName>.<category> # Stage-specific logs
155
+ ├── samples # Sample-level data
156
+ ├── performance # Timing/metrics
157
+ └── error # Stage errors
158
+ ```
159
+
160
+ ### Basic Topic Filtering
161
+
162
+ ```typescript
163
+ const pipeline = createDspPipeline();
164
+
165
+ // Subscribe to ALL logs (no filter)
166
+ pipeline.pipeline({
167
+ onLogBatch: (logs) => {
168
+ logs.forEach((log) => {
169
+ console.log(`[${log.topic}] ${log.level}: ${log.message}`);
170
+ // [pipeline.debug] debug: Starting pipeline processing
171
+ // [pipeline.stage.rms.performance] info: RMS processing complete
172
+ });
173
+ },
174
+ });
175
+
176
+ // Filter by stage (only RMS logs)
177
+ pipeline.pipeline({
178
+ onLogBatch: (logs) => {
179
+ logs.forEach((log) => console.log(log.message));
180
+ },
181
+ topicFilter: "pipeline.stage.rms.*", // Only RMS stage logs
182
+ });
183
+
184
+ // Filter by category (only errors)
185
+ pipeline.pipeline({
186
+ onLogBatch: (logs) => {
187
+ if (logs.length > 0) {
188
+ alertService.notify("Pipeline errors detected", logs);
189
+ }
190
+ },
191
+ topicFilter: "pipeline.*.error", // All errors from any stage
192
+ });
193
+
194
+ // Multiple filters (errors + performance)
195
+ pipeline.pipeline({
196
+ onLogBatch: (logs) => {
197
+ logs.forEach((log) => {
198
+ if (log.topic.includes("error")) {
199
+ errorAlerts.push(log);
200
+ } else {
201
+ metrics.push(log);
202
+ }
203
+ });
204
+ },
205
+ topicFilter: [
206
+ "pipeline.*.error", // All errors
207
+ "pipeline.*.performance", // All performance metrics
208
+ ],
209
+ });
210
+ ```
211
+
212
+ ### Topic-Based Routing (Production Pattern)
213
+
214
+ ```typescript
215
+ const pipeline = createDspPipeline();
216
+
217
+ pipeline.pipeline({
218
+ onLogBatch: (logs) => {
219
+ // Route logs to different backends based on topic
220
+ logs.forEach((log) => {
221
+ if (log.topic.includes("error")) {
222
+ // Send errors to alerting system (PagerDuty, Slack, etc.)
223
+ await alerting.send(log);
224
+ } else if (
225
+ log.topic.includes("performance") ||
226
+ log.topic.includes("samples")
227
+ ) {
228
+ // Send metrics to monitoring (Prometheus, Datadog, etc.)
229
+ await metrics.record(log.topic, log.context);
230
+ } else {
231
+ // Send debug logs to centralized logging (Loki, Elasticsearch, etc.)
232
+ await logging.send(log);
233
+ }
234
+ });
235
+ },
236
+ });
237
+ ```
238
+
239
+ ### Topic Filter Patterns
240
+
241
+ | Pattern | Matches |
242
+ | ---------------------------------------------- | ----------------------------------------- |
243
+ | `pipeline.stage.*` | All logs from any stage |
244
+ | `pipeline.stage.rms.*` | Only RMS stage logs |
245
+ | `pipeline.*.error` | All errors (any stage) |
246
+ | `pipeline.*.performance` | All performance metrics |
247
+ | `['pipeline.error', 'pipeline.stage.*.error']` | Multiple patterns (errors from any stage) |
248
+
249
+ ### Production Benefits
250
+
251
+ - ✅ **Selective subscription** - Filter at source, reduce processing overhead
252
+ - ✅ **Topic-based routing** - Different topics → different backends (Kafka, Loki, Prometheus)
253
+ - ✅ **Industry alignment** - Matches telemetry standards (Kafka topics, NATS subjects, MQTT topics)
254
+ - ✅ **Efficient filtering** - Wildcard patterns processed before callback invocation
255
+
256
+ See `src/ts/examples/callbacks/topic-based-logging.ts` for comprehensive examples.
257
+
258
+ ---
259
+
260
+ ## Topic Router (Fan-Out to Multiple Backends)
261
+
262
+ The `TopicRouter` provides **production-grade fan-out routing** to multiple observability backends, matching patterns used by Grafana Loki, OpenTelemetry, and FluentBit:
263
+
264
+ ### Builder Pattern (Recommended)
265
+
266
+ ```typescript
267
+ import { createDspPipeline, createTopicRouter } from "dspx";
268
+
269
+ const router = createTopicRouter()
270
+ // Critical errors → PagerDuty
271
+ .errors(async (log) => {
272
+ await pagerDuty.alert(log);
273
+ })
274
+
275
+ // Performance metrics → Prometheus
276
+ .performance(async (log) => {
277
+ await prometheus.record(log.topic, log.context);
278
+ })
279
+
280
+ // Debug logs → Loki
281
+ .debug(async (log) => {
282
+ await loki.send(log);
283
+ })
284
+
285
+ // Everything else → CloudWatch (backup)
286
+ .default(async (log) => {
287
+ await cloudwatch.send(log);
288
+ })
289
+ .build();
290
+
291
+ const pipeline = createDspPipeline();
292
+ pipeline
293
+ .pipeline({
294
+ onLogBatch: (logs) => router.routeBatch(logs),
295
+ })
296
+ .MovingAverage({ windowSize: 10 })
297
+ .Rms({ windowSize: 5 });
298
+ ```
299
+
300
+ ### Custom Route Patterns
301
+
302
+ ```typescript
303
+ const router = createTopicRouter()
304
+ .custom(/^pipeline\.error/, pagerDuty.alert, "error-alerts")
305
+ .custom(/^pipeline\.stage\.rms/, prometheusHandler, "rms-metrics")
306
+ .custom(/^pipeline\.performance/, prometheusHandler, "performance")
307
+ .custom(/.*/, loki.send, "default-logs")
308
+ .build();
309
+ ```
310
+
311
+ ### Multi-Backend Fan-Out
312
+
313
+ ```typescript
314
+ // Route errors to BOTH PagerDuty AND CloudWatch
315
+ const router = createTopicRouter()
316
+ .errors(async (log) => {
317
+ await Promise.all([
318
+ pagerDuty.alert(log),
319
+ cloudwatch.send(log), // Backup for audit
320
+ ]);
321
+ })
322
+ .build();
323
+ ```
324
+
325
+ ### Stage-Specific Routing
326
+
327
+ ```typescript
328
+ const router = createTopicRouter()
329
+ .stage("rms", async (log) => {
330
+ // Only RMS stage logs
331
+ await prometheus.record(log.topic, log.context);
332
+ })
333
+ .stage("movingAverage", async (log) => {
334
+ // Only MovingAverage stage logs
335
+ await loki.send(log);
336
+ })
337
+ .build();
338
+ ```
339
+
340
+ ### Router API
341
+
342
+ | Method | Purpose | Example |
343
+ | ---------------- | ---------------------------------------------- | ---------------------------- |
344
+ | `.errors()` | Route errors to alerting (PagerDuty, Slack) | Critical alerts |
345
+ | `.performance()` | Route metrics to monitoring (Prometheus, DD) | Timing, throughput |
346
+ | `.debug()` | Route debug logs to centralized logging (Loki) | Development traces |
347
+ | `.alerts()` | Route threshold crossings to alerting | Anomaly detection |
348
+ | `.stage(name)` | Route stage-specific logs | Per-filter monitoring |
349
+ | `.custom(regex)` | Route with custom pattern | Organization-specific topics |
350
+ | `.default()` | Catch-all route (add last) | Backup logging |
351
+
352
+ ### Production Benefits
353
+
354
+ - ✅ **Parallel routing**: All backends called concurrently (`Promise.all`)
355
+ - ✅ **Non-blocking**: Async handlers prevent DSP throughput impact
356
+ - ✅ **Error isolation**: Failed backend doesn't break pipeline
357
+ - ✅ **Type-safe**: Full TypeScript support with RouteHandler type
358
+ - ✅ **Extensible**: Add routes without modifying pipeline code
359
+ - ✅ **Industry standard**: Matches Loki, OTEL, FluentBit, Vector.dev patterns
360
+
361
+ See `src/ts/examples/callbacks/production-topic-router.ts` for comprehensive examples.
362
+
363
+ ---
364
+
365
+ ## Priority-Based Routing (10-Level System)
366
+
367
+ The library supports a **10-level priority system** for fine-grained log filtering and routing. Each log can be assigned a priority from 1 (lowest) to 10 (highest), with default priorities automatically assigned based on log level.
368
+
369
+ ### Default Priority Mapping
370
+
371
+ | Log Level | Priority | Use Case |
372
+ | --------- | -------- | -------------------------- |
373
+ | `debug` | 2 | Development traces |
374
+ | `info` | 5 | General information |
375
+ | `warn` | 7 | Warnings, potential issues |
376
+ | `error` | 9 | Critical errors, failures |
377
+
378
+ Logs without an explicit priority default to **priority 1**.
379
+
380
+ ### Basic Priority Filtering
381
+
382
+ ```typescript
383
+ import { createDspPipeline, createTopicRouter } from "dspx";
384
+ import type { LogPriority } from "dspx";
385
+
386
+ // Route only high-priority logs (priority >= 7) to alerting
387
+ const router = createTopicRouter()
388
+ .errors(pagerDuty.alert, {
389
+ minPriority: 7, // Only warnings (7) and errors (9)
390
+ })
391
+ .performance(prometheus.record, {
392
+ minPriority: 5, // Info (5) and above
393
+ maxPriority: 7, // Exclude critical errors
394
+ })
395
+ .build();
396
+
397
+ const pipeline = createDspPipeline();
398
+ pipeline
399
+ .pipeline({
400
+ onLogBatch: (logs) => router.routeBatch(logs),
401
+ })
402
+ .MovingAverage({ windowSize: 10 })
403
+ .Rms({ windowSize: 5 });
404
+ ```
405
+
406
+ ### Custom Priority Assignment
407
+
408
+ ```typescript
409
+ import type { LogEntry, LogPriority } from "dspx";
410
+
411
+ // Assign custom priorities in your backend handlers
412
+ const router = createTopicRouter()
413
+ .custom(/^pipeline\.stage\.rms/, async (log: LogEntry) => {
414
+ // Override priority based on context
415
+ const priority: LogPriority = log.context?.rmsValue > 100 ? 10 : 5;
416
+
417
+ await monitoring.send({
418
+ ...log,
419
+ priority,
420
+ customField: "rms-analysis",
421
+ });
422
+ })
423
+ .build();
424
+ ```
425
+
426
+ ### Multi-Tier Routing by Priority
427
+
428
+ ```typescript
429
+ // Route logs to different backends based on priority tiers
430
+ const router = createTopicRouter()
431
+ // Critical (9-10): Immediate alerting
432
+ .custom(/.*/, pagerDuty.alert, "critical-alerts", {
433
+ minPriority: 9,
434
+ })
435
+
436
+ // High (7-8): Slack notifications
437
+ .custom(/.*/, slack.notify, "high-priority", {
438
+ minPriority: 7,
439
+ maxPriority: 8,
440
+ })
441
+
442
+ // Medium (4-6): Centralized logging
443
+ .custom(/.*/, loki.send, "medium-priority", {
444
+ minPriority: 4,
445
+ maxPriority: 6,
446
+ })
447
+
448
+ // Low (1-3): Debug logs only
449
+ .custom(/.*/, debugLogger.write, "low-priority", {
450
+ maxPriority: 3,
451
+ })
452
+ .build();
453
+ ```
454
+
455
+ ### Priority with Metrics Tracking
456
+
457
+ ```typescript
458
+ const router = createTopicRouter()
459
+ .errors(async (log: LogEntry) => {
460
+ // Track priority distribution
461
+ metrics.increment("logs.priority", {
462
+ level: log.level,
463
+ priority: log.priority ?? 1,
464
+ });
465
+
466
+ // Only alert on high-priority errors
467
+ if ((log.priority ?? 1) >= 8) {
468
+ await pagerDuty.alert(log);
469
+ }
470
+ })
471
+ .build();
472
+ ```
473
+
474
+ ### Dynamic Priority Assignment
475
+
476
+ ```typescript
477
+ const router = createTopicRouter()
478
+ .custom(/^pipeline\.performance/, async (log: LogEntry) => {
479
+ // Calculate priority based on performance metrics
480
+ const duration = log.context?.durationMs || 0;
481
+ const priority: LogPriority =
482
+ duration > 1000
483
+ ? 10 // Critical slowdown
484
+ : duration > 500
485
+ ? 8 // High latency
486
+ : duration > 100
487
+ ? 5 // Normal
488
+ : 2; // Fast
489
+
490
+ await monitoring.send({
491
+ ...log,
492
+ priority,
493
+ severity: priority >= 8 ? "high" : "normal",
494
+ });
495
+ })
496
+ .build();
497
+ ```
498
+
499
+ ### Priority Filtering Options
500
+
501
+ | Option | Type | Description |
502
+ | ------------- | ------------- | -------------------------------- |
503
+ | `minPriority` | `LogPriority` | Minimum priority to route (1-10) |
504
+ | `maxPriority` | `LogPriority` | Maximum priority to route (1-10) |
505
+
506
+ ### Production Benefits
507
+
508
+ - **Fine-grained control**: 10 priority levels for precise filtering
509
+ - **Default mapping**: Automatic priority assignment based on log level
510
+ - **Cost optimization**: Route low-priority logs to cheaper storage
511
+ - **Alert fatigue reduction**: Only high-priority logs trigger pages
512
+ - **Flexible thresholds**: Adjust priority cutoffs without code changes
513
+ - **Type-safe**: `LogPriority` type enforces valid values (1-10)
514
+
515
+ See `src/ts/examples/callbacks/priority-routing-example.ts` for comprehensive examples.
516
+
517
+ ---
518
+
519
+ ## Debugging with `.tap()`
520
+
521
+ Inspect pipeline intermediate results at any point using `.tap()` - a pure TypeScript method (no C++ changes):
522
+
523
+ ```typescript
524
+ const pipeline = createDspPipeline()
525
+ .MovingAverage({ windowSize: 10 })
526
+ .tap((samples, stage) => {
527
+ console.log(`After ${stage}:`, samples.slice(0, 5));
528
+ })
529
+ .Rectify({ mode: "full" })
530
+ .tap((samples, stage) => {
531
+ const max = Math.max(...samples);
532
+ if (max > THRESHOLD) {
533
+ logger.warn(`High value detected at ${stage}: ${max}`);
534
+ }
535
+ })
536
+ .Rms({ windowSize: 5 });
537
+ ```
538
+
539
+ ### Use Cases
540
+
541
+ - 🐛 **Debug pipeline behavior** - Inspect values between stages
542
+ - 📊 **Collect statistics** - Calculate min/max/mean at any point
543
+ - ⚠️ **Threshold monitoring** - Alert on anomalies during processing
544
+ - 📝 **Logger integration** - Conditional logging based on sample values
545
+ - 🔍 **Development insights** - Understand signal transformations
546
+
547
+ ### Performance
548
+
549
+ - Minimal overhead (~4% with empty callbacks in benchmarks)
550
+ - Remove `.tap()` calls in production or use conditional logic
551
+ - Errors in tap callbacks are caught and logged (won't break pipeline)
552
+
553
+ See `src/ts/examples/tap-debugging.ts` for comprehensive examples.
554
+
555
+ ---
556
+
557
+ ## Back to Main Documentation
558
+
559
+ [← Back to README](../README.md)