@oas-tools/oas-telemetry 0.7.1 → 0.8.0-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.
- package/.env.example +21 -2
- package/README.md +1 -2
- package/dist/cjs/config/bootConfig.cjs +19 -14
- package/dist/cjs/config/config.cjs +112 -125
- package/dist/cjs/config/config.types.cjs +1 -4
- package/dist/cjs/docs/openapi.yaml +158 -4
- package/dist/cjs/index.cjs +27 -30
- package/dist/cjs/routesManager.cjs +62 -70
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs +202 -190
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +204 -99
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +152 -116
- package/dist/cjs/telemetry/custom-implementations/instrumentations/logsInstrumentation.cjs +92 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/Chunk.cjs +159 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/Series.cjs +168 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.cjs +389 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/types.cjs +2 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/utils.cjs +77 -0
- package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.cjs +65 -63
- package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.cjs +63 -62
- package/dist/cjs/telemetry/custom-implementations/utils/circular.cjs +47 -47
- package/dist/cjs/telemetry/custom-implementations/utils/storagePath.cjs +39 -0
- package/dist/cjs/telemetry/custom-implementations/wrappers.cjs +141 -138
- package/dist/cjs/telemetry/initializeTelemetry.cjs +35 -91
- package/dist/cjs/telemetry/telemetryConfigurator.cjs +70 -72
- package/dist/cjs/telemetry/telemetryRegistry.cjs +45 -31
- package/dist/cjs/tlm-ai/agent.cjs +49 -64
- package/dist/cjs/tlm-ai/aiController.cjs +54 -76
- package/dist/cjs/tlm-ai/aiRoutes.cjs +17 -20
- package/dist/cjs/tlm-ai/aiService.cjs +91 -95
- package/dist/cjs/tlm-ai/tools.cjs +177 -174
- package/dist/cjs/tlm-auth/authController.cjs +80 -123
- package/dist/cjs/tlm-auth/authMiddleware.cjs +25 -30
- package/dist/cjs/tlm-auth/authRoutes.cjs +11 -14
- package/dist/cjs/tlm-log/logController.cjs +171 -116
- package/dist/cjs/tlm-log/logRoutes.cjs +20 -20
- package/dist/cjs/tlm-metric/metricsController.cjs +211 -121
- package/dist/cjs/tlm-metric/metricsRoutes.cjs +23 -20
- package/dist/cjs/tlm-plugin/pluginController.cjs +128 -140
- package/dist/cjs/tlm-plugin/pluginProcess.cjs +89 -94
- package/dist/cjs/tlm-plugin/pluginRoutes.cjs +11 -14
- package/dist/cjs/tlm-plugin/pluginService.cjs +73 -74
- package/dist/cjs/tlm-trace/traceController.cjs +169 -117
- package/dist/cjs/tlm-trace/traceRoutes.cjs +20 -20
- package/dist/cjs/tlm-ui/uiRoutes.cjs +63 -32
- package/dist/cjs/tlm-util/utilController.cjs +68 -70
- package/dist/cjs/tlm-util/utilRoutes.cjs +51 -63
- package/dist/cjs/types/index.cjs +2 -5
- package/dist/cjs/utils/logger.cjs +38 -43
- package/dist/cjs/utils/regexUtils.cjs +22 -22
- package/dist/esm/config/bootConfig.js +6 -0
- package/dist/esm/config/config.js +1 -2
- package/dist/esm/docs/openapi.yaml +158 -4
- package/dist/esm/index.js +9 -8
- package/dist/esm/routesManager.js +6 -10
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js +47 -8
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js +164 -48
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +69 -29
- package/dist/esm/telemetry/custom-implementations/instrumentations/logsInstrumentation.js +85 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/Chunk.js +155 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/Series.js +164 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.js +382 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/types.js +1 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/utils.js +74 -0
- package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.js +2 -1
- package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.js +1 -1
- package/dist/esm/telemetry/custom-implementations/utils/storagePath.js +33 -0
- package/dist/esm/telemetry/custom-implementations/wrappers.js +5 -2
- package/dist/esm/telemetry/initializeTelemetry.js +27 -69
- package/dist/esm/telemetry/telemetryConfigurator.js +42 -40
- package/dist/esm/telemetry/telemetryRegistry.js +12 -1
- package/dist/esm/tlm-ai/agent.js +5 -3
- package/dist/esm/tlm-ai/aiController.js +3 -3
- package/dist/esm/tlm-ai/aiService.js +6 -2
- package/dist/esm/tlm-ai/tools.js +5 -9
- package/dist/esm/tlm-auth/authController.js +3 -2
- package/dist/esm/tlm-log/logController.js +84 -4
- package/dist/esm/tlm-log/logRoutes.js +5 -2
- package/dist/esm/tlm-metric/metricsController.js +172 -49
- package/dist/esm/tlm-metric/metricsRoutes.js +10 -4
- package/dist/esm/tlm-plugin/pluginController.js +6 -11
- package/dist/esm/tlm-plugin/pluginService.js +2 -4
- package/dist/esm/tlm-trace/traceController.js +102 -16
- package/dist/esm/tlm-trace/traceRoutes.js +5 -2
- package/dist/esm/tlm-ui/uiRoutes.js +5 -5
- package/dist/esm/tlm-util/utilController.js +3 -9
- package/dist/esm/tlm-util/utilRoutes.js +2 -2
- package/dist/types/config/bootConfig.d.ts +4 -0
- package/dist/types/config/config.d.ts +36 -7
- package/dist/types/config/config.types.d.ts +6 -0
- package/dist/types/index.d.ts +2 -3
- package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts +4 -1
- package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts +60 -15
- package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts +9 -4
- package/dist/types/telemetry/custom-implementations/instrumentations/logsInstrumentation.d.ts +23 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/Chunk.d.ts +49 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/Series.d.ts +67 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.d.ts +69 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/types.d.ts +68 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/utils.d.ts +21 -0
- package/dist/types/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.d.ts +2 -2
- package/dist/types/telemetry/custom-implementations/utils/storagePath.d.ts +12 -0
- package/dist/types/telemetry/custom-implementations/wrappers.d.ts +1 -1
- package/dist/types/telemetry/telemetryConfigurator.d.ts +1 -1
- package/dist/types/telemetry/telemetryRegistry.d.ts +8 -0
- package/dist/types/tlm-ai/agent.d.ts +1 -1
- package/dist/types/tlm-ai/aiService.d.ts +1 -1
- package/dist/types/tlm-log/logController.d.ts +2 -0
- package/dist/types/tlm-metric/metricsController.d.ts +16 -2
- package/dist/types/tlm-trace/traceController.d.ts +3 -1
- package/dist/types/types/index.d.ts +2 -2
- package/dist/ui/assets/{ApiDocsPage-C_VVPPHa.js → ApiDocsPage-BFUrXE5F.js} +2 -2
- package/dist/ui/assets/CollapsibleCard-STA1GVQO.js +1 -0
- package/dist/ui/assets/DevToolsPage-BRSfZqO_.js +1 -0
- package/dist/ui/assets/LandingPage-DzeDy7q7.js +6 -0
- package/dist/ui/assets/LogsPage-BeiFrV2X.js +1 -0
- package/dist/ui/assets/{NotFoundPage-B3quk3P1.js → NotFoundPage-fRNOatbM.js} +1 -1
- package/dist/ui/assets/PluginCreatePage-Ch_RXsdf.js +50 -0
- package/dist/ui/assets/PluginPage-Cl65ZZ_n.js +27 -0
- package/dist/ui/assets/TraceSpansPage-BoK4M5Hh.js +6 -0
- package/dist/ui/assets/VirtualizedListPanel-zcj0v7DL.js +16 -0
- package/dist/ui/assets/alert-BkNVKxJN.js +1133 -0
- package/dist/ui/assets/badge-CN7FeufU.js +1 -0
- package/dist/ui/assets/{chevron-down-CPsvsmqj.js → chevron-down-CG--ounh.js} +1 -1
- package/dist/ui/assets/{chevron-up-Df9jMo1X.js → chevron-up-B6tzMAOm.js} +1 -1
- package/dist/ui/assets/{circle-alert-DOPQPvU8.js → circle-alert-BDF8Tq9y.js} +1 -1
- package/dist/ui/assets/dialog-BrpWNk36.js +15 -0
- package/dist/ui/assets/index-6xOVKwKn.js +305 -0
- package/dist/ui/assets/index-D6f1KjWV.css +1 -0
- package/dist/ui/assets/index-D96rVSkR.js +1 -0
- package/dist/ui/assets/info-99kuqpbx.js +6 -0
- package/dist/ui/assets/{input-Dzvg_ZEZ.js → input-B-01QDg_.js} +1 -1
- package/dist/ui/assets/label-CQLeZjM1.js +1 -0
- package/dist/ui/assets/{loader-circle-CrvlRy5o.js → loader-circle-BoDGk-BO.js} +1 -1
- package/dist/ui/assets/{loginPage-qa4V-B70.js → loginPage-8F4EEd1B.js} +1 -1
- package/dist/ui/assets/metrics-page-D1GxaB_c.css +1 -0
- package/dist/ui/assets/metrics-page-DPtteXqY.js +31 -0
- package/dist/ui/assets/popover-DS_8DYYt.js +11 -0
- package/dist/ui/assets/select-DYjegiXi.js +6 -0
- package/dist/ui/assets/separator-DGsRxIrl.js +6 -0
- package/dist/ui/assets/severityOptions-DEOvJqC9.js +11 -0
- package/dist/ui/assets/square-pen-DPhgYz6O.js +6 -0
- package/dist/ui/assets/switch-Di9NJH2A.js +1 -0
- package/dist/ui/assets/trace-DJq1miYa.js +1 -0
- package/dist/ui/assets/upload-BiLTpCnX.js +11 -0
- package/dist/ui/assets/{utilService-DNyqzwj0.js → utilService-CNZOmadC.js} +1 -1
- package/dist/ui/assets/wand-sparkles-CPoBNFFg.js +6 -0
- package/dist/ui/index.html +2 -2
- package/package.json +44 -48
- package/dist/ui/assets/CollapsibleCard-B3KR_8mL.js +0 -1
- package/dist/ui/assets/DevToolsPage-OyZcDcmw.js +0 -1
- package/dist/ui/assets/LandingPage-CppFBA6K.js +0 -6
- package/dist/ui/assets/LogsPage-9Fq8GArS.js +0 -26
- package/dist/ui/assets/PluginCreatePage-X_aCH4t4.js +0 -50
- package/dist/ui/assets/PluginPage-DMDSihrZ.js +0 -27
- package/dist/ui/assets/alert-jQ9HCPIf.js +0 -1133
- package/dist/ui/assets/badge-CNq0-mH5.js +0 -1
- package/dist/ui/assets/card-DFAwwhN3.js +0 -1
- package/dist/ui/assets/index-BkD6DijD.js +0 -15
- package/dist/ui/assets/index-CERGVYZK.js +0 -292
- package/dist/ui/assets/index-CSIPf9qw.css +0 -1
- package/dist/ui/assets/label-DuVnkZ4q.js +0 -1
- package/dist/ui/assets/select-DhS8YUtJ.js +0 -1
- package/dist/ui/assets/separator-isK4chBP.js +0 -6
- package/dist/ui/assets/severityOptions-O38dSOfk.js +0 -11
- package/dist/ui/assets/switch-Z3mImG9n.js +0 -1
- package/dist/ui/assets/tabs-_77MUUQe.js +0 -16
- package/dist/ui/assets/upload-C1LT4Gkb.js +0 -16
|
@@ -31,8 +31,8 @@ servers:
|
|
|
31
31
|
port:
|
|
32
32
|
default: "3000"
|
|
33
33
|
basePath:
|
|
34
|
-
default: telemetry
|
|
35
|
-
description: Base path for all endpoints.
|
|
34
|
+
default: oas-telemetry
|
|
35
|
+
description: Base path for all endpoints. Configured via OASTLM_BOOT_BASE_URL environment variable
|
|
36
36
|
|
|
37
37
|
tags:
|
|
38
38
|
- name: traces
|
|
@@ -326,6 +326,44 @@ paths:
|
|
|
326
326
|
type: string
|
|
327
327
|
example: Invalid retention time. Must be a positive number.
|
|
328
328
|
|
|
329
|
+
/traces/export:
|
|
330
|
+
get:
|
|
331
|
+
tags:
|
|
332
|
+
- traces
|
|
333
|
+
summary: Export collected traces
|
|
334
|
+
description: Export all collected traces in NDJSON format
|
|
335
|
+
responses:
|
|
336
|
+
'200':
|
|
337
|
+
description: Traces exported successfully
|
|
338
|
+
content:
|
|
339
|
+
application/x-ndjson:
|
|
340
|
+
schema:
|
|
341
|
+
type: string
|
|
342
|
+
|
|
343
|
+
/traces/import:
|
|
344
|
+
post:
|
|
345
|
+
tags:
|
|
346
|
+
- traces
|
|
347
|
+
summary: Import traces
|
|
348
|
+
description: Import traces from NDJSON format
|
|
349
|
+
requestBody:
|
|
350
|
+
required: true
|
|
351
|
+
content:
|
|
352
|
+
application/x-ndjson:
|
|
353
|
+
schema:
|
|
354
|
+
type: string
|
|
355
|
+
responses:
|
|
356
|
+
'200':
|
|
357
|
+
description: Traces imported successfully
|
|
358
|
+
content:
|
|
359
|
+
application/json:
|
|
360
|
+
schema:
|
|
361
|
+
type: object
|
|
362
|
+
properties:
|
|
363
|
+
message:
|
|
364
|
+
type: string
|
|
365
|
+
example: Traces imported successfully
|
|
366
|
+
|
|
329
367
|
/metrics:
|
|
330
368
|
get:
|
|
331
369
|
summary: Get collected metrics
|
|
@@ -548,6 +586,69 @@ paths:
|
|
|
548
586
|
type: string
|
|
549
587
|
example: Invalid retention time. Must be a positive number.
|
|
550
588
|
|
|
589
|
+
/metrics/export:
|
|
590
|
+
get:
|
|
591
|
+
tags:
|
|
592
|
+
- metrics
|
|
593
|
+
summary: Export collected metrics
|
|
594
|
+
description: Export all collected metrics in NDJSON format
|
|
595
|
+
responses:
|
|
596
|
+
'200':
|
|
597
|
+
description: Metrics exported successfully
|
|
598
|
+
content:
|
|
599
|
+
application/x-ndjson:
|
|
600
|
+
schema:
|
|
601
|
+
type: string
|
|
602
|
+
|
|
603
|
+
/metrics/import:
|
|
604
|
+
post:
|
|
605
|
+
tags:
|
|
606
|
+
- metrics
|
|
607
|
+
summary: Import metrics
|
|
608
|
+
description: Import metrics from NDJSON format
|
|
609
|
+
requestBody:
|
|
610
|
+
required: true
|
|
611
|
+
content:
|
|
612
|
+
application/x-ndjson:
|
|
613
|
+
schema:
|
|
614
|
+
type: string
|
|
615
|
+
responses:
|
|
616
|
+
'200':
|
|
617
|
+
description: Metrics imported successfully
|
|
618
|
+
content:
|
|
619
|
+
application/json:
|
|
620
|
+
schema:
|
|
621
|
+
type: object
|
|
622
|
+
properties:
|
|
623
|
+
message:
|
|
624
|
+
type: string
|
|
625
|
+
example: Metrics imported successfully
|
|
626
|
+
|
|
627
|
+
/metrics/stats:
|
|
628
|
+
get:
|
|
629
|
+
tags:
|
|
630
|
+
- metrics
|
|
631
|
+
summary: Get metrics statistics
|
|
632
|
+
description: Get statistics about collected metrics
|
|
633
|
+
responses:
|
|
634
|
+
'200':
|
|
635
|
+
description: Metrics statistics retrieved successfully
|
|
636
|
+
content:
|
|
637
|
+
application/json:
|
|
638
|
+
schema:
|
|
639
|
+
type: object
|
|
640
|
+
properties:
|
|
641
|
+
totalMetrics:
|
|
642
|
+
type: number
|
|
643
|
+
example: 42
|
|
644
|
+
activeMetrics:
|
|
645
|
+
type: number
|
|
646
|
+
example: 35
|
|
647
|
+
retentionTime:
|
|
648
|
+
type: number
|
|
649
|
+
description: Retention time in seconds
|
|
650
|
+
example: 3600
|
|
651
|
+
|
|
551
652
|
/logs:
|
|
552
653
|
get:
|
|
553
654
|
summary: Get collected logs
|
|
@@ -683,6 +784,44 @@ paths:
|
|
|
683
784
|
type: string
|
|
684
785
|
example: Invalid regex in query
|
|
685
786
|
|
|
787
|
+
/logs/export:
|
|
788
|
+
get:
|
|
789
|
+
tags:
|
|
790
|
+
- logs
|
|
791
|
+
summary: Export collected logs
|
|
792
|
+
description: Export all collected logs in NDJSON format
|
|
793
|
+
responses:
|
|
794
|
+
'200':
|
|
795
|
+
description: Logs exported successfully
|
|
796
|
+
content:
|
|
797
|
+
application/x-ndjson:
|
|
798
|
+
schema:
|
|
799
|
+
type: string
|
|
800
|
+
|
|
801
|
+
/logs/import:
|
|
802
|
+
post:
|
|
803
|
+
tags:
|
|
804
|
+
- logs
|
|
805
|
+
summary: Import logs
|
|
806
|
+
description: Import logs from NDJSON format
|
|
807
|
+
requestBody:
|
|
808
|
+
required: true
|
|
809
|
+
content:
|
|
810
|
+
application/x-ndjson:
|
|
811
|
+
schema:
|
|
812
|
+
type: string
|
|
813
|
+
responses:
|
|
814
|
+
'200':
|
|
815
|
+
description: Logs imported successfully
|
|
816
|
+
content:
|
|
817
|
+
application/json:
|
|
818
|
+
schema:
|
|
819
|
+
type: object
|
|
820
|
+
properties:
|
|
821
|
+
message:
|
|
822
|
+
type: string
|
|
823
|
+
example: Logs imported successfully
|
|
824
|
+
|
|
686
825
|
/utils/spec:
|
|
687
826
|
get:
|
|
688
827
|
summary: Get OpenAPI spec in JSON
|
|
@@ -842,14 +981,14 @@ paths:
|
|
|
842
981
|
type: string
|
|
843
982
|
example: Started generating mock logs
|
|
844
983
|
|
|
845
|
-
/utils/generate-wait
|
|
984
|
+
/utils/generate-wait:
|
|
846
985
|
get:
|
|
847
986
|
summary: Wait for the specified seconds
|
|
848
987
|
tags:
|
|
849
988
|
- utils
|
|
850
989
|
parameters:
|
|
851
990
|
- name: seconds
|
|
852
|
-
in:
|
|
991
|
+
in: query
|
|
853
992
|
required: false
|
|
854
993
|
schema:
|
|
855
994
|
type: integer
|
|
@@ -867,6 +1006,21 @@ paths:
|
|
|
867
1006
|
type: number
|
|
868
1007
|
example: 2
|
|
869
1008
|
|
|
1009
|
+
/utils/oas-telemetry-spec:
|
|
1010
|
+
get:
|
|
1011
|
+
summary: Get OAS-Telemetry specification
|
|
1012
|
+
tags:
|
|
1013
|
+
- utils
|
|
1014
|
+
description: Retrieve the OpenAPI specification for OAS-Telemetry
|
|
1015
|
+
responses:
|
|
1016
|
+
'200':
|
|
1017
|
+
description: OK
|
|
1018
|
+
content:
|
|
1019
|
+
application/json:
|
|
1020
|
+
schema:
|
|
1021
|
+
type: object
|
|
1022
|
+
description: OpenAPI specification
|
|
1023
|
+
|
|
870
1024
|
/health:
|
|
871
1025
|
get:
|
|
872
1026
|
summary: Health check
|
package/dist/esm/index.js
CHANGED
|
@@ -5,25 +5,26 @@ import { getConfig } from './config/config.js';
|
|
|
5
5
|
import { Router } from 'express';
|
|
6
6
|
import { configureRoutes } from './routesManager.js';
|
|
7
7
|
import { configureTelemetry } from './telemetry/telemetryConfigurator.js';
|
|
8
|
+
import { isTelemetryConfigured, setTelemetryRouter, getTelemetryRouter } from './telemetry/telemetryRegistry.js';
|
|
8
9
|
import { bootEnvVariables } from "./config/bootConfig.js";
|
|
9
|
-
// WARN: If changed the API, also change in packages/lib/src/types/cjs-index.d.ts (used for CJS compilation)
|
|
10
10
|
/**
|
|
11
11
|
* Returns the OAS-Telemetry middleware.
|
|
12
12
|
* All parameters are optional. However, either `spec` or `specFileName` must be provided to enable endpoint filtering.
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
function oasTelemetry(oasTlmInputConfig) {
|
|
15
|
+
if (isTelemetryConfigured()) {
|
|
16
|
+
return getTelemetryRouter();
|
|
17
|
+
}
|
|
15
18
|
const router = Router();
|
|
16
|
-
// This environment variable cannot be set via the config object,
|
|
17
|
-
// as it is required to disable OpenTelemetry SDK initialization,
|
|
18
|
-
// which occurs during the first import at the top of this file.
|
|
19
19
|
if (bootEnvVariables.OASTLM_BOOT_MODULE_DISABLED) {
|
|
20
|
+
setTelemetryRouter(router);
|
|
20
21
|
return router;
|
|
21
22
|
}
|
|
22
23
|
const oasTlmConfig = getConfig(oasTlmInputConfig);
|
|
23
|
-
logger.info("BaseUrl: ",
|
|
24
|
-
if (!oasTlmConfig.general.spec && !oasTlmConfig.general.specFileName)
|
|
25
|
-
logger.warn("No spec provided, endpoint filtering will not be available. Please provide either `spec` or `specFileName` in the configuration.");
|
|
24
|
+
logger.info("BaseUrl: ", bootEnvVariables.OASTLM_BOOT_BASE_URL);
|
|
26
25
|
configureTelemetry(oasTlmConfig);
|
|
27
26
|
configureRoutes(router, oasTlmConfig);
|
|
27
|
+
setTelemetryRouter(router);
|
|
28
28
|
return router;
|
|
29
29
|
}
|
|
30
|
+
export { oasTelemetry };
|
|
@@ -13,21 +13,17 @@ import { getAIRoutes } from "./tlm-ai/aiRoutes.js";
|
|
|
13
13
|
import { bootEnvVariables } from "./config/bootConfig.js";
|
|
14
14
|
import { getPluginRoutes } from "./tlm-plugin/pluginRoutes.js";
|
|
15
15
|
export const configureRoutes = (router, oasTlmConfig) => {
|
|
16
|
+
if (!oasTlmConfig.general.spec && !oasTlmConfig.general.specFileName) {
|
|
17
|
+
logger.warn("No spec provided, endpoint filtering will not be available. Please provide either `spec` or `specFileName` in the configuration.");
|
|
18
|
+
}
|
|
16
19
|
if (bootEnvVariables.OASTLM_BOOT_ENV === 'development') {
|
|
17
20
|
logger.info("Running in development mode, enabling CORS for all origins");
|
|
18
21
|
router.use(cors({
|
|
19
|
-
origin:
|
|
20
|
-
if (!origin || /^http:\/\/localhost:\d+$/.test(origin)) {
|
|
21
|
-
callback(null, true);
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
callback(new Error('Not allowed by CORS'));
|
|
25
|
-
}
|
|
26
|
-
},
|
|
22
|
+
origin: true,
|
|
27
23
|
credentials: true
|
|
28
24
|
}));
|
|
29
25
|
}
|
|
30
|
-
const telemetryBaseUrl =
|
|
26
|
+
const telemetryBaseUrl = bootEnvVariables.OASTLM_BOOT_BASE_URL;
|
|
31
27
|
// Sub-router for all telemetry endpoints
|
|
32
28
|
const telemetryRouter = Router();
|
|
33
29
|
// Body parser for JSON requests
|
|
@@ -35,7 +31,7 @@ export const configureRoutes = (router, oasTlmConfig) => {
|
|
|
35
31
|
if (req.body !== undefined) {
|
|
36
32
|
return next(); // Already parsed, no need to parse again.
|
|
37
33
|
}
|
|
38
|
-
return json({ limit: '
|
|
34
|
+
return json({ limit: '500mb' })(req, res, next);
|
|
39
35
|
});
|
|
40
36
|
telemetryRouter.get('/health', (_req, res) => {
|
|
41
37
|
res.status(200).send({ status: 'OK' });
|
|
@@ -6,18 +6,36 @@ import { applyNesting, removeCircularRefs } from '../utils/circular.js';
|
|
|
6
6
|
import { Enabler } from '../wrappers.js';
|
|
7
7
|
import logger from '../../../utils/logger.js';
|
|
8
8
|
import { pluginService } from '../../../tlm-plugin/pluginService.js';
|
|
9
|
+
import { getStoragePath } from '../utils/storagePath.js';
|
|
9
10
|
export class InMemoryDbLogExporter extends Enabler {
|
|
11
|
+
_db = null;
|
|
12
|
+
_miniSearch = null;
|
|
13
|
+
_retentionTimeInSeconds;
|
|
14
|
+
_storagePath = null;
|
|
15
|
+
_initialized = false;
|
|
10
16
|
constructor(retentionTimeInSeconds = 3600) {
|
|
11
17
|
super();
|
|
12
18
|
this._retentionTimeInSeconds = retentionTimeInSeconds;
|
|
13
|
-
this.
|
|
19
|
+
this._storagePath = getStoragePath('logs');
|
|
20
|
+
this._startCleanupJob();
|
|
21
|
+
}
|
|
22
|
+
_ensureInitialized() {
|
|
23
|
+
if (this._initialized)
|
|
24
|
+
return;
|
|
25
|
+
this._initialized = true;
|
|
26
|
+
this._db = new Datastore(this._storagePath ? { filename: this._storagePath, timestampData: true, autoload: true } : { timestampData: true });
|
|
14
27
|
this._db.ensureIndex({ fieldName: 'createdAt' });
|
|
15
28
|
this._miniSearch = new MiniSearch({
|
|
16
29
|
fields: ['body'],
|
|
17
30
|
storeFields: ['_id'],
|
|
18
31
|
idField: '_id',
|
|
19
32
|
});
|
|
20
|
-
this.
|
|
33
|
+
if (this._storagePath) {
|
|
34
|
+
logger.info(`[LogExporter] Disk storage enabled at: ${this._storagePath}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
logger.info(`[LogExporter] Using in-memory storage`);
|
|
38
|
+
}
|
|
21
39
|
}
|
|
22
40
|
/*
|
|
23
41
|
* SUPER WARNING:
|
|
@@ -31,6 +49,7 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
31
49
|
* @param resultCallback
|
|
32
50
|
*/
|
|
33
51
|
export(logs, resultCallback) {
|
|
52
|
+
this._ensureInitialized();
|
|
34
53
|
const logsToInsert = logs.map(logRecord => {
|
|
35
54
|
// Remove circular references first, then apply nesting, then export info
|
|
36
55
|
const formattedLog = this._formatLogRecord(logRecord);
|
|
@@ -48,7 +67,17 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
48
67
|
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
49
68
|
}
|
|
50
69
|
reset() {
|
|
51
|
-
this.
|
|
70
|
+
this._ensureInitialized();
|
|
71
|
+
// Remove all logs from database but keep persistence enabled
|
|
72
|
+
this._db.remove({}, { multi: true }, (err) => {
|
|
73
|
+
if (err) {
|
|
74
|
+
logger.error(`[LogExporter] Error during reset: ${err.message}`);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
logger.info(`[LogExporter] Reset - all logs cleared`);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Clear mini search index
|
|
52
81
|
this._miniSearch = new MiniSearch({
|
|
53
82
|
fields: ['body'],
|
|
54
83
|
storeFields: ['_id'],
|
|
@@ -61,8 +90,10 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
61
90
|
async shutdown() {
|
|
62
91
|
this._db = null;
|
|
63
92
|
this._miniSearch = null;
|
|
93
|
+
this._initialized = false;
|
|
64
94
|
}
|
|
65
95
|
async find(findConfig) {
|
|
96
|
+
this._ensureInitialized();
|
|
66
97
|
const { query, messageSearch, limit, sortOrder } = findConfig;
|
|
67
98
|
const finalQuery = { ...query };
|
|
68
99
|
const effectiveSortOrder = sortOrder || { timestamp: -1 };
|
|
@@ -73,10 +104,13 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
73
104
|
finalQuery._id = { $in: ids };
|
|
74
105
|
}
|
|
75
106
|
const docs = await new Promise((resolve, reject) => {
|
|
76
|
-
this._db.find(finalQuery)
|
|
77
|
-
.sort(effectiveSortOrder)
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
let query_exec = this._db.find(finalQuery)
|
|
108
|
+
.sort(effectiveSortOrder);
|
|
109
|
+
// Only apply limit if provided
|
|
110
|
+
if (limit !== undefined) {
|
|
111
|
+
query_exec = query_exec.limit(limit);
|
|
112
|
+
}
|
|
113
|
+
query_exec.exec((err, docs) => {
|
|
80
114
|
if (err)
|
|
81
115
|
reject(err);
|
|
82
116
|
else
|
|
@@ -103,6 +137,7 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
103
137
|
});
|
|
104
138
|
}
|
|
105
139
|
getFinishedLogs() {
|
|
140
|
+
this._ensureInitialized();
|
|
106
141
|
return this._db.getAllData();
|
|
107
142
|
}
|
|
108
143
|
/**
|
|
@@ -136,6 +171,8 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
136
171
|
return this._retentionTimeInSeconds;
|
|
137
172
|
}
|
|
138
173
|
_insertLogs(logsToInsert, resultCallback) {
|
|
174
|
+
if (!this._db)
|
|
175
|
+
return resultCallback({ code: ExportResultCode.FAILED });
|
|
139
176
|
this._db.insert(logsToInsert, (err, newDocs) => {
|
|
140
177
|
if (err) {
|
|
141
178
|
console.dir(err);
|
|
@@ -143,7 +180,7 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
143
180
|
return;
|
|
144
181
|
}
|
|
145
182
|
// console.dir(newDocs, { depth: 3 });
|
|
146
|
-
newDocs.forEach((doc) => this._miniSearch
|
|
183
|
+
newDocs.forEach((doc) => this._miniSearch?.add(doc));
|
|
147
184
|
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
148
185
|
});
|
|
149
186
|
return;
|
|
@@ -151,6 +188,8 @@ export class InMemoryDbLogExporter extends Enabler {
|
|
|
151
188
|
_startCleanupJob() {
|
|
152
189
|
const interval = 1000;
|
|
153
190
|
setInterval(() => {
|
|
191
|
+
if (!this._db)
|
|
192
|
+
return; // Safety check
|
|
154
193
|
const expirationDate = new Date(Date.now() - this._retentionTimeInSeconds * 1000);
|
|
155
194
|
this._db.remove({ createdAt: { $lt: expirationDate } }, { multi: true }, (err, numRemoved) => {
|
|
156
195
|
if (err) {
|
|
@@ -1,32 +1,100 @@
|
|
|
1
1
|
import { ExportResultCode } from '@opentelemetry/core';
|
|
2
|
-
import dataStore from '@seald-io/nedb';
|
|
3
|
-
import { applyNesting } from '../utils/circular.js';
|
|
4
2
|
import { Enabler } from '../wrappers.js';
|
|
5
3
|
import logger from '../../../utils/logger.js';
|
|
6
4
|
import { pluginService } from '../../../tlm-plugin/pluginService.js';
|
|
5
|
+
import { rawToOtel } from '../metrics/tsdb/utils.js';
|
|
6
|
+
import { SeriesRegistry } from '../metrics/tsdb/SeriesRegistry.js';
|
|
7
|
+
import { getStoragePath } from '../utils/storagePath.js';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
/**
|
|
10
|
+
* In-Memory TSDB Metric Exporter
|
|
11
|
+
* Series identified by: scope + metricName + attributes
|
|
12
|
+
*/
|
|
7
13
|
export class InMemoryDbMetricExporter extends Enabler {
|
|
8
|
-
|
|
14
|
+
static DEFAULT_CONFIG = {
|
|
15
|
+
retentionTimeInSeconds: 3600,
|
|
16
|
+
chunkSize: 120,
|
|
17
|
+
maxChunks: 60
|
|
18
|
+
};
|
|
19
|
+
registry;
|
|
20
|
+
config;
|
|
21
|
+
cachedResource = null;
|
|
22
|
+
_storageFilePath = null;
|
|
23
|
+
_autoSaveInterval = null;
|
|
24
|
+
_storageLogged = false; // Track if we've logged storage info
|
|
25
|
+
get rawDataDB() {
|
|
26
|
+
// For debug/inspection only - metrics are stored in registry chunks
|
|
27
|
+
const stats = this.registry.getStats();
|
|
28
|
+
return stats.totalSamples > 0 ? [`[${stats.totalSamples} samples in registry]`] : [];
|
|
29
|
+
}
|
|
30
|
+
constructor(config) {
|
|
9
31
|
super();
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
|
|
32
|
+
this.config = { ...InMemoryDbMetricExporter.DEFAULT_CONFIG, ...config };
|
|
33
|
+
this.registry = new SeriesRegistry(this.config.chunkSize, this.config.maxChunks);
|
|
34
|
+
// Load persisted metrics if disk storage is enabled
|
|
35
|
+
this._storageFilePath = getStoragePath('metrics');
|
|
36
|
+
if (this._storageFilePath) {
|
|
37
|
+
this._loadMetricsFromDisk();
|
|
38
|
+
this._startAutoSave();
|
|
39
|
+
}
|
|
13
40
|
this._startCleanupJob();
|
|
14
41
|
}
|
|
15
|
-
|
|
42
|
+
_loadMetricsFromDisk() {
|
|
43
|
+
if (!this._storageFilePath)
|
|
44
|
+
return;
|
|
45
|
+
try {
|
|
46
|
+
if (fs.existsSync(this._storageFilePath)) {
|
|
47
|
+
const ndjsonData = fs.readFileSync(this._storageFilePath, 'utf-8');
|
|
48
|
+
this.registry.deserializeFromNDJSON(ndjsonData);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Silently fail during boot
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
_startAutoSave() {
|
|
56
|
+
if (!this._storageFilePath)
|
|
57
|
+
return;
|
|
58
|
+
// Save every 30 seconds
|
|
59
|
+
this._autoSaveInterval = setInterval(() => {
|
|
60
|
+
this._saveMetricsToDisk();
|
|
61
|
+
}, 30000);
|
|
62
|
+
}
|
|
63
|
+
_saveMetricsToDisk() {
|
|
64
|
+
if (!this._storageFilePath)
|
|
65
|
+
return;
|
|
66
|
+
try {
|
|
67
|
+
const ndjsonData = this.registry.serializeToNDJSON();
|
|
68
|
+
fs.writeFileSync(this._storageFilePath, ndjsonData);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Silently fail to avoid logging issues
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export(resourceMetrics, resultCallback) {
|
|
75
|
+
// Log storage info on first export (when logger is ready)
|
|
76
|
+
if (!this._storageLogged) {
|
|
77
|
+
this._storageLogged = true;
|
|
78
|
+
if (this._storageFilePath) {
|
|
79
|
+
logger.info(`[MetricExporter] Disk storage enabled at: ${this._storageFilePath} (auto-save every 30s)`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
logger.info(`[MetricExporter] Using in-memory storage`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
16
85
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
86
|
+
// Cache resource (unique per exporter instance)
|
|
87
|
+
if (!this.cachedResource) {
|
|
88
|
+
this.cachedResource = resourceMetrics.resource;
|
|
89
|
+
}
|
|
90
|
+
const scopeMetrics = resourceMetrics.scopeMetrics;
|
|
91
|
+
// Broadcast to plugins
|
|
92
|
+
scopeMetrics?.forEach((metric) => {
|
|
20
93
|
pluginService.broadcastMetric(metric);
|
|
21
94
|
});
|
|
22
|
-
//
|
|
23
|
-
if (this.isEnabled()) {
|
|
24
|
-
this.
|
|
25
|
-
if (err) {
|
|
26
|
-
logger.error('Insertion Error:', err);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
95
|
+
// Store if enabled - use new storeScopeMetrics method
|
|
96
|
+
if (this.isEnabled() && scopeMetrics) {
|
|
97
|
+
this.registry.storeScopeMetrics(scopeMetrics);
|
|
30
98
|
}
|
|
31
99
|
setTimeout(() => resultCallback({ code: ExportResultCode.SUCCESS }), 0);
|
|
32
100
|
}
|
|
@@ -40,48 +108,96 @@ export class InMemoryDbMetricExporter extends Enabler {
|
|
|
40
108
|
}
|
|
41
109
|
shutdown() {
|
|
42
110
|
this._enabled = false;
|
|
43
|
-
|
|
111
|
+
// Stop auto-save and save one final time
|
|
112
|
+
if (this._autoSaveInterval) {
|
|
113
|
+
clearInterval(this._autoSaveInterval);
|
|
114
|
+
this._autoSaveInterval = null;
|
|
115
|
+
}
|
|
116
|
+
if (this._storageFilePath) {
|
|
117
|
+
this._saveMetricsToDisk();
|
|
118
|
+
logger.info(`[MetricExporter] Metrics saved to disk at shutdown`);
|
|
119
|
+
}
|
|
120
|
+
this.registry.reset();
|
|
44
121
|
return this.forceFlush();
|
|
45
122
|
}
|
|
123
|
+
reset() {
|
|
124
|
+
// Clear metrics but save empty state to disk
|
|
125
|
+
this.registry.reset();
|
|
126
|
+
if (this._storageFilePath) {
|
|
127
|
+
this._saveMetricsToDisk();
|
|
128
|
+
logger.info(`[MetricExporter] Reset - all metrics cleared and saved to disk`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
logger.info(`[MetricExporter] Reset - all metrics cleared`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
46
134
|
forceFlush() {
|
|
47
135
|
return Promise.resolve();
|
|
48
136
|
}
|
|
49
|
-
|
|
50
|
-
this.
|
|
137
|
+
getCachedResource() {
|
|
138
|
+
return this.cachedResource;
|
|
51
139
|
}
|
|
52
|
-
|
|
53
|
-
this.
|
|
140
|
+
set retentionTimeInSeconds(value) {
|
|
141
|
+
this.config.retentionTimeInSeconds = value;
|
|
142
|
+
logger.info(`Retention time set to ${value} seconds`);
|
|
143
|
+
}
|
|
144
|
+
get retentionTimeInSeconds() {
|
|
145
|
+
return this.config.retentionTimeInSeconds;
|
|
54
146
|
}
|
|
55
|
-
|
|
56
|
-
return this.
|
|
147
|
+
getStats() {
|
|
148
|
+
return this.registry.getStats();
|
|
149
|
+
}
|
|
150
|
+
_startCleanupJob() {
|
|
151
|
+
setInterval(() => {
|
|
152
|
+
const retentionTimeNs = this.config.retentionTimeInSeconds * 1_000_000_000;
|
|
153
|
+
const result = this.registry.evictOldData(retentionTimeNs);
|
|
154
|
+
if (result.evictedChunks > 0 || result.evictedSeries > 0) {
|
|
155
|
+
logger.debug(`Cleanup: evicted ${result.evictedChunks} chunks, ${result.evictedSeries} series`);
|
|
156
|
+
}
|
|
157
|
+
}, 5000);
|
|
57
158
|
}
|
|
58
159
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* @param callback - The callback to execute after insertion.
|
|
160
|
+
* Find metrics by scope+metric queries with filters
|
|
161
|
+
* Supports both raw and otel formats
|
|
62
162
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
163
|
+
find(request) {
|
|
164
|
+
const format = request.format || 'raw';
|
|
165
|
+
// Get raw results from registry using new unified query method
|
|
166
|
+
const rawResults = this.registry.query(request.scopeMetrics, request.from, request.to);
|
|
167
|
+
// Convert format if needed
|
|
168
|
+
if (format === 'otel') {
|
|
169
|
+
return { results: rawToOtel(rawResults) };
|
|
170
|
+
}
|
|
171
|
+
return { results: rawResults };
|
|
65
172
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
173
|
+
/**
|
|
174
|
+
* Export all metrics to NDJSON format (one chunk per line)
|
|
175
|
+
*/
|
|
176
|
+
exportToNDJSON() {
|
|
177
|
+
return this.registry.serializeToNDJSON();
|
|
69
178
|
}
|
|
70
|
-
|
|
71
|
-
|
|
179
|
+
/**
|
|
180
|
+
* Import metrics from NDJSON format
|
|
181
|
+
*/
|
|
182
|
+
importFromNDJSON(ndjsonData) {
|
|
183
|
+
this.registry.deserializeFromNDJSON(ndjsonData);
|
|
72
184
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Insert metrics in OpenTelemetry (OTEL) format directly into the registry
|
|
187
|
+
* @param scopeMetrics Array of ScopeMetrics (OTEL format)
|
|
188
|
+
*/
|
|
189
|
+
insertOtel(scopeMetrics) {
|
|
190
|
+
// Store only in registry (chunks) - no duplication
|
|
191
|
+
if (this.isEnabled()) {
|
|
192
|
+
this.registry.storeScopeMetrics(scopeMetrics);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Insert metrics in raw format (MetricQueryResult[]), converts to OTEL and delegates to insertOtel
|
|
197
|
+
* @param rawScopeMetrics Array of MetricQueryResult (raw format)
|
|
198
|
+
*/
|
|
199
|
+
insertRaw(rawScopeMetrics) {
|
|
200
|
+
const otelScopeMetrics = rawToOtel(rawScopeMetrics);
|
|
201
|
+
this.insertOtel(otelScopeMetrics);
|
|
86
202
|
}
|
|
87
203
|
}
|