@kopai/ui 0.0.5 → 0.2.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 (125) hide show
  1. package/README.md +137 -0
  2. package/dist/index.cjs +5069 -3
  3. package/dist/index.d.cts +301 -3
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +302 -3
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +5010 -3
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +25 -7
  10. package/src/components/KeyboardShortcuts/KeyboardShortcutsProvider.tsx +113 -0
  11. package/src/components/KeyboardShortcuts/ShortcutsHelpDialog.tsx +82 -0
  12. package/src/components/KeyboardShortcuts/context.ts +23 -0
  13. package/src/components/KeyboardShortcuts/index.ts +8 -0
  14. package/src/components/KeyboardShortcuts/types.ts +11 -0
  15. package/src/components/dashboard/Badge/Badge.stories.tsx +29 -0
  16. package/src/components/dashboard/Badge/index.tsx +32 -0
  17. package/src/components/dashboard/Button/Button.stories.tsx +107 -0
  18. package/src/components/dashboard/Button/index.tsx +63 -0
  19. package/src/components/dashboard/Card/Card.stories.tsx +81 -0
  20. package/src/components/dashboard/Card/index.tsx +58 -0
  21. package/src/components/dashboard/Chart/Chart.stories.tsx +48 -0
  22. package/src/components/dashboard/Chart/index.tsx +74 -0
  23. package/src/components/dashboard/DatePicker/DatePicker.stories.tsx +33 -0
  24. package/src/components/dashboard/DatePicker/index.tsx +41 -0
  25. package/src/components/dashboard/Divider/Divider.stories.tsx +17 -0
  26. package/src/components/dashboard/Divider/index.tsx +49 -0
  27. package/src/components/dashboard/Empty/Empty.stories.tsx +48 -0
  28. package/src/components/dashboard/Empty/index.tsx +46 -0
  29. package/src/components/dashboard/Grid/Grid.stories.tsx +52 -0
  30. package/src/components/dashboard/Grid/index.tsx +26 -0
  31. package/src/components/dashboard/Heading/Heading.stories.tsx +25 -0
  32. package/src/components/dashboard/Heading/index.tsx +27 -0
  33. package/src/components/dashboard/List/List.stories.tsx +37 -0
  34. package/src/components/dashboard/List/index.tsx +24 -0
  35. package/src/components/dashboard/Metric/Metric.stories.tsx +65 -0
  36. package/src/components/dashboard/Metric/index.tsx +36 -0
  37. package/src/components/dashboard/Stack/Stack.stories.tsx +61 -0
  38. package/src/components/dashboard/Stack/index.tsx +33 -0
  39. package/src/components/dashboard/Table/Table.stories.tsx +38 -0
  40. package/src/components/dashboard/Table/index.tsx +104 -0
  41. package/src/components/dashboard/Text/Text.stories.tsx +53 -0
  42. package/src/components/dashboard/Text/index.tsx +18 -0
  43. package/src/components/dashboard/index.ts +46 -0
  44. package/src/components/index.ts +17 -0
  45. package/src/components/observability/LogTimeline/LogDetailPane/AttributesTab.tsx +56 -0
  46. package/src/components/observability/LogTimeline/LogDetailPane/JsonTreeView.tsx +139 -0
  47. package/src/components/observability/LogTimeline/LogDetailPane/index.tsx +271 -0
  48. package/src/components/observability/LogTimeline/LogFilter.stories.tsx +66 -0
  49. package/src/components/observability/LogTimeline/LogFilter.test.tsx +696 -0
  50. package/src/components/observability/LogTimeline/LogFilter.tsx +674 -0
  51. package/src/components/observability/LogTimeline/LogRow.tsx +174 -0
  52. package/src/components/observability/LogTimeline/LogTimeline.stories.tsx +154 -0
  53. package/src/components/observability/LogTimeline/index.tsx +542 -0
  54. package/src/components/observability/LogTimeline/shortcuts.ts +18 -0
  55. package/src/components/observability/MetricHistogram/MetricHistogram.stories.tsx +20 -0
  56. package/src/components/observability/MetricHistogram/index.tsx +303 -0
  57. package/src/components/observability/MetricStat/MetricStat.stories.tsx +30 -0
  58. package/src/components/observability/MetricStat/index.tsx +281 -0
  59. package/src/components/observability/MetricTable/MetricTable.stories.tsx +20 -0
  60. package/src/components/observability/MetricTable/index.tsx +194 -0
  61. package/src/components/observability/MetricTimeSeries/MetricTimeSeries.stories.tsx +28 -0
  62. package/src/components/observability/MetricTimeSeries/index.tsx +462 -0
  63. package/src/components/observability/RawDataTable/RawDataTable.stories.tsx +27 -0
  64. package/src/components/observability/RawDataTable/index.tsx +131 -0
  65. package/src/components/observability/ServiceList/ServiceList.stories.tsx +20 -0
  66. package/src/components/observability/ServiceList/index.tsx +60 -0
  67. package/src/components/observability/ServiceList/shortcuts.ts +6 -0
  68. package/src/components/observability/TabBar/TabBar.stories.tsx +34 -0
  69. package/src/components/observability/TabBar/index.tsx +46 -0
  70. package/src/components/observability/TraceDetail/TraceDetail.stories.tsx +51 -0
  71. package/src/components/observability/TraceDetail/index.tsx +53 -0
  72. package/src/components/observability/TraceSearch/TraceSearch.stories.tsx +49 -0
  73. package/src/components/observability/TraceSearch/index.tsx +292 -0
  74. package/src/components/observability/TraceTimeline/DetailPane/AttributesTab.tsx +152 -0
  75. package/src/components/observability/TraceTimeline/DetailPane/EventsTab.tsx +128 -0
  76. package/src/components/observability/TraceTimeline/DetailPane/LinksTab.tsx +210 -0
  77. package/src/components/observability/TraceTimeline/DetailPane/index.tsx +174 -0
  78. package/src/components/observability/TraceTimeline/SpanRow.tsx +173 -0
  79. package/src/components/observability/TraceTimeline/TimelineBar.tsx +41 -0
  80. package/src/components/observability/TraceTimeline/Tooltip.tsx +42 -0
  81. package/src/components/observability/TraceTimeline/TraceHeader.tsx +88 -0
  82. package/src/components/observability/TraceTimeline/TraceTimeline.stories.tsx +25 -0
  83. package/src/components/observability/TraceTimeline/index.tsx +478 -0
  84. package/src/components/observability/TraceTimeline/shortcuts.ts +16 -0
  85. package/src/components/observability/__fixtures__/logs.ts +476 -0
  86. package/src/components/observability/__fixtures__/metrics.ts +216 -0
  87. package/src/components/observability/__fixtures__/raw-table.ts +204 -0
  88. package/src/components/observability/__fixtures__/services.ts +8 -0
  89. package/src/components/observability/__fixtures__/trace-summaries.ts +81 -0
  90. package/src/components/observability/__fixtures__/traces.ts +396 -0
  91. package/src/components/observability/index.ts +66 -0
  92. package/src/components/observability/renderers/OtelMetricDiscovery.tsx +77 -0
  93. package/src/components/observability/renderers/OtelMetricHistogram.tsx +29 -0
  94. package/src/components/observability/renderers/OtelMetricStat.tsx +44 -0
  95. package/src/components/observability/renderers/OtelMetricTable.tsx +29 -0
  96. package/src/components/observability/renderers/OtelMetricTimeSeries.tsx +30 -0
  97. package/src/components/observability/renderers/index.ts +5 -0
  98. package/src/components/observability/shared/LoadingSkeleton.tsx +43 -0
  99. package/src/components/observability/types.ts +113 -0
  100. package/src/components/observability/utils/attributes.ts +17 -0
  101. package/src/components/observability/utils/colors.ts +29 -0
  102. package/src/components/observability/utils/flatten-tree.ts +53 -0
  103. package/src/components/observability/utils/lttb.ts +121 -0
  104. package/src/components/observability/utils/time.ts +46 -0
  105. package/src/hooks/use-kopai-data.test.ts +296 -0
  106. package/src/hooks/use-kopai-data.ts +64 -0
  107. package/src/hooks/use-live-logs.test.ts +193 -0
  108. package/src/hooks/use-live-logs.ts +113 -0
  109. package/src/index.ts +15 -0
  110. package/src/lib/__snapshots__/generate-prompt-instructions.test.ts.snap +33 -0
  111. package/src/lib/catalog.ts +165 -0
  112. package/src/lib/component-catalog.test.ts +357 -0
  113. package/src/lib/component-catalog.ts +171 -0
  114. package/src/lib/dashboard-datasource.ts +76 -0
  115. package/src/lib/generate-prompt-instructions.test.ts +27 -0
  116. package/src/lib/generate-prompt-instructions.ts +185 -0
  117. package/src/lib/log-buffer.test.ts +88 -0
  118. package/src/lib/log-buffer.ts +62 -0
  119. package/src/lib/observability-catalog.ts +143 -0
  120. package/src/lib/renderer.test.tsx +693 -0
  121. package/src/lib/renderer.tsx +276 -0
  122. package/src/pages/observability.tsx +825 -0
  123. package/src/providers/kopai-provider.tsx +51 -0
  124. package/src/styles/globals.css +46 -0
  125. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,476 @@
