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,326 @@
1
+ /**
2
+ * Advanced Topic Router Features Example
3
+ *
4
+ * Demonstrates:
5
+ * 1. Concurrency control per route
6
+ * 2. Metrics tracking and monitoring
7
+ * 3. Pluggable backend handlers
8
+ * 4. Production-grade observability
9
+ */
10
+
11
+ import {
12
+ createDspPipeline,
13
+ createTopicRouter,
14
+ createConsoleHandler,
15
+ createMockHandler,
16
+ } from "../../index.js";
17
+
18
+ console.log("Advanced Topic Router Features\n");
19
+
20
+ // Example 1: Concurrency Control
21
+ console.log("1. Concurrency Control (Prevent Alert Storms)\n");
22
+ {
23
+ let alertCount = 0;
24
+ const slowAlertHandler = async () => {
25
+ alertCount++;
26
+ console.log(
27
+ ` [Alert ${alertCount}] Processing (simulating network call)...`
28
+ );
29
+ await new Promise((resolve) => setTimeout(resolve, 100));
30
+ console.log(` [Alert ${alertCount}] Complete`);
31
+ };
32
+
33
+ const router = createTopicRouter()
34
+ .errors(slowAlertHandler, {
35
+ concurrency: 2, // Max 2 concurrent alerts
36
+ trackMetrics: true,
37
+ })
38
+ .default(createConsoleHandler())
39
+ .build();
40
+
41
+ const pipeline = createDspPipeline();
42
+ pipeline
43
+ .pipeline({
44
+ onLogBatch: (logs) => router.routeBatch(logs),
45
+ })
46
+ .MovingAverage({ mode: "moving", windowSize: 3 });
47
+
48
+ console.log(" Processing with concurrency limit of 2...\n");
49
+
50
+ const samples = new Float32Array([1, 2, 3]);
51
+ await pipeline.process(samples, { sampleRate: 1000 });
52
+
53
+ console.log("\n Metrics:");
54
+ const metrics = router.getMetrics();
55
+ metrics.forEach((m) => {
56
+ console.log(` â€ĸ Route: ${m.name}`);
57
+ console.log(` Executions: ${m.executionCount}`);
58
+ console.log(` Avg Duration: ${m.averageDuration.toFixed(2)}ms`);
59
+ console.log(
60
+ ` Min/Max: ${m.minDuration.toFixed(2)}ms / ${m.maxDuration.toFixed(
61
+ 2
62
+ )}ms`
63
+ );
64
+ });
65
+
66
+ console.log();
67
+ }
68
+
69
+ // Example 2: Metrics Tracking
70
+ console.log("2. Metrics Tracking (Mini-OpenTelemetry)\n");
71
+ {
72
+ const mock = createMockHandler((log) => {
73
+ console.log(` Tracked: [${log.topic}] ${log.message}`);
74
+ });
75
+
76
+ const router = createTopicRouter()
77
+ .performance(mock.handler, {
78
+ trackMetrics: true,
79
+ concurrency: 5,
80
+ })
81
+ .debug(mock.handler, {
82
+ trackMetrics: true,
83
+ })
84
+ .default(mock.handler, {
85
+ trackMetrics: false, // No tracking for default route
86
+ })
87
+ .build();
88
+
89
+ const pipeline = createDspPipeline();
90
+ pipeline
91
+ .pipeline({
92
+ onLogBatch: (logs) => router.routeBatch(logs),
93
+ })
94
+ .MovingAverage({ mode: "moving", windowSize: 3 })
95
+ .Rms({ mode: "moving", windowSize: 5 });
96
+
97
+ const samples = new Float32Array([1, -2, 3, -4, 5]);
98
+ await pipeline.process(samples, { sampleRate: 1000 });
99
+
100
+ console.log("\n Route Metrics:");
101
+ const metrics = router.getMetrics();
102
+ metrics.forEach((m) => {
103
+ console.log(`\n Route: ${m.name}`);
104
+ console.log(` â€ĸ Executions: ${m.executionCount}`);
105
+ console.log(` â€ĸ Total Duration: ${m.totalDuration.toFixed(2)}ms`);
106
+ console.log(` â€ĸ Avg Duration: ${m.averageDuration.toFixed(2)}ms`);
107
+ console.log(
108
+ ` â€ĸ Min/Max: ${m.minDuration.toFixed(2)}ms / ${m.maxDuration.toFixed(
109
+ 2
110
+ )}ms`
111
+ );
112
+ console.log(` â€ĸ Errors: ${m.errorCount}`);
113
+ console.log(
114
+ ` â€ĸ Last Executed: ${
115
+ m.lastExecuted ? new Date(m.lastExecuted).toISOString() : "Never"
116
+ }`
117
+ );
118
+ });
119
+
120
+ console.log(`\n Total logs captured: ${mock.getLogs().length}`);
121
+ console.log();
122
+ }
123
+
124
+ // Example 3: Pluggable Backends
125
+ console.log("3. Pluggable Backend Handlers\n");
126
+ {
127
+ console.log(" Using built-in handlers:\n");
128
+
129
+ // Simulate backend configurations
130
+ const mockPagerDuty = createMockHandler((log) => {
131
+ console.log(` [PagerDuty] Alert triggered: ${log.message}`);
132
+ });
133
+
134
+ const mockPrometheus = createMockHandler((log) => {
135
+ console.log(` [Prometheus] Metric recorded: ${log.topic}`);
136
+ });
137
+
138
+ const mockLoki = createMockHandler((log) => {
139
+ console.log(` [Loki] Log stored: [${log.level}] ${log.message}`);
140
+ });
141
+
142
+ const router = createTopicRouter()
143
+ .errors(mockPagerDuty.handler, { trackMetrics: true })
144
+ .performance(mockPrometheus.handler, { trackMetrics: true })
145
+ .debug(mockLoki.handler, { trackMetrics: true })
146
+ .build();
147
+
148
+ const pipeline = createDspPipeline();
149
+ pipeline
150
+ .pipeline({
151
+ onLogBatch: (logs) => router.routeBatch(logs),
152
+ })
153
+ .MovingAverage({ mode: "moving", windowSize: 3 });
154
+
155
+ const samples = new Float32Array([1, 2, 3]);
156
+ await pipeline.process(samples, { sampleRate: 1000 });
157
+
158
+ console.log("\n Backend Summary:");
159
+ console.log(` â€ĸ PagerDuty logs: ${mockPagerDuty.getLogs().length}`);
160
+ console.log(` â€ĸ Prometheus logs: ${mockPrometheus.getLogs().length}`);
161
+ console.log(` â€ĸ Loki logs: ${mockLoki.getLogs().length}`);
162
+ console.log();
163
+ }
164
+
165
+ // Example 4: Production-Grade Setup
166
+ console.log("4. Production-Grade Configuration\n");
167
+ {
168
+ console.log(" Multi-tier routing with metrics + concurrency:\n");
169
+
170
+ const criticalAlerts = createMockHandler((log) => {
171
+ console.log(` [CRITICAL] ${log.message}`);
172
+ });
173
+
174
+ const performanceMetrics = createMockHandler((log) => {
175
+ console.log(` [METRICS] ${log.topic}: ${JSON.stringify(log.context)}`);
176
+ });
177
+
178
+ const debugLogs = createMockHandler();
179
+
180
+ const router = createTopicRouter()
181
+ // Critical errors: Limited concurrency to prevent PagerDuty overload
182
+ .errors(criticalAlerts.handler, {
183
+ concurrency: 3,
184
+ trackMetrics: true,
185
+ })
186
+ // Performance: Higher concurrency for metrics
187
+ .performance(performanceMetrics.handler, {
188
+ concurrency: 10,
189
+ trackMetrics: true,
190
+ })
191
+ // Debug: No concurrency limit, but track metrics
192
+ .debug(debugLogs.handler, {
193
+ trackMetrics: true,
194
+ })
195
+ // Default: Console with no limits
196
+ .default(createConsoleHandler(), {
197
+ trackMetrics: false,
198
+ })
199
+ .build();
200
+
201
+ const pipeline = createDspPipeline();
202
+ pipeline
203
+ .pipeline({
204
+ onLogBatch: (logs) => router.routeBatch(logs),
205
+ })
206
+ .MovingAverage({ mode: "moving", windowSize: 10 })
207
+ .Rectify()
208
+ .Rms({ mode: "moving", windowSize: 5 });
209
+
210
+ const samples = new Float32Array(50).map(() => Math.random() * 10 - 5);
211
+ await pipeline.process(samples, { sampleRate: 48000 });
212
+
213
+ console.log("\n Final Metrics Report:");
214
+ const metrics = router.getMetrics();
215
+
216
+ console.log(
217
+ "\n ┌─────────────────────â”Ŧ──────────â”Ŧ─────────────â”Ŧ────────────┐"
218
+ );
219
+ console.log(
220
+ " │ Route │ Exec │ Avg (ms) │ Errors │"
221
+ );
222
+ console.log(
223
+ " ├─────────────────────â”ŧ──────────â”ŧ─────────────â”ŧ────────────┤"
224
+ );
225
+
226
+ metrics.forEach((m) => {
227
+ const route = m.name.padEnd(19);
228
+ const exec = String(m.executionCount).padEnd(8);
229
+ const avg = m.averageDuration.toFixed(2).padEnd(11);
230
+ const errors = String(m.errorCount).padEnd(10);
231
+ console.log(` │ ${route} │ ${exec} │ ${avg} │ ${errors} │`);
232
+ });
233
+
234
+ console.log(
235
+ " └─────────────────────┴──────────┴─────────────┴────────────┘"
236
+ );
237
+
238
+ console.log("\n Performance Insights:");
239
+ const totalExec = metrics.reduce((sum, m) => sum + m.executionCount, 0);
240
+ const avgLatency =
241
+ metrics.reduce((sum, m) => sum + m.averageDuration, 0) / metrics.length;
242
+ const totalErrors = metrics.reduce((sum, m) => sum + m.errorCount, 0);
243
+
244
+ console.log(` â€ĸ Total Route Executions: ${totalExec}`);
245
+ console.log(` â€ĸ Average Route Latency: ${avgLatency.toFixed(2)}ms`);
246
+ console.log(` â€ĸ Total Errors: ${totalErrors}`);
247
+ console.log(
248
+ ` â€ĸ Success Rate: ${((1 - totalErrors / totalExec) * 100).toFixed(2)}%`
249
+ );
250
+ }
251
+
252
+ // Example 5: Priority-Based Routing
253
+ console.log("\n5. Priority-Based Routing (NEW)\n");
254
+ {
255
+ console.log(
256
+ " Route critical errors to PagerDuty, warnings to Prometheus\n"
257
+ );
258
+
259
+ const pagerDuty = createMockHandler((log) => {
260
+ console.log(
261
+ ` [PagerDuty] ALERT: ${log.message} (priority: ${log.priority})`
262
+ );
263
+ });
264
+
265
+ const prometheus = createMockHandler((log) => {
266
+ console.log(
267
+ ` [Prometheus] Metric: ${log.message} (priority: ${log.priority})`
268
+ );
269
+ });
270
+
271
+ const loki = createMockHandler((log) => {
272
+ console.log(` [Loki] Log: ${log.message} (priority: ${log.priority})`);
273
+ });
274
+
275
+ const router = createTopicRouter()
276
+ // Critical errors (9-10) → PagerDuty
277
+ .errors(pagerDuty.handler, {
278
+ minPriority: 9,
279
+ maxPriority: 10,
280
+ concurrency: 3,
281
+ })
282
+ // Warnings (7-8) → Prometheus
283
+ .custom(/^pipeline\./, prometheus.handler, {
284
+ minPriority: 7,
285
+ maxPriority: 8,
286
+ })
287
+ // All logs → Loki
288
+ .default(loki.handler, {
289
+ minPriority: 1,
290
+ maxPriority: 10,
291
+ })
292
+ .build();
293
+
294
+ const pipeline = createDspPipeline();
295
+ pipeline
296
+ .pipeline({
297
+ onLogBatch: (logs) => router.routeBatch(logs),
298
+ })
299
+ .MovingAverage({ mode: "moving", windowSize: 5 });
300
+
301
+ const samples = new Float32Array([1, 2, 3, 4, 5]);
302
+ await pipeline.process(samples, { sampleRate: 1000 });
303
+
304
+ console.log(`\n Priority Summary:`);
305
+ console.log(
306
+ ` â€ĸ PagerDuty (critical 9-10): ${pagerDuty.getLogs().length} alerts`
307
+ );
308
+ console.log(
309
+ ` â€ĸ Prometheus (warn 7-8): ${prometheus.getLogs().length} metrics`
310
+ );
311
+ console.log(` â€ĸ Loki (all): ${loki.getLogs().length} logs`);
312
+ }
313
+
314
+ console.log("\nAdvanced Features Summary:");
315
+ console.log(" - Concurrency Control - Prevent backend overload");
316
+ console.log(" - Metrics Tracking - Built-in observability");
317
+ console.log(" - Pluggable Backends - Drop-in integrations");
318
+ console.log(" - Priority Routing - 10-level smart routing (NEW)");
319
+ console.log(" - Production-Ready - Real-world patterns");
320
+
321
+ console.log("\nUse Cases:");
322
+ console.log(" â€ĸ Rate-limit PagerDuty alerts (concurrency: 3)");
323
+ console.log(" â€ĸ Track route performance (trackMetrics: true)");
324
+ console.log(" â€ĸ Monitor error rates per backend");
325
+ console.log(" â€ĸ Route by priority (critical → PagerDuty, warn → metrics)");
326
+ console.log(" â€ĸ Optimize routing strategy with metrics");
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Benchmark: Circular Buffer vs Array for Log Pooling
3
+ * Demonstrates memory and performance benefits of circular buffer
4
+ */
5
+
6
+ import { CircularLogBuffer } from "../../CircularLogBuffer.js";
7
+ import type { LogEntry } from "../../types.js";
8
+
9
+ function benchmarkArray(iterations: number, logsPerIteration: number): number {
10
+ const startTime = performance.now();
11
+
12
+ for (let i = 0; i < iterations; i++) {
13
+ const logPool: LogEntry[] = [];
14
+
15
+ // Simulate log accumulation
16
+ for (let j = 0; j < logsPerIteration; j++) {
17
+ logPool.push({
18
+ level: "info",
19
+ message: `Log entry ${j}`,
20
+ context: { iteration: i, index: j },
21
+ timestamp: performance.now(),
22
+ });
23
+ }
24
+
25
+ // Simulate flush
26
+ const logs = [...logPool];
27
+ // In real app: send logs to callback
28
+ const _sum = logs.length;
29
+ }
30
+
31
+ return performance.now() - startTime;
32
+ }
33
+
34
+ function benchmarkCircularBuffer(
35
+ iterations: number,
36
+ logsPerIteration: number
37
+ ): number {
38
+ const buffer = new CircularLogBuffer(32);
39
+ const startTime = performance.now();
40
+
41
+ for (let i = 0; i < iterations; i++) {
42
+ // Simulate log accumulation
43
+ for (let j = 0; j < logsPerIteration; j++) {
44
+ buffer.push({
45
+ level: "info",
46
+ message: `Log entry ${j}`,
47
+ context: { iteration: i, index: j },
48
+ timestamp: performance.now(),
49
+ });
50
+ }
51
+
52
+ // Simulate flush
53
+ const logs = buffer.flush();
54
+ // In real app: send logs to callback
55
+ const _sum = logs.length;
56
+ }
57
+
58
+ return performance.now() - startTime;
59
+ }
60
+
61
+ console.log("Benchmarking Log Pooling: Array vs Circular Buffer\n");
62
+
63
+ const testCases = [
64
+ {
65
+ iterations: 1000,
66
+ logsPerIteration: 3,
67
+ description: "1000 iterations × 3 logs (typical usage)",
68
+ },
69
+ {
70
+ iterations: 10000,
71
+ logsPerIteration: 5,
72
+ description: "10000 iterations × 5 logs (high frequency)",
73
+ },
74
+ {
75
+ iterations: 100000,
76
+ logsPerIteration: 2,
77
+ description: "100000 iterations × 2 logs (extreme load)",
78
+ },
79
+ ];
80
+
81
+ for (const testCase of testCases) {
82
+ console.log(`Test: ${testCase.description}`);
83
+
84
+ // Warm-up
85
+ benchmarkArray(10, testCase.logsPerIteration);
86
+ benchmarkCircularBuffer(10, testCase.logsPerIteration);
87
+
88
+ // Run benchmarks
89
+ const arrayTime = benchmarkArray(
90
+ testCase.iterations,
91
+ testCase.logsPerIteration
92
+ );
93
+ const circularTime = benchmarkCircularBuffer(
94
+ testCase.iterations,
95
+ testCase.logsPerIteration
96
+ );
97
+
98
+ console.log(` Array approach: ${arrayTime.toFixed(3)}ms`);
99
+ console.log(` Circular buffer approach: ${circularTime.toFixed(3)}ms`);
100
+ console.log(` Speedup: ${(arrayTime / circularTime).toFixed(2)}x faster`);
101
+ console.log(` Time saved: ${(arrayTime - circularTime).toFixed(3)}ms\n`);
102
+ }
103
+
104
+ console.log("Key Benefits of Circular Buffer:");
105
+ console.log(" - Fixed memory footprint (no array reallocations)");
106
+ console.log(" - No garbage collection pressure from temporary arrays");
107
+ console.log(" - Cache-friendly memory access pattern");
108
+ console.log(" - Predictable performance under load");
109
+ console.log(" - Handles burst logging gracefully (overwrites oldest)");
@@ -0,0 +1,265 @@
1
+ import { createDspPipeline } from "../../bindings.js";
2
+ import type { PipelineCallbacks, LogLevel } from "../../types.js";
3
+
4
+ /**
5
+ * Example: Real-time audio monitoring with callbacks
6
+ * Demonstrates selective callback usage for performance monitoring
7
+ */
8
+
9
+ class PerformanceMonitor {
10
+ private stageTimes = new Map<string, number[]>();
11
+
12
+ recordStageTime(stage: string, durationMs: number) {
13
+ if (!this.stageTimes.has(stage)) {
14
+ this.stageTimes.set(stage, []);
15
+ }
16
+ this.stageTimes.get(stage)!.push(durationMs);
17
+ }
18
+
19
+ getStats(stage: string) {
20
+ const times = this.stageTimes.get(stage) || [];
21
+ if (times.length === 0) {
22
+ return { min: 0, max: 0, avg: 0, count: 0 };
23
+ }
24
+
25
+ return {
26
+ min: Math.min(...times),
27
+ max: Math.max(...times),
28
+ avg: times.reduce((a, b) => a + b, 0) / times.length,
29
+ count: times.length,
30
+ };
31
+ }
32
+
33
+ printReport() {
34
+ console.log("\nPerformance Report:");
35
+ console.log("─".repeat(70));
36
+ console.log(
37
+ "Stage".padEnd(30),
38
+ "Count".padEnd(10),
39
+ "Avg (ms)".padEnd(10),
40
+ "Min (ms)".padEnd(10),
41
+ "Max (ms)"
42
+ );
43
+ console.log("─".repeat(70));
44
+
45
+ for (const [stage, _] of this.stageTimes) {
46
+ const stats = this.getStats(stage);
47
+ console.log(
48
+ stage.padEnd(30),
49
+ stats.count.toString().padEnd(10),
50
+ stats.avg.toFixed(3).padEnd(10),
51
+ stats.min.toFixed(3).padEnd(10),
52
+ stats.max.toFixed(3)
53
+ );
54
+ }
55
+ console.log("─".repeat(70));
56
+ }
57
+ }
58
+
59
+ class SignalAnalyzer {
60
+ private peakCount = 0;
61
+ private clipCount = 0;
62
+
63
+ analyzeSample(value: number, index: number, stage: string) {
64
+ const absValue = Math.abs(value);
65
+
66
+ // Detect clipping (value at maximum)
67
+ if (absValue >= 0.99) {
68
+ this.clipCount++;
69
+ console.log(
70
+ `âš ī¸ Clipping detected at sample ${index} in ${stage}: ${value.toFixed(
71
+ 4
72
+ )}`
73
+ );
74
+ }
75
+ // Detect peaks (high amplitude)
76
+ else if (absValue > 0.85) {
77
+ this.peakCount++;
78
+ }
79
+ }
80
+
81
+ getReport() {
82
+ return {
83
+ peaks: this.peakCount,
84
+ clips: this.clipCount,
85
+ };
86
+ }
87
+ }
88
+
89
+ async function monitoringExample() {
90
+ console.log("=".repeat(70));
91
+ console.log("Real-time Audio Monitoring with Callbacks");
92
+ console.log("=".repeat(70));
93
+ console.log();
94
+
95
+ const monitor = new PerformanceMonitor();
96
+ const analyzer = new SignalAnalyzer();
97
+
98
+ const callbacks: PipelineCallbacks = {
99
+ // Analyze every sample for clipping/peaks (can be disabled for performance)
100
+ onSample: (value, index, stage) => {
101
+ analyzer.analyzeSample(value, index, stage);
102
+ },
103
+
104
+ // Track performance of each processing run
105
+ onStageComplete: (stage, durationMs) => {
106
+ monitor.recordStageTime(stage, durationMs);
107
+ },
108
+
109
+ // Handle errors gracefully
110
+ onError: (stage, error) => {
111
+ console.error(`❌ Error in ${stage}:`, error.message);
112
+ },
113
+
114
+ // Structured logging
115
+ onLog: (level, msg, ctx) => {
116
+ const timestamp = new Date().toISOString();
117
+ const emoji = {
118
+ debug: "🔍",
119
+ info: "â„šī¸",
120
+ warn: "âš ī¸",
121
+ error: "❌",
122
+ }[level];
123
+
124
+ if (level !== "debug") {
125
+ console.log(
126
+ `${emoji} [${timestamp}] [${level.toUpperCase()}] ${msg}`,
127
+ ctx ? JSON.stringify(ctx) : ""
128
+ );
129
+ }
130
+ },
131
+ };
132
+
133
+ // Build pipeline with comprehensive processing
134
+ const pipeline = createDspPipeline()
135
+ .pipeline(callbacks)
136
+ .MovingAverage({ mode: "moving", windowSize: 5 })
137
+ .Rectify({ mode: "full" })
138
+ .Rms({ mode: "moving", windowSize: 10 });
139
+
140
+ console.log("Processing audio batches...\n");
141
+
142
+ // Simulate multiple processing batches (like streaming audio)
143
+ const sampleRate = 44100;
144
+ const batchSize = 512; // Typical audio buffer size
145
+ const numBatches = 5;
146
+
147
+ for (let batch = 0; batch < numBatches; batch++) {
148
+ console.log(`\nProcessing batch ${batch + 1}/${numBatches}...`);
149
+
150
+ // Generate test signal with varying characteristics
151
+ const signal = new Float32Array(batchSize);
152
+ for (let i = 0; i < batchSize; i++) {
153
+ // Add some variation between batches
154
+ const amplitude = 0.5 + batch * 0.1;
155
+ signal[i] = Math.sin((2 * Math.PI * 440 * i) / sampleRate) * amplitude;
156
+
157
+ // Add occasional peaks
158
+ if (i % 100 === 0) {
159
+ signal[i] = 0.95;
160
+ }
161
+
162
+ // Add occasional clips in later batches
163
+ if (batch >= 3 && i % 150 === 0) {
164
+ signal[i] = 1.0; // Clipping!
165
+ }
166
+ }
167
+
168
+ await pipeline.process(signal, { sampleRate, channels: 1 });
169
+ }
170
+
171
+ // Print reports
172
+ monitor.printReport();
173
+
174
+ const signalStats = analyzer.getReport();
175
+ console.log("\nSignal Analysis:");
176
+ console.log("─".repeat(70));
177
+ console.log(` Peak samples (> 0.85): ${signalStats.peaks}`);
178
+ console.log(` Clipped samples (>= 0.99): ${signalStats.clips}`);
179
+ console.log("─".repeat(70));
180
+
181
+ console.log("\nMonitoring complete!\n");
182
+ }
183
+
184
+ async function selectiveCallbacksExample() {
185
+ console.log("\n" + "=".repeat(70));
186
+ console.log("Selective Callbacks Example (Performance-Optimized)");
187
+ console.log("=".repeat(70));
188
+ console.log();
189
+
190
+ let processCount = 0;
191
+
192
+ // Use only the callbacks you need for better performance
193
+ const lightweightCallbacks: PipelineCallbacks = {
194
+ // No onSample callback - saves significant overhead for large buffers
195
+ // onSample: undefined,
196
+
197
+ onStageComplete: (stage, durationMs) => {
198
+ processCount++;
199
+ console.log(
200
+ `✓ Batch ${processCount}: ${stage} completed in ${durationMs.toFixed(
201
+ 3
202
+ )}ms`
203
+ );
204
+ },
205
+
206
+ // Only log errors and warnings
207
+ onLog: (level, msg, ctx) => {
208
+ if (level === "error" || level === "warn") {
209
+ console.log(`[${level.toUpperCase()}] ${msg}`, ctx || "");
210
+ }
211
+ },
212
+ };
213
+
214
+ const pipeline = createDspPipeline()
215
+ .pipeline(lightweightCallbacks)
216
+ .MovingAverage({ mode: "moving", windowSize: 3 })
217
+ .Rms({ mode: "moving", windowSize: 5 });
218
+
219
+ console.log("Processing large batches without per-sample callbacks...\n");
220
+
221
+ // Process larger buffers more efficiently
222
+ const largeBuffer = new Float32Array(4096);
223
+ for (let i = 0; i < largeBuffer.length; i++) {
224
+ largeBuffer[i] = Math.random() * 0.5;
225
+ }
226
+
227
+ const iterations = 10;
228
+ const startTime = performance.now();
229
+
230
+ for (let i = 0; i < iterations; i++) {
231
+ await pipeline.process(largeBuffer, { sampleRate: 44100, channels: 1 });
232
+ }
233
+
234
+ const totalTime = performance.now() - startTime;
235
+ const avgTime = totalTime / iterations;
236
+
237
+ console.log("\n" + "─".repeat(70));
238
+ console.log(
239
+ `Processed ${iterations} batches of ${largeBuffer.length} samples`
240
+ );
241
+ console.log(`Total time: ${totalTime.toFixed(2)}ms`);
242
+ console.log(`Average per batch: ${avgTime.toFixed(3)}ms`);
243
+ console.log(
244
+ `Throughput: ${(
245
+ (largeBuffer.length * iterations) /
246
+ (totalTime / 1000)
247
+ ).toFixed(0)} samples/sec`
248
+ );
249
+ console.log("─".repeat(70));
250
+
251
+ console.log("\nPerformance test complete!\n");
252
+ }
253
+
254
+ async function main() {
255
+ try {
256
+ // Run both examples
257
+ await monitoringExample();
258
+ await selectiveCallbacksExample();
259
+ } catch (error) {
260
+ console.error("Example failed:", error);
261
+ process.exit(1);
262
+ }
263
+ }
264
+
265
+ main();