1
+ import type { denormalizedSignals } from "@kopai/core";
2
+
3
+ type OtelLogsRow = denormalizedSignals.OtelLogsRow;
4
+
5
+ // Correlatable trace/span IDs (match traces fixture)
6
+ const TRACE_ID = "0af7651916cd43dd8448eb211c80319c";
7
+ const ROOT_SPAN = "b7ad6b7169203331";
8
+ const CHILD_AUTH = "5cc999522982f714";
9
+ const CHILD_USERS = "0e0a2b1c7f4d3e5a";
10
+ const CHILD_DB = "1a2b3c4d5e6f7a8b";
11
+
12
+ // Base timestamp, staggered over ~10 seconds
13
+ const BASE_NS = 1700000000000000000n;
14
+ const ts = (offsetMs: number) =>
15
+ (BASE_NS + BigInt(offsetMs) * 1000000n).toString();
16
+
17
+ export const mockLogRows: OtelLogsRow[] = [
18
+ // ── api-gateway logs ──
19
+ {
20
+ Timestamp: ts(0),
21
+ Body: "Request received: GET /api/users",
22
+ SeverityText: "INFO",
23
+ SeverityNumber: 9,
24
+ ServiceName: "api-gateway",
25
+ TraceId: TRACE_ID,
26
+ SpanId: ROOT_SPAN,
27
+ LogAttributes: {
28
+ "http.method": "GET",
29
+ "http.path": "/api/users",
30
+ "client.address": "192.168.1.42",
31
+ },
32
+ ResourceAttributes: {
33
+ "service.name": "api-gateway",
34
+ "service.version": "1.4.2",
35
+ "deployment.environment": "production",
36
+ },
37
+ ScopeName: "com.example.api-gateway",
38
+ },
39
+ {
40
+ Timestamp: ts(1),
41
+ Body: "Logging middleware initialized",
42
+ SeverityText: "TRACE",
43
+ SeverityNumber: 1,
44
+ ServiceName: "api-gateway",
45
+ LogAttributes: { "middleware.name": "loggingMiddleware" },
46
+ ResourceAttributes: {
47
+ "service.name": "api-gateway",
48
+ "service.version": "1.4.2",
49
+ },
50
+ ScopeName: "com.example.api-gateway",
51
+ },
52
+ {
53
+ Timestamp: ts(320),
54
+ Body: "Response sent: 200 OK (320ms)",
55
+ SeverityText: "INFO",
56
+ SeverityNumber: 9,
57
+ ServiceName: "api-gateway",
58
+ TraceId: TRACE_ID,
59
+ SpanId: ROOT_SPAN,
60
+ LogAttributes: {
61
+ "http.method": "GET",
62
+ "http.path": "/api/users",
63
+ "http.status_code": 200,
64
+ "response.duration_ms": 320,
65
+ },
66
+ ResourceAttributes: {
67
+ "service.name": "api-gateway",
68
+ "service.version": "1.4.2",
69
+ "deployment.environment": "production",
70
+ },
71
+ ScopeName: "com.example.api-gateway",
72
+ },
73
+ {
74
+ Timestamp: ts(1200),
75
+ Body: "Rate limit threshold approaching: 450/500 requests in current window",
76
+ SeverityText: "WARN",
77
+ SeverityNumber: 13,
78
+ ServiceName: "api-gateway",
79
+ LogAttributes: {
80
+ "rate_limit.current": 450,
81
+ "rate_limit.max": 500,
82
+ "rate_limit.window_seconds": 60,
83
+ },
84
+ ResourceAttributes: {
85
+ "service.name": "api-gateway",
86
+ "service.version": "1.4.2",
87
+ "deployment.environment": "production",
88
+ },
89
+ ScopeName: "com.example.api-gateway.rate-limiter",
90
+ },
91
+ {
92
+ Timestamp: ts(2500),
93
+ Body: "TLS certificate expires in 7 days",
94
+ SeverityText: "WARN",
95
+ SeverityNumber: 14,
96
+ ServiceName: "api-gateway",
97
+ LogAttributes: {
98
+ "tls.cert.expiry_days": 7,
99
+ "tls.cert.subject": "*.example.com",
100
+ },
101
+ ResourceAttributes: {
102
+ "service.name": "api-gateway",
103
+ "service.version": "1.4.2",
104
+ },
105
+ ScopeName: "com.example.api-gateway.tls",
106
+ },
107
+
108
+ // ── auth-service logs ──
109
+ {
110
+ Timestamp: ts(3),
111
+ Body: "User authenticated successfully",
112
+ SeverityText: "INFO",
113
+ SeverityNumber: 9,
114
+ ServiceName: "auth-service",
115
+ TraceId: TRACE_ID,
116
+ SpanId: CHILD_AUTH,
117
+ LogAttributes: {
118
+ "auth.method": "Bearer",
119
+ "auth.user_id": "usr_8f2k3j",
120
+ "auth.token_valid": true,
121
+ },
122
+ ResourceAttributes: {
123
+ "service.name": "auth-service",
124
+ "service.version": "2.1.0",
125
+ "deployment.environment": "production",
126
+ },
127
+ ScopeName: "com.example.auth-service",
128
+ },
129
+ {
130
+ Timestamp: ts(3500),
131
+ Body: "Token refresh issued for user usr_8f2k3j",
132
+ SeverityText: "DEBUG",
133
+ SeverityNumber: 5,
134
+ ServiceName: "auth-service",
135
+ LogAttributes: {
136
+ "auth.user_id": "usr_8f2k3j",
137
+ "auth.token_ttl_seconds": 3600,
138
+ },
139
+ ResourceAttributes: {
140
+ "service.name": "auth-service",
141
+ "service.version": "2.1.0",
142
+ },
143
+ ScopeName: "com.example.auth-service",
144
+ },
145
+ {
146
+ Timestamp: ts(5000),
147
+ Body: "Failed to validate token: signature mismatch",
148
+ SeverityText: "ERROR",
149
+ SeverityNumber: 17,
150
+ ServiceName: "auth-service",
151
+ LogAttributes: {
152
+ "error.type": "TokenValidationError",
153
+ "auth.method": "Bearer",
154
+ "auth.token_prefix": "eyJhbGci...",
155
+ },
156
+ ResourceAttributes: {
157
+ "service.name": "auth-service",
158
+ "service.version": "2.1.0",
159
+ "deployment.environment": "production",
160
+ },
161
+ ScopeName: "com.example.auth-service",
162
+ },
163
+ {
164
+ Timestamp: ts(5200),
165
+ Body: "Auth cache eviction: 128 expired entries removed",
166
+ SeverityText: "DEBUG",
167
+ SeverityNumber: 7,
168
+ ServiceName: "auth-service",
169
+ LogAttributes: {
170
+ "cache.evicted_count": 128,
171
+ "cache.remaining_count": 4096,
172
+ },
173
+ ResourceAttributes: {
174
+ "service.name": "auth-service",
175
+ "service.version": "2.1.0",
176
+ },
177
+ ScopeName: "com.example.auth-service.cache",
178
+ },
179
+
180
+ // ── user-service logs ──
181
+ {
182
+ Timestamp: ts(42),
183
+ Body: "Fetching users with pagination: limit=50 offset=0",
184
+ SeverityText: "DEBUG",
185
+ SeverityNumber: 5,
186
+ ServiceName: "user-service",
187
+ TraceId: TRACE_ID,
188
+ SpanId: CHILD_USERS,
189
+ LogAttributes: {
190
+ "app.users.limit": 50,
191
+ "app.users.offset": 0,
192
+ },
193
+ ResourceAttributes: {
194
+ "service.name": "user-service",
195
+ "service.version": "3.0.1",
196
+ },
197
+ ScopeName: "com.example.user-service",
198
+ },
199
+ {
200
+ Timestamp: ts(46),
201
+ Body: "Database query started: SELECT users",
202
+ SeverityText: "TRACE",
203
+ SeverityNumber: 2,
204
+ ServiceName: "user-service",
205
+ TraceId: TRACE_ID,
206
+ SpanId: CHILD_DB,
207
+ LogAttributes: {
208
+ "db.system": "postgresql",
209
+ "db.operation": "SELECT",
210
+ "db.sql.table": "users",
211
+ },
212
+ ResourceAttributes: {
213
+ "service.name": "user-service",
214
+ "service.version": "3.0.1",
215
+ },
216
+ ScopeName: "com.example.user-service.db",
217
+ },
218
+ {
219
+ Timestamp: ts(225),
220
+ Body: "Database query completed in 180ms, returned 42 rows",
221
+ SeverityText: "INFO",
222
+ SeverityNumber: 9,
223
+ ServiceName: "user-service",
224
+ TraceId: TRACE_ID,
225
+ SpanId: CHILD_DB,
226
+ LogAttributes: {
227
+ "db.system": "postgresql",
228
+ "db.operation": "SELECT",
229
+ "db.duration_ms": 180,
230
+ "db.rows_returned": 42,
231
+ },
232
+ ResourceAttributes: {
233
+ "service.name": "user-service",
234
+ "service.version": "3.0.1",
235
+ "deployment.environment": "production",
236
+ },
237
+ ScopeName: "com.example.user-service.db",
238
+ },
239
+ {
240
+ Timestamp: ts(4000),
241
+ Body: "Connection pool exhausted: all 20 connections in use",
242
+ SeverityText: "ERROR",
243
+ SeverityNumber: 17,
244
+ ServiceName: "user-service",
245
+ LogAttributes: {
246
+ "db.system": "postgresql",
247
+ "db.pool.size": 20,
248
+ "db.pool.active": 20,
249
+ "db.pool.idle": 0,
250
+ "db.pool.waiting": 5,
251
+ },
252
+ ResourceAttributes: {
253
+ "service.name": "user-service",
254
+ "service.version": "3.0.1",
255
+ "deployment.environment": "production",
256
+ },
257
+ ScopeName: "com.example.user-service.db",
258
+ },
259
+ {
260
+ Timestamp: ts(4100),
261
+ Body: "Connection pool recovered: 3 connections freed",
262
+ SeverityText: "INFO",
263
+ SeverityNumber: 10,
264
+ ServiceName: "user-service",
265
+ LogAttributes: {
266
+ "db.system": "postgresql",
267
+ "db.pool.size": 20,
268
+ "db.pool.active": 17,
269
+ "db.pool.idle": 3,
270
+ },
271
+ ResourceAttributes: {
272
+ "service.name": "user-service",
273
+ "service.version": "3.0.1",
274
+ },
275
+ ScopeName: "com.example.user-service.db",
276
+ },
277
+ {
278
+ Timestamp: ts(6000),
279
+ Body: "Slow query detected: 2340ms for SELECT on orders table",
280
+ SeverityText: "WARN",
281
+ SeverityNumber: 13,
282
+ ServiceName: "user-service",
283
+ LogAttributes: {
284
+ "db.system": "postgresql",
285
+ "db.operation": "SELECT",
286
+ "db.sql.table": "orders",
287
+ "db.duration_ms": 2340,
288
+ "db.slow_query_threshold_ms": 1000,
289
+ },
290
+ ResourceAttributes: {
291
+ "service.name": "user-service",
292
+ "service.version": "3.0.1",
293
+ "deployment.environment": "production",
294
+ },
295
+ ScopeName: "com.example.user-service.db",
296
+ },
297
+ {
298
+ Timestamp: ts(6500),
299
+ Body: "User profile updated: usr_3m9x1p",
300
+ SeverityText: "INFO",
301
+ SeverityNumber: 9,
302
+ ServiceName: "user-service",
303
+ LogAttributes: {
304
+ "app.user_id": "usr_3m9x1p",
305
+ "app.fields_updated": "email,phone",
306
+ },
307
+ ResourceAttributes: {
308
+ "service.name": "user-service",
309
+ "service.version": "3.0.1",
310
+ },
311
+ ScopeName: "com.example.user-service",
312
+ },
313
+ {
314
+ Timestamp: ts(7000),
315
+ Body: "Failed to parse request body: invalid JSON at position 42",
316
+ SeverityText: "ERROR",
317
+ SeverityNumber: 18,
318
+ ServiceName: "api-gateway",
319
+ LogAttributes: {
320
+ "http.method": "POST",
321
+ "http.path": "/api/users",
322
+ "error.type": "SyntaxError",
323
+ "error.position": 42,
324
+ },
325
+ ResourceAttributes: {
326
+ "service.name": "api-gateway",
327
+ "service.version": "1.4.2",
328
+ "deployment.environment": "production",
329
+ },
330
+ ScopeName: "com.example.api-gateway",
331
+ },
332
+ {
333
+ Timestamp: ts(7500),
334
+ Body: "Health check passed: all dependencies healthy",
335
+ SeverityText: "INFO",
336
+ SeverityNumber: 9,
337
+ ServiceName: "api-gateway",
338
+ LogAttributes: {
339
+ "health.db": "ok",
340
+ "health.cache": "ok",
341
+ "health.auth": "ok",
342
+ },
343
+ ResourceAttributes: {
344
+ "service.name": "api-gateway",
345
+ "service.version": "1.4.2",
346
+ },
347
+ ScopeName: "com.example.api-gateway.health",
348
+ },
349
+ {
350
+ Timestamp: ts(8000),
351
+ Body: "Graceful shutdown initiated",
352
+ SeverityText: "WARN",
353
+ SeverityNumber: 15,
354
+ ServiceName: "user-service",
355
+ LogAttributes: {
356
+ "shutdown.reason": "SIGTERM",
357
+ "shutdown.active_connections": 3,
358
+ },
359
+ ResourceAttributes: {
360
+ "service.name": "user-service",
361
+ "service.version": "3.0.1",
362
+ "deployment.environment": "production",
363
+ },
364
+ ScopeName: "com.example.user-service",
365
+ },
366
+ {
367
+ Timestamp: ts(8500),
368
+ Body: "Unrecoverable error in event loop - process exiting",
369
+ SeverityText: "FATAL",
370
+ SeverityNumber: 21,
371
+ ServiceName: "user-service",
372
+ LogAttributes: {
373
+ "error.type": "UnhandledRejection",
374
+ "error.message": "ENOMEM: not enough memory",
375
+ "process.pid": 12345,
376
+ },
377
+ ResourceAttributes: {
378
+ "service.name": "user-service",
379
+ "service.version": "3.0.1",
380
+ "deployment.environment": "production",
381
+ },
382
+ ScopeName: "com.example.user-service",
383
+ },
384
+ {
385
+ Timestamp: ts(9000),
386
+ Body: "Retry attempt 3/5 for upstream service call",
387
+ SeverityText: "WARN",
388
+ SeverityNumber: 13,
389
+ ServiceName: "api-gateway",
390
+ LogAttributes: {
391
+ "retry.attempt": 3,
392
+ "retry.max": 5,
393
+ "retry.backoff_ms": 800,
394
+ "upstream.service": "user-service",
395
+ },
396
+ ResourceAttributes: {
397
+ "service.name": "api-gateway",
398
+ "service.version": "1.4.2",
399
+ "deployment.environment": "production",
400
+ },
401
+ ScopeName: "com.example.api-gateway.retry",
402
+ },
403
+ {
404
+ Timestamp: ts(9200),
405
+ Body: "Circuit breaker opened for user-service",
406
+ SeverityText: "ERROR",
407
+ SeverityNumber: 17,
408
+ ServiceName: "api-gateway",
409
+ LogAttributes: {
410
+ "circuit_breaker.state": "open",
411
+ "circuit_breaker.failure_count": 10,
412
+ "circuit_breaker.threshold": 5,
413
+ "circuit_breaker.reset_timeout_ms": 30000,
414
+ "upstream.service": "user-service",
415
+ },
416
+ ResourceAttributes: {
417
+ "service.name": "api-gateway",
418
+ "service.version": "1.4.2",
419
+ "deployment.environment": "production",
420
+ },
421
+ ScopeName: "com.example.api-gateway.circuit-breaker",
422
+ },
423
+ {
424
+ Timestamp: ts(9500),
425
+ Body: "JWKS key rotation completed",
426
+ SeverityText: "INFO",
427
+ SeverityNumber: 10,
428
+ ServiceName: "auth-service",
429
+ LogAttributes: {
430
+ "auth.jwks.kid_old": "key-2023-10",
431
+ "auth.jwks.kid_new": "key-2023-11",
432
+ },
433
+ ResourceAttributes: {
434
+ "service.name": "auth-service",
435
+ "service.version": "2.1.0",
436
+ },
437
+ ScopeName: "com.example.auth-service.jwks",
438
+ },
439
+ {
440
+ Timestamp: ts(9800),
441
+ Body: "Metrics flush completed: 1247 data points exported",
442
+ SeverityText: "DEBUG",
443
+ SeverityNumber: 6,
444
+ ServiceName: "api-gateway",
445
+ LogAttributes: {
446
+ "metrics.data_points": 1247,
447
+ "metrics.export_duration_ms": 45,
448
+ "metrics.destination": "otel-collector:4317",
449
+ },
450
+ ResourceAttributes: {
451
+ "service.name": "api-gateway",
452
+ "service.version": "1.4.2",
453
+ },
454
+ ScopeName: "com.example.api-gateway.metrics",
455
+ },
456
+ {
457
+ Timestamp: ts(10000),
458
+ Body: "Request completed: GET /api/users/search?q=admin",
459
+ SeverityText: "INFO",
460
+ SeverityNumber: 9,
461
+ ServiceName: "api-gateway",
462
+ LogAttributes: {
463
+ "http.method": "GET",
464
+ "http.path": "/api/users/search",
465
+ "http.query": "q=admin",
466
+ "http.status_code": 200,
467
+ "response.duration_ms": 89,
468
+ },
469
+ ResourceAttributes: {
470
+ "service.name": "api-gateway",
471
+ "service.version": "1.4.2",
472
+ "deployment.environment": "production",
473
+ },
474
+ ScopeName: "com.example.api-gateway",
475
+ },
476
+ ];
@@ -0,0 +1,216 @@
1
+ import type { denormalizedSignals } from "@kopai/core";
2
+
3
+ type OtelMetricsRow = denormalizedSignals.OtelMetricsRow;
4
+
5
+ // Base timestamp: 2023-11-14T22:13:20Z in nanoseconds
6
+ // 5-minute window: 300_000ms
7
+ const BASE_NS = 1700000000000000000n;
8
+ const ts = (offsetMs: number) =>
9
+ (BASE_NS + BigInt(offsetMs) * 1000000n).toString();
10
+
11
+ // Interval for 50 points over 5 minutes = 6000ms each
12
+ const INTERVAL_MS = 6000;
13
+
14
+ // ── Gauge: http.server.active_requests ──
15
+ // 2 series: GET and POST, 25 points each = 50 total
16
+
17
+ function gaugePoint(
18
+ index: number,
19
+ value: number,
20
+ method: string
21
+ ): OtelMetricsRow {
22
+ return {
23
+ MetricType: "Gauge" as const,
24
+ MetricName: "http.server.active_requests",
25
+ MetricDescription: "Number of active HTTP server requests",
26
+ MetricUnit: "{requests}",
27
+ TimeUnix: ts(index * INTERVAL_MS),
28
+ StartTimeUnix: ts(0),
29
+ Value: value,
30
+ ServiceName: "api-gateway",
31
+ Attributes: { "http.method": method },
32
+ ResourceAttributes: {
33
+ "service.name": "api-gateway",
34
+ "service.version": "1.4.2",
35
+ "deployment.environment": "production",
36
+ },
37
+ ScopeName: "opentelemetry.instrumentation.http",
38
+ ScopeVersion: "0.44.0",
39
+ };
40
+ }
41
+
42
+ // GET series: fluctuates between 5-45
43
+ const getValues = [
44
+ 12, 18, 24, 15, 22, 35, 28, 19, 31, 42, 38, 25, 14, 20, 33, 27, 16, 39, 44,
45
+ 30, 21, 11, 26, 36, 8,
46
+ ];
47
+ // POST series: lower, fluctuates between 2-20
48
+ const postValues = [
49
+ 4, 7, 5, 9, 12, 8, 15, 6, 10, 18, 14, 7, 3, 11, 16, 9, 5, 13, 20, 12, 8, 4, 6,
50
+ 17, 2,
51
+ ];
52
+
53
+ export const mockGaugeRows: OtelMetricsRow[] = [
54
+ ...getValues.map((v, i) => gaugePoint(i, v, "GET")),
55
+ ...postValues.map((v, i) => gaugePoint(i, v, "POST")),
56
+ ];
57
+
58
+ // ── Sum: http.server.request_count ──
59
+ // 50 points, monotonically increasing, 2 series
60
+
61
+ function sumPoint(
62
+ index: number,
63
+ value: number,
64
+ method: string
65
+ ): OtelMetricsRow {
66
+ return {
67
+ MetricType: "Sum" as const,
68
+ MetricName: "http.server.request_count",
69
+ MetricDescription: "Total number of HTTP requests received",
70
+ MetricUnit: "{requests}",
71
+ TimeUnix: ts(index * INTERVAL_MS),
72
+ StartTimeUnix: ts(0),
73
+ Value: value,
74
+ IsMonotonic: 1,
75
+ AggTemporality: "CUMULATIVE",
76
+ ServiceName: "api-gateway",
77
+ Attributes: { "http.method": method },
78
+ ResourceAttributes: {
79
+ "service.name": "api-gateway",
80
+ "service.version": "1.4.2",
81
+ "deployment.environment": "production",
82
+ },
83
+ ScopeName: "opentelemetry.instrumentation.http",
84
+ ScopeVersion: "0.44.0",
85
+ };
86
+ }
87
+
88
+ // GET: starts at 1000, increases by 15-45 per interval
89
+ const getSumValues: number[] = [];
90
+ let getAccum = 1000;
91
+ for (let i = 0; i < 25; i++) {
92
+ getSumValues.push(getAccum);
93
+ getAccum += 15 + Math.floor(30 * Math.abs(Math.sin(i * 0.7)));
94
+ }
95
+
96
+ // POST: starts at 200, increases by 5-20 per interval
97
+ const postSumValues: number[] = [];
98
+ let postAccum = 200;
99
+ for (let i = 0; i < 25; i++) {
100
+ postSumValues.push(postAccum);
101
+ postAccum += 5 + Math.floor(15 * Math.abs(Math.sin(i * 0.5)));
102
+ }
103
+
104
+ export const mockSumRows: OtelMetricsRow[] = [
105
+ ...getSumValues.map((v, i) => sumPoint(i, v, "GET")),
106
+ ...postSumValues.map((v, i) => sumPoint(i, v, "POST")),
107
+ ];
108
+
109
+ // ── Histogram: http.server.request_duration ──
110
+ // 3 data points with explicit bounds [5, 10, 25, 50, 75, 100, 250, 500, 1000]
111
+
112
+ const HISTOGRAM_BOUNDS = [5, 10, 25, 50, 75, 100, 250, 500, 1000];
113
+
114
+ export const mockHistogramRows: OtelMetricsRow[] = [
115
+ {
116
+ MetricType: "Histogram" as const,
117
+ MetricName: "http.server.request_duration",
118
+ MetricDescription: "Duration of HTTP server requests",
119
+ MetricUnit: "ms",
120
+ TimeUnix: ts(0),
121
+ StartTimeUnix: ts(0),
122
+ ServiceName: "api-gateway",
123
+ Count: 1500,
124
+ Sum: 87450,
125
+ Min: 1,
126
+ Max: 1850,
127
+ ExplicitBounds: HISTOGRAM_BOUNDS,
128
+ BucketCounts: [120, 280, 350, 310, 180, 120, 85, 35, 15, 5],
129
+ AggTemporality: "CUMULATIVE",
130
+ Attributes: { "http.method": "GET" },
131
+ ResourceAttributes: {
132
+ "service.name": "api-gateway",
133
+ "service.version": "1.4.2",
134
+ "deployment.environment": "production",
135
+ },
136
+ ScopeName: "opentelemetry.instrumentation.http",
137
+ ScopeVersion: "0.44.0",
138
+ },
139
+ {
140
+ MetricType: "Histogram" as const,
141
+ MetricName: "http.server.request_duration",
142
+ MetricDescription: "Duration of HTTP server requests",
143
+ MetricUnit: "ms",
144
+ TimeUnix: ts(60000),
145
+ StartTimeUnix: ts(0),
146
+ ServiceName: "api-gateway",
147
+ Count: 3200,
148
+ Sum: 192000,
149
+ Min: 1,
150
+ Max: 2100,
151
+ ExplicitBounds: HISTOGRAM_BOUNDS,
152
+ BucketCounts: [250, 580, 720, 640, 380, 280, 190, 95, 45, 20],
153
+ AggTemporality: "CUMULATIVE",
154
+ Attributes: { "http.method": "GET" },
155
+ ResourceAttributes: {
156
+ "service.name": "api-gateway",
157
+ "service.version": "1.4.2",
158
+ "deployment.environment": "production",
159
+ },
160
+ ScopeName: "opentelemetry.instrumentation.http",
161
+ ScopeVersion: "0.44.0",
162
+ },
163
+ {
164
+ MetricType: "Histogram" as const,
165
+ MetricName: "http.server.request_duration",
166
+ MetricDescription: "Duration of HTTP server requests",
167
+ MetricUnit: "ms",
168
+ TimeUnix: ts(120000),
169
+ StartTimeUnix: ts(0),
170
+ ServiceName: "api-gateway",
171
+ Count: 4800,
172
+ Sum: 278400,
173
+ Min: 1,
174
+ Max: 1950,
175
+ ExplicitBounds: HISTOGRAM_BOUNDS,
176
+ BucketCounts: [380, 850, 1100, 950, 560, 420, 310, 140, 65, 25],
177
+ AggTemporality: "CUMULATIVE",
178
+ Attributes: { "http.method": "GET" },
179
+ ResourceAttributes: {
180
+ "service.name": "api-gateway",
181
+ "service.version": "1.4.2",
182
+ "deployment.environment": "production",
183
+ },
184
+ ScopeName: "opentelemetry.instrumentation.http",
185
+ ScopeVersion: "0.44.0",
186
+ },
187
+ ];
188
+
189
+ // ── Gauge: system.cpu.utilization ──
190
+ // 30 points, values 0-1 range, MetricUnit "1"
191
+
192
+ const cpuValues = [
193
+ 0.32, 0.35, 0.41, 0.38, 0.45, 0.52, 0.48, 0.55, 0.62, 0.58, 0.65, 0.71, 0.68,
194
+ 0.75, 0.82, 0.79, 0.73, 0.68, 0.61, 0.55, 0.48, 0.42, 0.38, 0.45, 0.52, 0.58,
195
+ 0.63, 0.57, 0.49, 0.44,
196
+ ];
197
+
198
+ export const mockStatRows: OtelMetricsRow[] = cpuValues.map((value, i) => ({
199
+ MetricType: "Gauge" as const,
200
+ MetricName: "system.cpu.utilization",
201
+ MetricDescription: "CPU utilization as a fraction (0.0 to 1.0)",
202
+ MetricUnit: "1",
203
+ TimeUnix: ts(i * 10000), // 10s intervals over 5 minutes
204
+ StartTimeUnix: ts(0),
205
+ Value: value,
206
+ ServiceName: "api-gateway",
207
+ Attributes: { "cpu.core": "all" },
208
+ ResourceAttributes: {
209
+ "service.name": "api-gateway",
210
+ "service.version": "1.4.2",
211
+ "deployment.environment": "production",
212
+ "host.name": "api-gw-prod-01",
213
+ },
214
+ ScopeName: "opentelemetry.instrumentation.system",
215
+ ScopeVersion: "0.44.0",
216
+ }));