tracelattice 1.2.5
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/LICENSE +24 -0
- package/README.md +112 -0
- package/dist/ServerConfig.d.ts +229 -0
- package/dist/ServerConfig.d.ts.map +1 -0
- package/dist/ServerConfig.js +121 -0
- package/dist/ServerConfig.js.map +1 -0
- package/dist/__tests__/base-registry.test.d.ts +2 -0
- package/dist/__tests__/base-registry.test.d.ts.map +1 -0
- package/dist/__tests__/base-transport-cov.test.d.ts +2 -0
- package/dist/__tests__/base-transport-cov.test.d.ts.map +1 -0
- package/dist/__tests__/base-transport.test.d.ts +2 -0
- package/dist/__tests__/base-transport.test.d.ts.map +1 -0
- package/dist/__tests__/config-loader.test.d.ts +2 -0
- package/dist/__tests__/config-loader.test.d.ts.map +1 -0
- package/dist/__tests__/connection-pool-cov.test.d.ts +2 -0
- package/dist/__tests__/connection-pool-cov.test.d.ts.map +1 -0
- package/dist/__tests__/connection-pool.test.d.ts +2 -0
- package/dist/__tests__/connection-pool.test.d.ts.map +1 -0
- package/dist/__tests__/container.test.d.ts +2 -0
- package/dist/__tests__/container.test.d.ts.map +1 -0
- package/dist/__tests__/crud.test.d.ts +2 -0
- package/dist/__tests__/crud.test.d.ts.map +1 -0
- package/dist/__tests__/discovery-cache.test.d.ts +2 -0
- package/dist/__tests__/discovery-cache.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/factories.test.d.ts +2 -0
- package/dist/__tests__/factories.test.d.ts.map +1 -0
- package/dist/__tests__/health-checker-cov.test.d.ts +2 -0
- package/dist/__tests__/health-checker-cov.test.d.ts.map +1 -0
- package/dist/__tests__/health-checker.test.d.ts +2 -0
- package/dist/__tests__/health-checker.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/factories.d.ts +36 -0
- package/dist/__tests__/helpers/factories.d.ts.map +1 -0
- package/dist/__tests__/helpers/index.d.ts +3 -0
- package/dist/__tests__/helpers/index.d.ts.map +1 -0
- package/dist/__tests__/helpers/timers.d.ts +4 -0
- package/dist/__tests__/helpers/timers.d.ts.map +1 -0
- package/dist/__tests__/history-manager.test.d.ts +2 -0
- package/dist/__tests__/history-manager.test.d.ts.map +1 -0
- package/dist/__tests__/http-helpers-cov.test.d.ts +2 -0
- package/dist/__tests__/http-helpers-cov.test.d.ts.map +1 -0
- package/dist/__tests__/http-transport-cov.test.d.ts +2 -0
- package/dist/__tests__/http-transport-cov.test.d.ts.map +1 -0
- package/dist/__tests__/http-transport.test.d.ts +2 -0
- package/dist/__tests__/http-transport.test.d.ts.map +1 -0
- package/dist/__tests__/input-normalizer.test.d.ts +8 -0
- package/dist/__tests__/input-normalizer.test.d.ts.map +1 -0
- package/dist/__tests__/integration.test.d.ts +2 -0
- package/dist/__tests__/integration.test.d.ts.map +1 -0
- package/dist/__tests__/lib-server.test.d.ts +2 -0
- package/dist/__tests__/lib-server.test.d.ts.map +1 -0
- package/dist/__tests__/memory-persistence.test.d.ts +2 -0
- package/dist/__tests__/memory-persistence.test.d.ts.map +1 -0
- package/dist/__tests__/metrics-integration.test.d.ts +2 -0
- package/dist/__tests__/metrics-integration.test.d.ts.map +1 -0
- package/dist/__tests__/persistence.test.d.ts +2 -0
- package/dist/__tests__/persistence.test.d.ts.map +1 -0
- package/dist/__tests__/reasoning-integration.test.d.ts +11 -0
- package/dist/__tests__/reasoning-integration.test.d.ts.map +1 -0
- package/dist/__tests__/reasoning-types.test.d.ts +2 -0
- package/dist/__tests__/reasoning-types.test.d.ts.map +1 -0
- package/dist/__tests__/request-context.test.d.ts +2 -0
- package/dist/__tests__/request-context.test.d.ts.map +1 -0
- package/dist/__tests__/sanitize.test.d.ts +2 -0
- package/dist/__tests__/sanitize.test.d.ts.map +1 -0
- package/dist/__tests__/schema.test.d.ts +2 -0
- package/dist/__tests__/schema.test.d.ts.map +1 -0
- package/dist/__tests__/sequentialthinking-tools.test.d.ts +2 -0
- package/dist/__tests__/sequentialthinking-tools.test.d.ts.map +1 -0
- package/dist/__tests__/server-config.test.d.ts +2 -0
- package/dist/__tests__/server-config.test.d.ts.map +1 -0
- package/dist/__tests__/skill-discovery.test.d.ts +2 -0
- package/dist/__tests__/skill-discovery.test.d.ts.map +1 -0
- package/dist/__tests__/skill-registry.test.d.ts +2 -0
- package/dist/__tests__/skill-registry.test.d.ts.map +1 -0
- package/dist/__tests__/skill-watcher.test.d.ts +2 -0
- package/dist/__tests__/skill-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/sqlite-persistence.test.d.ts +2 -0
- package/dist/__tests__/sqlite-persistence.test.d.ts.map +1 -0
- package/dist/__tests__/sse-transport-cov.test.d.ts +2 -0
- package/dist/__tests__/sse-transport-cov.test.d.ts.map +1 -0
- package/dist/__tests__/sse-transport.test.d.ts +2 -0
- package/dist/__tests__/sse-transport.test.d.ts.map +1 -0
- package/dist/__tests__/streamable-http-cov.test.d.ts +2 -0
- package/dist/__tests__/streamable-http-cov.test.d.ts.map +1 -0
- package/dist/__tests__/streamable-http-transport.test.d.ts +2 -0
- package/dist/__tests__/streamable-http-transport.test.d.ts.map +1 -0
- package/dist/__tests__/structured-logger.test.d.ts +2 -0
- package/dist/__tests__/structured-logger.test.d.ts.map +1 -0
- package/dist/__tests__/thought-evaluator.test.d.ts +2 -0
- package/dist/__tests__/thought-evaluator.test.d.ts.map +1 -0
- package/dist/__tests__/thought-formatter.test.d.ts +2 -0
- package/dist/__tests__/thought-formatter.test.d.ts.map +1 -0
- package/dist/__tests__/thought-processor.test.d.ts +8 -0
- package/dist/__tests__/thought-processor.test.d.ts.map +1 -0
- package/dist/__tests__/tool-registry-cov.test.d.ts +2 -0
- package/dist/__tests__/tool-registry-cov.test.d.ts.map +1 -0
- package/dist/__tests__/tool-registry.test.d.ts +2 -0
- package/dist/__tests__/tool-registry.test.d.ts.map +1 -0
- package/dist/__tests__/tool-watcher.test.d.ts +2 -0
- package/dist/__tests__/tool-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/worker-manager-cov.test.d.ts +2 -0
- package/dist/__tests__/worker-manager-cov.test.d.ts.map +1 -0
- package/dist/__tests__/worker-manager.test.d.ts +2 -0
- package/dist/__tests__/worker-manager.test.d.ts.map +1 -0
- package/dist/cache/DiscoveryCache.d.ts +269 -0
- package/dist/cache/DiscoveryCache.d.ts.map +1 -0
- package/dist/cache/DiscoveryCache.js +100 -0
- package/dist/cache/DiscoveryCache.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +114 -0
- package/dist/cli.js.map +1 -0
- package/dist/cluster/WorkerManager.d.ts +166 -0
- package/dist/cluster/WorkerManager.d.ts.map +1 -0
- package/dist/cluster/WorkerManager.js +202 -0
- package/dist/cluster/WorkerManager.js.map +1 -0
- package/dist/cluster/worker.d.ts +11 -0
- package/dist/cluster/worker.d.ts.map +1 -0
- package/dist/cluster/worker.js +36 -0
- package/dist/cluster/worker.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +224 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +85 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/context/RequestContext.d.ts +61 -0
- package/dist/context/RequestContext.d.ts.map +1 -0
- package/dist/context/RequestContext.js +17 -0
- package/dist/context/RequestContext.js.map +1 -0
- package/dist/contracts/index.d.ts +10 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/interfaces.d.ts +107 -0
- package/dist/contracts/interfaces.d.ts.map +1 -0
- package/dist/contracts/interfaces.js +1 -0
- package/dist/core/HistoryManager.d.ts +514 -0
- package/dist/core/HistoryManager.d.ts.map +1 -0
- package/dist/core/HistoryManager.js +331 -0
- package/dist/core/HistoryManager.js.map +1 -0
- package/dist/core/IHistoryManager.d.ts +100 -0
- package/dist/core/IHistoryManager.d.ts.map +1 -0
- package/dist/core/IHistoryManager.js +1 -0
- package/dist/core/InputNormalizer.d.ts +139 -0
- package/dist/core/InputNormalizer.d.ts.map +1 -0
- package/dist/core/InputNormalizer.js +101 -0
- package/dist/core/InputNormalizer.js.map +1 -0
- package/dist/core/ThoughtEvaluator.d.ts +127 -0
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -0
- package/dist/core/ThoughtEvaluator.js +346 -0
- package/dist/core/ThoughtEvaluator.js.map +1 -0
- package/dist/core/ThoughtFormatter.d.ts +133 -0
- package/dist/core/ThoughtFormatter.d.ts.map +1 -0
- package/dist/core/ThoughtFormatter.js +70 -0
- package/dist/core/ThoughtFormatter.js.map +1 -0
- package/dist/core/ThoughtProcessor.d.ts +218 -0
- package/dist/core/ThoughtProcessor.d.ts.map +1 -0
- package/dist/core/ThoughtProcessor.js +205 -0
- package/dist/core/ThoughtProcessor.js.map +1 -0
- package/dist/core/reasoning.d.ts +169 -0
- package/dist/core/reasoning.d.ts.map +1 -0
- package/dist/core/reasoning.js +1 -0
- package/dist/core/step.d.ts +45 -0
- package/dist/core/step.d.ts.map +1 -0
- package/dist/core/step.js +1 -0
- package/dist/core/thought.d.ts +190 -0
- package/dist/core/thought.d.ts.map +1 -0
- package/dist/core/thought.js +1 -0
- package/dist/di/Container.d.ts +226 -0
- package/dist/di/Container.d.ts.map +1 -0
- package/dist/di/Container.js +96 -0
- package/dist/di/Container.js.map +1 -0
- package/dist/di/ServiceRegistry.d.ts +32 -0
- package/dist/di/ServiceRegistry.d.ts.map +1 -0
- package/dist/di/ServiceRegistry.js +1 -0
- package/dist/errors.d.ts +482 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +108 -0
- package/dist/errors.js.map +1 -0
- package/dist/health/HealthChecker.d.ts +73 -0
- package/dist/health/HealthChecker.d.ts.map +1 -0
- package/dist/health/HealthChecker.js +69 -0
- package/dist/health/HealthChecker.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/lib.d.ts +205 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +219 -0
- package/dist/lib.js.map +1 -0
- package/dist/logger/NullLogger.d.ts +154 -0
- package/dist/logger/NullLogger.d.ts.map +1 -0
- package/dist/logger/NullLogger.js +24 -0
- package/dist/logger/NullLogger.js.map +1 -0
- package/dist/logger/StructuredLogger.d.ts +327 -0
- package/dist/logger/StructuredLogger.d.ts.map +1 -0
- package/dist/logger/StructuredLogger.js +72 -0
- package/dist/logger/StructuredLogger.js.map +1 -0
- package/dist/metrics/__tests__/metrics.test.d.ts +2 -0
- package/dist/metrics/__tests__/metrics.test.d.ts.map +1 -0
- package/dist/metrics/metrics.impl.d.ts +252 -0
- package/dist/metrics/metrics.impl.d.ts.map +1 -0
- package/dist/metrics/metrics.impl.js +197 -0
- package/dist/metrics/metrics.impl.js.map +1 -0
- package/dist/persistence/FilePersistence.d.ts +66 -0
- package/dist/persistence/FilePersistence.d.ts.map +1 -0
- package/dist/persistence/FilePersistence.js +132 -0
- package/dist/persistence/FilePersistence.js.map +1 -0
- package/dist/persistence/MemoryPersistence.d.ts +68 -0
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -0
- package/dist/persistence/MemoryPersistence.js +51 -0
- package/dist/persistence/MemoryPersistence.js.map +1 -0
- package/dist/persistence/PersistenceBackend.d.ts +69 -0
- package/dist/persistence/PersistenceBackend.d.ts.map +1 -0
- package/dist/persistence/PersistenceBackend.js +1 -0
- package/dist/persistence/PersistenceFactory.d.ts +21 -0
- package/dist/persistence/PersistenceFactory.d.ts.map +1 -0
- package/dist/persistence/PersistenceFactory.js +25 -0
- package/dist/persistence/PersistenceFactory.js.map +1 -0
- package/dist/persistence/SqlitePersistence.d.ts +60 -0
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -0
- package/dist/persistence/SqlitePersistence.js +136 -0
- package/dist/persistence/SqlitePersistence.js.map +1 -0
- package/dist/pool/ConnectionPool.d.ts +215 -0
- package/dist/pool/ConnectionPool.d.ts.map +1 -0
- package/dist/pool/ConnectionPool.js +187 -0
- package/dist/pool/ConnectionPool.js.map +1 -0
- package/dist/registry/BaseRegistry.d.ts +203 -0
- package/dist/registry/BaseRegistry.d.ts.map +1 -0
- package/dist/registry/BaseRegistry.js +165 -0
- package/dist/registry/BaseRegistry.js.map +1 -0
- package/dist/registry/SkillRegistry.d.ts +69 -0
- package/dist/registry/SkillRegistry.d.ts.map +1 -0
- package/dist/registry/SkillRegistry.js +88 -0
- package/dist/registry/SkillRegistry.js.map +1 -0
- package/dist/registry/ToolRegistry.d.ts +69 -0
- package/dist/registry/ToolRegistry.d.ts.map +1 -0
- package/dist/registry/ToolRegistry.js +93 -0
- package/dist/registry/ToolRegistry.js.map +1 -0
- package/dist/sanitize.d.ts +63 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +14 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/schema.d.ts +531 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +204 -0
- package/dist/schema.js.map +1 -0
- package/dist/telemetry/Telemetry.d.ts +36 -0
- package/dist/telemetry/Telemetry.d.ts.map +1 -0
- package/dist/telemetry/Telemetry.js +68 -0
- package/dist/telemetry/Telemetry.js.map +1 -0
- package/dist/telemetry/__tests__/Telemetry.test.d.ts +2 -0
- package/dist/telemetry/__tests__/Telemetry.test.d.ts.map +1 -0
- package/dist/transport/BaseTransport.d.ts +184 -0
- package/dist/transport/BaseTransport.d.ts.map +1 -0
- package/dist/transport/BaseTransport.js +200 -0
- package/dist/transport/BaseTransport.js.map +1 -0
- package/dist/transport/HttpHelpers.d.ts +60 -0
- package/dist/transport/HttpHelpers.d.ts.map +1 -0
- package/dist/transport/HttpHelpers.js +50 -0
- package/dist/transport/HttpHelpers.js.map +1 -0
- package/dist/transport/HttpTransport.d.ts +134 -0
- package/dist/transport/HttpTransport.d.ts.map +1 -0
- package/dist/transport/HttpTransport.js +175 -0
- package/dist/transport/HttpTransport.js.map +1 -0
- package/dist/transport/SseTransport.d.ts +133 -0
- package/dist/transport/SseTransport.d.ts.map +1 -0
- package/dist/transport/SseTransport.js +318 -0
- package/dist/transport/SseTransport.js.map +1 -0
- package/dist/transport/StreamableHttpTransport.d.ts +224 -0
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -0
- package/dist/transport/StreamableHttpTransport.js +407 -0
- package/dist/transport/StreamableHttpTransport.js.map +1 -0
- package/dist/types/disposable.d.ts +22 -0
- package/dist/types/disposable.d.ts.map +1 -0
- package/dist/types/disposable.js +1 -0
- package/dist/types/server-config.d.ts +32 -0
- package/dist/types/server-config.d.ts.map +1 -0
- package/dist/types/server-config.js +1 -0
- package/dist/types/skill.d.ts +69 -0
- package/dist/types/skill.d.ts.map +1 -0
- package/dist/types/skill.js +1 -0
- package/dist/types/tool.d.ts +68 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +1 -0
- package/dist/watchers/SkillWatcher.d.ts +132 -0
- package/dist/watchers/SkillWatcher.d.ts.map +1 -0
- package/dist/watchers/SkillWatcher.js +73 -0
- package/dist/watchers/SkillWatcher.js.map +1 -0
- package/dist/watchers/ToolWatcher.d.ts +109 -0
- package/dist/watchers/ToolWatcher.d.ts.map +1 -0
- package/dist/watchers/ToolWatcher.js +71 -0
- package/dist/watchers/ToolWatcher.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prometheus-compatible metrics collection.
|
|
3
|
+
*
|
|
4
|
+
* This module provides metrics collection and export in Prometheus text format.
|
|
5
|
+
* Supports counters, gauges, and histograms for observability.
|
|
6
|
+
*
|
|
7
|
+
* @module metrics
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Metric types supported by the metrics collector.
|
|
11
|
+
*/
|
|
12
|
+
export declare enum MetricType {
|
|
13
|
+
/** Counter - a cumulative metric that only increases */
|
|
14
|
+
Counter = "counter",
|
|
15
|
+
/** Gauge - a metric that can go up and down */
|
|
16
|
+
Gauge = "gauge",
|
|
17
|
+
/** Histogram - a metric for sampling observations */
|
|
18
|
+
Histogram = "histogram"
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A collected metric with its value and labels.
|
|
22
|
+
*/
|
|
23
|
+
export interface Metric {
|
|
24
|
+
/** Name of the metric */
|
|
25
|
+
name: string;
|
|
26
|
+
/** Type of metric (counter, gauge, histogram) */
|
|
27
|
+
type: MetricType;
|
|
28
|
+
/** Current value */
|
|
29
|
+
value: number;
|
|
30
|
+
/** Labels for the metric */
|
|
31
|
+
labels: Record<string, string>;
|
|
32
|
+
/** Help text describing the metric */
|
|
33
|
+
help?: string;
|
|
34
|
+
/** Timestamp when metric was recorded (Unix epoch) */
|
|
35
|
+
timestamp?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Prometheus-compatible metrics collector.
|
|
39
|
+
*
|
|
40
|
+
* Collects and exports metrics in Prometheus text format for scraping.
|
|
41
|
+
* Thread-safe and supports counters, gauges, and histograms.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* **Metric Types:**
|
|
45
|
+
* - **Counter**: Cumulative value that only increases (e.g., request counts)
|
|
46
|
+
* - **Gauge**: Value that can go up or down (e.g., active connections)
|
|
47
|
+
* - **Histogram**: Sampling observations (e.g., request latency)
|
|
48
|
+
*
|
|
49
|
+
* **Labels:**
|
|
50
|
+
* Metrics can have labels for dimensional data:
|
|
51
|
+
* ```typescript
|
|
52
|
+
* counter('http_requests_total', { method: 'GET', status: '200' });
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* **Export Format:**
|
|
56
|
+
* Metrics are exported in Prometheus text format:
|
|
57
|
+
* ```
|
|
58
|
+
* # HELP http_requests_total Total HTTP requests
|
|
59
|
+
* # TYPE http_requests_total counter
|
|
60
|
+
* http_requests_total{method="GET",status="200"} 1234
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const metrics = new Metrics({ prefix: 'mcp_server' });
|
|
66
|
+
*
|
|
67
|
+
* // Count requests
|
|
68
|
+
* metrics.counter('requests_total', { method: 'GET' }).inc();
|
|
69
|
+
*
|
|
70
|
+
* // Track active connections
|
|
71
|
+
* const activeConnections = metrics.gauge('active_connections');
|
|
72
|
+
* activeConnections.set(5);
|
|
73
|
+
* activeConnections.dec();
|
|
74
|
+
*
|
|
75
|
+
* // Record latency
|
|
76
|
+
* metrics.histogram('request_duration_seconds').observe(0.023);
|
|
77
|
+
*
|
|
78
|
+
* // Export for Prometheus
|
|
79
|
+
* const prometheusText = metrics.export();
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare class Metrics {
|
|
83
|
+
/** Metrics storage indexed by name and label hash */
|
|
84
|
+
private _metrics;
|
|
85
|
+
/** Histogram samples */
|
|
86
|
+
private _histograms;
|
|
87
|
+
/** Prefix for all metric names */
|
|
88
|
+
private _prefix;
|
|
89
|
+
/** Default labels to apply to all metrics */
|
|
90
|
+
private _defaultLabels;
|
|
91
|
+
/** Counter for metric collection operations */
|
|
92
|
+
private _operationsCounter;
|
|
93
|
+
/**
|
|
94
|
+
* Creates a new Metrics instance.
|
|
95
|
+
*
|
|
96
|
+
* @param options - Configuration options
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const metrics = new Metrics({ prefix: 'mcp_server' });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
constructor(options?: {
|
|
104
|
+
prefix?: string;
|
|
105
|
+
defaultLabels?: Record<string, string>;
|
|
106
|
+
});
|
|
107
|
+
/**
|
|
108
|
+
* Creates a counter metric.
|
|
109
|
+
*
|
|
110
|
+
* @param name - Metric name
|
|
111
|
+
* @param value - Increment value (default: 1)
|
|
112
|
+
* @param labels - Optional labels
|
|
113
|
+
* @param help - Help text
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* metrics.counter('requests_total', 1, { method: 'GET' });
|
|
118
|
+
* metrics.counter('errors_total', 1, { type: 'timeout' });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
counter(name: string, value?: number, labels?: Record<string, string>, help?: string): void;
|
|
122
|
+
/**
|
|
123
|
+
* Creates a gauge metric.
|
|
124
|
+
*
|
|
125
|
+
* @param name - Metric name
|
|
126
|
+
* @param value - Current value
|
|
127
|
+
* @param labels - Optional labels
|
|
128
|
+
* @param help - Help text
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const activeConnections = metrics.gauge('active_connections');
|
|
133
|
+
* activeConnections.set(5);
|
|
134
|
+
* activeConnections.dec();
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
gauge(name: string, value: number, labels?: Record<string, string>, help?: string): void;
|
|
138
|
+
/**
|
|
139
|
+
* Records a histogram observation.
|
|
140
|
+
*
|
|
141
|
+
* @param name - Histogram name
|
|
142
|
+
* @param value - Observed value
|
|
143
|
+
* @param labels - Optional labels
|
|
144
|
+
* @param help - Help text
|
|
145
|
+
* @param buckets - Custom bucket boundaries
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* metrics.histogram('request_duration_seconds').observe(0.023);
|
|
150
|
+
* metrics.histogram('thought_processing_ms').observe(45);
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
histogram(name: string, value: number, labels?: Record<string, string>, buckets?: number[]): void;
|
|
154
|
+
/**
|
|
155
|
+
* Gets the current value of a metric.
|
|
156
|
+
*
|
|
157
|
+
* @param name - Metric name
|
|
158
|
+
* @param labels - Labels
|
|
159
|
+
* @returns Current value or undefined if not found
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const count = metrics.get('requests_total', { method: 'GET' });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
get(name: string, labels?: Record<string, string>): number | undefined;
|
|
167
|
+
/**
|
|
168
|
+
* Increments a counter by 1.
|
|
169
|
+
*
|
|
170
|
+
* @param name - Metric name
|
|
171
|
+
* @param labels - Optional labels
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* metrics.inc('requests_total', { method: 'GET' });
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
inc(name: string, labels?: Record<string, string>): void;
|
|
179
|
+
/**
|
|
180
|
+
* Decrements a gauge by 1.
|
|
181
|
+
*
|
|
182
|
+
* @param name - Metric name
|
|
183
|
+
* @param labels - Optional labels
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* metrics.dec('active_connections');
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
dec(name: string, labels?: Record<string, string>): void;
|
|
191
|
+
/**
|
|
192
|
+
* Resets all metrics to zero.
|
|
193
|
+
* Useful for testing or on server restart.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* metrics.reset();
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
reset(): void;
|
|
201
|
+
/**
|
|
202
|
+
* Gets the number of metric operations performed.
|
|
203
|
+
* Useful for testing.
|
|
204
|
+
*
|
|
205
|
+
* @returns Operation count
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* const ops = metrics.getOperationCount();
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
getOperationCount(): number;
|
|
213
|
+
/**
|
|
214
|
+
* Exports metrics in Prometheus text format.
|
|
215
|
+
*
|
|
216
|
+
* @returns Prometheus text format string
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const prometheusText = metrics.export();
|
|
221
|
+
* console.log(prometheusText);
|
|
222
|
+
* // Output:
|
|
223
|
+
* // # HELP http_requests_total Total HTTP requests
|
|
224
|
+
* // # TYPE http_requests_total counter
|
|
225
|
+
* // http_requests_total{method="GET",status="200"} 1234
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export(): string;
|
|
229
|
+
/**
|
|
230
|
+
* Gets metric name with prefix.
|
|
231
|
+
* @param name - Metric name
|
|
232
|
+
* @returns Full metric name
|
|
233
|
+
* @private
|
|
234
|
+
*/
|
|
235
|
+
private _fullName;
|
|
236
|
+
/**
|
|
237
|
+
* Creates a unique key for a metric with labels.
|
|
238
|
+
* @param name - Metric name
|
|
239
|
+
* @param labels - Labels
|
|
240
|
+
* @returns Unique key
|
|
241
|
+
* @private
|
|
242
|
+
*/
|
|
243
|
+
private _metricKey;
|
|
244
|
+
/**
|
|
245
|
+
* Parses a metric key back into name and labels.
|
|
246
|
+
* @param key - Metric key
|
|
247
|
+
* @returns Name and labels
|
|
248
|
+
* @private
|
|
249
|
+
*/
|
|
250
|
+
private _parseMetricKey;
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=metrics.impl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.impl.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics.impl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,oBAAY,UAAU;IACrB,wDAAwD;IACxD,OAAO,YAAY;IAEnB,+CAA+C;IAC/C,KAAK,UAAU;IAEf,qDAAqD;IACrD,SAAS,cAAc;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACtB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb,iDAAiD;IACjD,IAAI,EAAE,UAAU,CAAC;IAEjB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IAEd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBAAa,OAAO;IACnB,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAsB;IAEtC,wBAAwB;IACxB,OAAO,CAAC,WAAW,CAA4E;IAE/F,kCAAkC;IAClC,OAAO,CAAC,OAAO,CAAS;IAExB,6CAA6C;IAC7C,OAAO,CAAC,cAAc,CAAyB;IAE/C,+CAA+C;IAC/C,OAAO,CAAC,kBAAkB,CAAa;IAEvC;;;;;;;;;OASG;gBACS,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAO;IAOrF;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAuB1F;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAe5F;;;;;;;;;;;;;;OAcG;IACH,SAAS,CACR,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACnC,OAAO,WAAkB,GACvB,IAAI;IAgCP;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,GAAG,SAAS;IAO1E;;;;;;;;;;OAUG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAIxD;;;;;;;;;;OAUG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKxD;;;;;;;;OAQG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;;;;;OAUG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;;;;;;;;;;;;;OAcG;IACH,MAAM,IAAI,MAAM;IAiEhB;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IASjB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAQlB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;CAyBvB"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
var metrics_impl_MetricType = /*#__PURE__*/ function(MetricType) {
|
|
2
|
+
MetricType["Counter"] = "counter";
|
|
3
|
+
MetricType["Gauge"] = "gauge";
|
|
4
|
+
MetricType["Histogram"] = "histogram";
|
|
5
|
+
return MetricType;
|
|
6
|
+
}({});
|
|
7
|
+
const DEFAULT_BUCKETS = [
|
|
8
|
+
0.005,
|
|
9
|
+
0.01,
|
|
10
|
+
0.025,
|
|
11
|
+
0.05,
|
|
12
|
+
0.1,
|
|
13
|
+
0.25,
|
|
14
|
+
0.5,
|
|
15
|
+
1,
|
|
16
|
+
2.5,
|
|
17
|
+
5,
|
|
18
|
+
10
|
|
19
|
+
];
|
|
20
|
+
class Metrics {
|
|
21
|
+
_metrics;
|
|
22
|
+
_histograms;
|
|
23
|
+
_prefix;
|
|
24
|
+
_defaultLabels;
|
|
25
|
+
_operationsCounter = 0;
|
|
26
|
+
constructor(options = {}){
|
|
27
|
+
this._metrics = new Map();
|
|
28
|
+
this._histograms = new Map();
|
|
29
|
+
this._prefix = options.prefix ?? '';
|
|
30
|
+
this._defaultLabels = options.defaultLabels ?? {};
|
|
31
|
+
}
|
|
32
|
+
counter(name, value = 1, labels = {}, help) {
|
|
33
|
+
const fullName = this._fullName(name);
|
|
34
|
+
const allLabels = {
|
|
35
|
+
...this._defaultLabels,
|
|
36
|
+
...labels
|
|
37
|
+
};
|
|
38
|
+
const key = this._metricKey(fullName, allLabels);
|
|
39
|
+
const existing = this._metrics.get(key);
|
|
40
|
+
if (existing) {
|
|
41
|
+
existing.value += value;
|
|
42
|
+
if (help && !existing.help) existing.help = help;
|
|
43
|
+
} else this._metrics.set(key, {
|
|
44
|
+
name: fullName,
|
|
45
|
+
type: "counter",
|
|
46
|
+
value,
|
|
47
|
+
labels: allLabels,
|
|
48
|
+
help
|
|
49
|
+
});
|
|
50
|
+
this._operationsCounter++;
|
|
51
|
+
}
|
|
52
|
+
gauge(name, value, labels = {}, help) {
|
|
53
|
+
const fullName = this._fullName(name);
|
|
54
|
+
const allLabels = {
|
|
55
|
+
...this._defaultLabels,
|
|
56
|
+
...labels
|
|
57
|
+
};
|
|
58
|
+
const key = this._metricKey(fullName, allLabels);
|
|
59
|
+
const existing = this._metrics.get(key);
|
|
60
|
+
this._metrics.set(key, {
|
|
61
|
+
name: fullName,
|
|
62
|
+
type: "gauge",
|
|
63
|
+
value,
|
|
64
|
+
labels: allLabels,
|
|
65
|
+
help: help ?? existing?.help
|
|
66
|
+
});
|
|
67
|
+
this._operationsCounter++;
|
|
68
|
+
}
|
|
69
|
+
histogram(name, value, labels = {}, buckets = DEFAULT_BUCKETS) {
|
|
70
|
+
const fullName = this._fullName(name);
|
|
71
|
+
const allLabels = {
|
|
72
|
+
...this._defaultLabels,
|
|
73
|
+
...labels
|
|
74
|
+
};
|
|
75
|
+
const key = this._metricKey(fullName, allLabels);
|
|
76
|
+
const histogram = this._histograms.get(key);
|
|
77
|
+
if (histogram) {
|
|
78
|
+
histogram.sum += value;
|
|
79
|
+
histogram.count += 1;
|
|
80
|
+
for (const boundary of buckets)if (value <= boundary) histogram.buckets.set(boundary, (histogram.buckets.get(boundary) ?? 0) + 1);
|
|
81
|
+
else histogram.buckets.set(boundary, histogram.buckets.get(boundary) ?? 0);
|
|
82
|
+
histogram.buckets.set(1 / 0, (histogram.buckets.get(1 / 0) ?? 0) + 1);
|
|
83
|
+
} else {
|
|
84
|
+
const histogramData = {
|
|
85
|
+
sum: value,
|
|
86
|
+
count: 1,
|
|
87
|
+
buckets: new Map()
|
|
88
|
+
};
|
|
89
|
+
for (const boundary of buckets)histogramData.buckets.set(boundary, value <= boundary ? 1 : 0);
|
|
90
|
+
histogramData.buckets.set(1 / 0, 1);
|
|
91
|
+
this._histograms.set(key, histogramData);
|
|
92
|
+
}
|
|
93
|
+
this._operationsCounter++;
|
|
94
|
+
}
|
|
95
|
+
get(name, labels = {}) {
|
|
96
|
+
const fullName = this._fullName(name);
|
|
97
|
+
const allLabels = {
|
|
98
|
+
...this._defaultLabels,
|
|
99
|
+
...labels
|
|
100
|
+
};
|
|
101
|
+
const key = this._metricKey(fullName, allLabels);
|
|
102
|
+
return this._metrics.get(key)?.value;
|
|
103
|
+
}
|
|
104
|
+
inc(name, labels) {
|
|
105
|
+
this.counter(name, 1, labels);
|
|
106
|
+
}
|
|
107
|
+
dec(name, labels) {
|
|
108
|
+
const value = this.get(name, labels) ?? 0;
|
|
109
|
+
this.gauge(name, value - 1, labels);
|
|
110
|
+
}
|
|
111
|
+
reset() {
|
|
112
|
+
this._metrics.clear();
|
|
113
|
+
this._histograms.clear();
|
|
114
|
+
this._operationsCounter = 0;
|
|
115
|
+
}
|
|
116
|
+
getOperationCount() {
|
|
117
|
+
return this._operationsCounter;
|
|
118
|
+
}
|
|
119
|
+
export() {
|
|
120
|
+
const lines = [];
|
|
121
|
+
const metrics = Array.from(this._metrics.values());
|
|
122
|
+
const histograms = Array.from(this._histograms.entries());
|
|
123
|
+
const helpEntries = new Map();
|
|
124
|
+
const typeEntries = new Map();
|
|
125
|
+
for (const metric of metrics){
|
|
126
|
+
if (!helpEntries.has(metric.name)) {
|
|
127
|
+
const helpText = metric.help ?? `${metric.name} metric`;
|
|
128
|
+
lines.push(`# HELP ${metric.name} ${helpText}`);
|
|
129
|
+
helpEntries.set(metric.name, helpText);
|
|
130
|
+
}
|
|
131
|
+
if (!typeEntries.has(metric.name)) {
|
|
132
|
+
lines.push(`# TYPE ${metric.name} ${metric.type}`);
|
|
133
|
+
typeEntries.set(metric.name, metric.type);
|
|
134
|
+
}
|
|
135
|
+
const labelStr = Object.entries(metric.labels).map(([k, v])=>`${k}="${v}"`).join(',');
|
|
136
|
+
lines.push(`${metric.name}{${labelStr}} ${metric.value}`);
|
|
137
|
+
}
|
|
138
|
+
for (const [key, histogram] of histograms){
|
|
139
|
+
const { name: fullName, labels } = this._parseMetricKey(key);
|
|
140
|
+
if (histogram.count > 0) {
|
|
141
|
+
if (!typeEntries.has(fullName)) {
|
|
142
|
+
lines.push(`# TYPE ${fullName} histogram`);
|
|
143
|
+
typeEntries.set(fullName, "histogram");
|
|
144
|
+
}
|
|
145
|
+
const labelStr = Object.entries(labels).map(([k, v])=>`${k}="${v}"`).join(',');
|
|
146
|
+
const formatMetricLine = (suffix, value)=>{
|
|
147
|
+
if (0 === labelStr.length) return `${fullName}${suffix} ${value}`;
|
|
148
|
+
return `${fullName}${suffix}{${labelStr}} ${value}`;
|
|
149
|
+
};
|
|
150
|
+
lines.push(formatMetricLine('_sum', histogram.sum));
|
|
151
|
+
lines.push(formatMetricLine('_count', histogram.count));
|
|
152
|
+
for (const [boundary, count] of histogram.buckets.entries()){
|
|
153
|
+
const boundaryLabel = boundary === 1 / 0 ? '+Inf' : Number.isFinite(boundary) ? String(boundary) : String(boundary);
|
|
154
|
+
const bucketLabels = 0 === labelStr.length ? `le="${boundaryLabel}"` : `${labelStr},le="${boundaryLabel}"`;
|
|
155
|
+
lines.push(`${fullName}_bucket{${bucketLabels}} ${count}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return lines.join('\n');
|
|
160
|
+
}
|
|
161
|
+
_fullName(name) {
|
|
162
|
+
if (!this._prefix) return name;
|
|
163
|
+
const prefix = `${this._prefix}_`;
|
|
164
|
+
return name.startsWith(prefix) ? name : `${prefix}${name}`;
|
|
165
|
+
}
|
|
166
|
+
_metricKey(name, labels) {
|
|
167
|
+
const sortedLabels = Object.entries(labels).sort(([a], [b])=>a.localeCompare(b)).map(([k, v])=>`${k}=${v}`).join(',');
|
|
168
|
+
return `${name}{${sortedLabels}}`;
|
|
169
|
+
}
|
|
170
|
+
_parseMetricKey(key) {
|
|
171
|
+
const match = key.match(/^([^{}]+)\{([^{}]*)\}$/);
|
|
172
|
+
if (!match) return {
|
|
173
|
+
name: key,
|
|
174
|
+
labels: {}
|
|
175
|
+
};
|
|
176
|
+
const [, name, labelsPart] = match;
|
|
177
|
+
if (!labelsPart) return {
|
|
178
|
+
name,
|
|
179
|
+
labels: {}
|
|
180
|
+
};
|
|
181
|
+
const labels = {};
|
|
182
|
+
for (const label of labelsPart.split(',')){
|
|
183
|
+
const separatorIndex = label.indexOf('=');
|
|
184
|
+
if (separatorIndex <= 0) continue;
|
|
185
|
+
const labelKey = label.slice(0, separatorIndex);
|
|
186
|
+
const labelValue = label.slice(separatorIndex + 1);
|
|
187
|
+
labels[labelKey] = labelValue;
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
name,
|
|
191
|
+
labels
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export { Metrics, metrics_impl_MetricType as MetricType };
|
|
196
|
+
|
|
197
|
+
//# sourceMappingURL=metrics.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics/metrics.impl.js","sources":["../../src/metrics/metrics.impl.ts"],"sourcesContent":["/**\n * Prometheus-compatible metrics collection.\n *\n * This module provides metrics collection and export in Prometheus text format.\n * Supports counters, gauges, and histograms for observability.\n *\n * @module metrics\n */\n\n/**\n * Metric types supported by the metrics collector.\n */\nexport enum MetricType {\n\t/** Counter - a cumulative metric that only increases */\n\tCounter = 'counter',\n\n\t/** Gauge - a metric that can go up and down */\n\tGauge = 'gauge',\n\n\t/** Histogram - a metric for sampling observations */\n\tHistogram = 'histogram',\n}\n\n/**\n * A collected metric with its value and labels.\n */\nexport interface Metric {\n\t/** Name of the metric */\n\tname: string;\n\n\t/** Type of metric (counter, gauge, histogram) */\n\ttype: MetricType;\n\n\t/** Current value */\n\tvalue: number;\n\n\t/** Labels for the metric */\n\tlabels: Record<string, string>;\n\n\t/** Help text describing the metric */\n\thelp?: string;\n\n\t/** Timestamp when metric was recorded (Unix epoch) */\n\ttimestamp?: number;\n}\n\n/**\n * Histogram bucket boundaries for latency tracking.\n */\nconst DEFAULT_BUCKETS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\n/**\n * Prometheus-compatible metrics collector.\n *\n * Collects and exports metrics in Prometheus text format for scraping.\n * Thread-safe and supports counters, gauges, and histograms.\n *\n * @remarks\n * **Metric Types:**\n * - **Counter**: Cumulative value that only increases (e.g., request counts)\n * - **Gauge**: Value that can go up or down (e.g., active connections)\n * - **Histogram**: Sampling observations (e.g., request latency)\n *\n * **Labels:**\n * Metrics can have labels for dimensional data:\n * ```typescript\n * counter('http_requests_total', { method: 'GET', status: '200' });\n * ```\n *\n * **Export Format:**\n * Metrics are exported in Prometheus text format:\n * ```\n * # HELP http_requests_total Total HTTP requests\n * # TYPE http_requests_total counter\n * http_requests_total{method=\"GET\",status=\"200\"} 1234\n * ```\n *\n * @example\n * ```typescript\n * const metrics = new Metrics({ prefix: 'mcp_server' });\n *\n * // Count requests\n * metrics.counter('requests_total', { method: 'GET' }).inc();\n *\n * // Track active connections\n * const activeConnections = metrics.gauge('active_connections');\n * activeConnections.set(5);\n * activeConnections.dec();\n *\n * // Record latency\n * metrics.histogram('request_duration_seconds').observe(0.023);\n *\n * // Export for Prometheus\n * const prometheusText = metrics.export();\n * ```\n */\nexport class Metrics {\n\t/** Metrics storage indexed by name and label hash */\n\tprivate _metrics: Map<string, Metric>;\n\n\t/** Histogram samples */\n\tprivate _histograms: Map<string, { sum: number; count: number; buckets: Map<number, number> }>;\n\n\t/** Prefix for all metric names */\n\tprivate _prefix: string;\n\n\t/** Default labels to apply to all metrics */\n\tprivate _defaultLabels: Record<string, string>;\n\n\t/** Counter for metric collection operations */\n\tprivate _operationsCounter: number = 0;\n\n\t/**\n\t * Creates a new Metrics instance.\n\t *\n\t * @param options - Configuration options\n\t *\n\t * @example\n\t * ```typescript\n\t * const metrics = new Metrics({ prefix: 'mcp_server' });\n\t * ```\n\t */\n\tconstructor(options: { prefix?: string; defaultLabels?: Record<string, string> } = {}) {\n\t\tthis._metrics = new Map();\n\t\tthis._histograms = new Map();\n\t\tthis._prefix = options.prefix ?? '';\n\t\tthis._defaultLabels = options.defaultLabels ?? {};\n\t}\n\n\t/**\n\t * Creates a counter metric.\n\t *\n\t * @param name - Metric name\n\t * @param value - Increment value (default: 1)\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.counter('requests_total', 1, { method: 'GET' });\n\t * metrics.counter('errors_total', 1, { type: 'timeout' });\n\t * ```\n\t */\n\tcounter(name: string, value = 1, labels: Record<string, string> = {}, help?: string): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst existing = this._metrics.get(key);\n\n\t\tif (existing) {\n\t\t\texisting.value += value;\n\t\t\tif (help && !existing.help) {\n\t\t\t\texisting.help = help;\n\t\t\t}\n\t\t} else {\n\t\t\tthis._metrics.set(key, {\n\t\t\t\tname: fullName,\n\t\t\t\ttype: MetricType.Counter,\n\t\t\t\tvalue,\n\t\t\t\tlabels: allLabels,\n\t\t\t\thelp,\n\t\t\t});\n\t\t}\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Creates a gauge metric.\n\t *\n\t * @param name - Metric name\n\t * @param value - Current value\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t *\n\t * @example\n\t * ```typescript\n\t * const activeConnections = metrics.gauge('active_connections');\n\t * activeConnections.set(5);\n\t * activeConnections.dec();\n\t * ```\n\t */\n\tgauge(name: string, value: number, labels: Record<string, string> = {}, help?: string): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst existing = this._metrics.get(key);\n\t\tthis._metrics.set(key, {\n\t\t\tname: fullName,\n\t\t\ttype: MetricType.Gauge,\n\t\t\tvalue,\n\t\t\tlabels: allLabels,\n\t\t\thelp: help ?? existing?.help,\n\t\t});\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Records a histogram observation.\n\t *\n\t * @param name - Histogram name\n\t * @param value - Observed value\n\t * @param labels - Optional labels\n\t * @param help - Help text\n\t * @param buckets - Custom bucket boundaries\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.histogram('request_duration_seconds').observe(0.023);\n\t * metrics.histogram('thought_processing_ms').observe(45);\n\t * ```\n\t */\n\thistogram(\n\t\tname: string,\n\t\tvalue: number,\n\t\tlabels: Record<string, string> = {},\n\t\tbuckets = DEFAULT_BUCKETS\n\t): void {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\tconst histogram = this._histograms.get(key);\n\n\t\tif (histogram) {\n\t\t\thistogram.sum += value;\n\t\t\thistogram.count += 1;\n\t\t\tfor (const boundary of buckets) {\n\t\t\t\tif (value <= boundary) {\n\t\t\t\t\thistogram.buckets.set(boundary, (histogram.buckets.get(boundary) ?? 0) + 1);\n\t\t\t\t} else {\n\t\t\t\t\thistogram.buckets.set(boundary, histogram.buckets.get(boundary) ?? 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\thistogram.buckets.set(Infinity, (histogram.buckets.get(Infinity) ?? 0) + 1);\n\t\t} else {\n\t\t\tconst histogramData = {\n\t\t\t\tsum: value,\n\t\t\t\tcount: 1,\n\t\t\t\tbuckets: new Map<number, number>(),\n\t\t\t};\n\t\t\tfor (const boundary of buckets) {\n\t\t\t\thistogramData.buckets.set(boundary, value <= boundary ? 1 : 0);\n\t\t\t}\n\t\t\thistogramData.buckets.set(Infinity, 1);\n\t\t\tthis._histograms.set(key, histogramData);\n\t\t}\n\t\tthis._operationsCounter++;\n\t}\n\n\t/**\n\t * Gets the current value of a metric.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Labels\n\t * @returns Current value or undefined if not found\n\t *\n\t * @example\n\t * ```typescript\n\t * const count = metrics.get('requests_total', { method: 'GET' });\n\t * ```\n\t */\n\tget(name: string, labels: Record<string, string> = {}): number | undefined {\n\t\tconst fullName = this._fullName(name);\n\t\tconst allLabels = { ...this._defaultLabels, ...labels };\n\t\tconst key = this._metricKey(fullName, allLabels);\n\t\treturn this._metrics.get(key)?.value;\n\t}\n\n\t/**\n\t * Increments a counter by 1.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Optional labels\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.inc('requests_total', { method: 'GET' });\n\t * ```\n\t */\n\tinc(name: string, labels?: Record<string, string>): void {\n\t\tthis.counter(name, 1, labels);\n\t}\n\n\t/**\n\t * Decrements a gauge by 1.\n\t *\n\t * @param name - Metric name\n\t * @param labels - Optional labels\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.dec('active_connections');\n\t * ```\n\t */\n\tdec(name: string, labels?: Record<string, string>): void {\n\t\tconst value = this.get(name, labels) ?? 0;\n\t\tthis.gauge(name, value - 1, labels);\n\t}\n\n\t/**\n\t * Resets all metrics to zero.\n\t * Useful for testing or on server restart.\n\t *\n\t * @example\n\t * ```typescript\n\t * metrics.reset();\n\t * ```\n\t */\n\treset(): void {\n\t\tthis._metrics.clear();\n\t\tthis._histograms.clear();\n\t\tthis._operationsCounter = 0;\n\t}\n\n\t/**\n\t * Gets the number of metric operations performed.\n\t * Useful for testing.\n\t *\n\t * @returns Operation count\n\t *\n\t * @example\n\t * ```typescript\n\t * const ops = metrics.getOperationCount();\n\t * ```\n\t */\n\tgetOperationCount(): number {\n\t\treturn this._operationsCounter;\n\t}\n\n\t/**\n\t * Exports metrics in Prometheus text format.\n\t *\n\t * @returns Prometheus text format string\n\t *\n\t * @example\n\t * ```typescript\n\t * const prometheusText = metrics.export();\n\t * console.log(prometheusText);\n\t * // Output:\n\t * // # HELP http_requests_total Total HTTP requests\n\t * // # TYPE http_requests_total counter\n\t * // http_requests_total{method=\"GET\",status=\"200\"} 1234\n\t * ```\n\t */\n\texport(): string {\n\t\tconst lines: string[] = [];\n\n\t\tconst metrics = Array.from(this._metrics.values());\n\t\tconst histograms = Array.from(this._histograms.entries());\n\n\t\tconst helpEntries = new Map<string, string>();\n\t\tconst typeEntries = new Map<string, MetricType>();\n\n\t\tfor (const metric of metrics) {\n\t\t\tif (!helpEntries.has(metric.name)) {\n\t\t\t\tconst helpText = metric.help ?? `${metric.name} metric`;\n\t\t\t\tlines.push(`# HELP ${metric.name} ${helpText}`);\n\t\t\t\thelpEntries.set(metric.name, helpText);\n\t\t\t}\n\t\t\tif (!typeEntries.has(metric.name)) {\n\t\t\t\tlines.push(`# TYPE ${metric.name} ${metric.type}`);\n\t\t\t\ttypeEntries.set(metric.name, metric.type);\n\t\t\t}\n\n\t\t\tconst labelStr = Object.entries(metric.labels)\n\t\t\t\t.map(([k, v]) => `${k}=\"${v}\"`)\n\t\t\t\t.join(',');\n\t\t\tlines.push(`${metric.name}{${labelStr}} ${metric.value}`);\n\t\t}\n\n\t\tfor (const [key, histogram] of histograms) {\n\t\t\tconst { name: fullName, labels } = this._parseMetricKey(key);\n\t\t\tif (histogram.count > 0) {\n\t\t\t\tif (!typeEntries.has(fullName)) {\n\t\t\t\t\tlines.push(`# TYPE ${fullName} histogram`);\n\t\t\t\t\ttypeEntries.set(fullName, MetricType.Histogram);\n\t\t\t\t}\n\n\t\t\t\tconst labelStr = Object.entries(labels)\n\t\t\t\t\t.map(([k, v]) => `${k}=\"${v}\"`)\n\t\t\t\t\t.join(',');\n\t\t\t\tconst formatMetricLine = (suffix: string, value: number): string => {\n\t\t\t\t\tif (labelStr.length === 0) {\n\t\t\t\t\t\treturn `${fullName}${suffix} ${value}`;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn `${fullName}${suffix}{${labelStr}} ${value}`;\n\t\t\t\t};\n\n\t\t\t\tlines.push(formatMetricLine('_sum', histogram.sum));\n\t\t\t\tlines.push(formatMetricLine('_count', histogram.count));\n\n\t\t\t\tfor (const [boundary, count] of histogram.buckets.entries()) {\n\t\t\t\t\tconst boundaryLabel =\n\t\t\t\t\t\tboundary === Infinity\n\t\t\t\t\t\t\t? '+Inf'\n\t\t\t\t\t\t\t: Number.isFinite(boundary)\n\t\t\t\t\t\t\t\t? String(boundary)\n\t\t\t\t\t\t\t\t: String(boundary);\n\t\t\t\t\tconst bucketLabels =\n\t\t\t\t\t\tlabelStr.length === 0 ? `le=\"${boundaryLabel}\"` : `${labelStr},le=\"${boundaryLabel}\"`;\n\t\t\t\t\tlines.push(`${fullName}_bucket{${bucketLabels}} ${count}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join('\\n');\n\t}\n\n\t/**\n\t * Gets metric name with prefix.\n\t * @param name - Metric name\n\t * @returns Full metric name\n\t * @private\n\t */\n\tprivate _fullName(name: string): string {\n\t\tif (!this._prefix) {\n\t\t\treturn name;\n\t\t}\n\n\t\tconst prefix = `${this._prefix}_`;\n\t\treturn name.startsWith(prefix) ? name : `${prefix}${name}`;\n\t}\n\n\t/**\n\t * Creates a unique key for a metric with labels.\n\t * @param name - Metric name\n\t * @param labels - Labels\n\t * @returns Unique key\n\t * @private\n\t */\n\tprivate _metricKey(name: string, labels: Record<string, string>): string {\n\t\tconst sortedLabels = Object.entries(labels)\n\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t.map(([k, v]) => `${k}=${v}`)\n\t\t\t.join(',');\n\t\treturn `${name}{${sortedLabels}}`;\n\t}\n\n\t/**\n\t * Parses a metric key back into name and labels.\n\t * @param key - Metric key\n\t * @returns Name and labels\n\t * @private\n\t */\n\tprivate _parseMetricKey(key: string): { name: string; labels: Record<string, string> } {\n\t\tconst match = key.match(/^([^{}]+)\\{([^{}]*)\\}$/);\n\t\tif (!match) {\n\t\t\treturn { name: key, labels: {} };\n\t\t}\n\n\t\tconst [, name, labelsPart] = match as [string, string, string | undefined];\n\t\tif (!labelsPart) {\n\t\t\treturn { name, labels: {} };\n\t\t}\n\n\t\tconst labels: Record<string, string> = {};\n\t\tfor (const label of labelsPart.split(',')) {\n\t\t\tconst separatorIndex = label.indexOf('=');\n\t\t\tif (separatorIndex <= 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst labelKey = label.slice(0, separatorIndex);\n\t\t\tconst labelValue = label.slice(separatorIndex + 1);\n\t\t\tlabels[labelKey] = labelValue;\n\t\t}\n\n\t\treturn { name, labels };\n\t}\n}\n"],"names":["MetricType","DEFAULT_BUCKETS","Metrics","options","Map","name","value","labels","help","fullName","allLabels","key","existing","buckets","histogram","boundary","Infinity","histogramData","lines","metrics","Array","histograms","helpEntries","typeEntries","metric","helpText","labelStr","Object","k","v","formatMetricLine","suffix","count","boundaryLabel","Number","String","bucketLabels","prefix","sortedLabels","a","b","match","labelsPart","label","separatorIndex","labelKey","labelValue"],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { IMetrics } from '../contracts/index.js';
|
|
2
|
+
import type { ThoughtData } from '../core/thought.js';
|
|
3
|
+
import type { PersistenceBackend, PersistenceConfig } from './PersistenceBackend.js';
|
|
4
|
+
/**
|
|
5
|
+
* File-based persistence backend using JSON files.
|
|
6
|
+
*
|
|
7
|
+
* Stores thoughts and branches as JSON files in a configured directory.
|
|
8
|
+
* Simple and reliable, with no external dependencies.
|
|
9
|
+
*
|
|
10
|
+
* File structure:
|
|
11
|
+
* ```
|
|
12
|
+
* dataDir/
|
|
13
|
+
* history.json # Main thought history
|
|
14
|
+
* branches/
|
|
15
|
+
* <branch-id>.json # Individual branch files
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare class FilePersistence implements PersistenceBackend {
|
|
19
|
+
private _dataDir;
|
|
20
|
+
private _historyPath;
|
|
21
|
+
private _branchesDir;
|
|
22
|
+
private _maxHistorySize;
|
|
23
|
+
private _persistBranches;
|
|
24
|
+
private _metrics?;
|
|
25
|
+
constructor(options?: PersistenceConfig['options'] & {
|
|
26
|
+
metrics?: IMetrics;
|
|
27
|
+
});
|
|
28
|
+
private _recordOperationDuration;
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the persistence directory structure.
|
|
31
|
+
*/
|
|
32
|
+
private _ensureDirectories;
|
|
33
|
+
/**
|
|
34
|
+
* Validates branch ID format and resolves the path safely.
|
|
35
|
+
*
|
|
36
|
+
* This method provides defense-in-depth security by:
|
|
37
|
+
* 1. Validating the branch ID format (alphanumeric, hyphens, underscores only)
|
|
38
|
+
* 2. Preventing path traversal attacks
|
|
39
|
+
*
|
|
40
|
+
* @param branchId - The branch ID to validate and resolve
|
|
41
|
+
* @returns The safe, resolved branch file path
|
|
42
|
+
* @throws Error if branch ID is invalid or path traversal is detected
|
|
43
|
+
*/
|
|
44
|
+
private _safeBranchPath;
|
|
45
|
+
saveThought(thought: ThoughtData): Promise<void>;
|
|
46
|
+
loadHistory(): Promise<ThoughtData[]>;
|
|
47
|
+
saveBranch(branchId: string, thoughts: ThoughtData[]): Promise<void>;
|
|
48
|
+
loadBranch(branchId: string): Promise<ThoughtData[] | undefined>;
|
|
49
|
+
listBranches(): Promise<string[]>;
|
|
50
|
+
clear(): Promise<void>;
|
|
51
|
+
healthy(): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Get the data directory path.
|
|
54
|
+
*/
|
|
55
|
+
getDataDir(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Get all branch IDs that are persisted.
|
|
58
|
+
*/
|
|
59
|
+
getBranchIds(): Promise<string[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Close the backend and release resources.
|
|
62
|
+
* No resources to release for file backend.
|
|
63
|
+
*/
|
|
64
|
+
close(): Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=FilePersistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/FilePersistence.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAErF;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAgB,YAAW,kBAAkB;IACzD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,CAAW;gBAEhB,OAAO,CAAC,EAAE,iBAAiB,CAAC,SAAS,CAAC,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,CAAA;KAAE;IAa3E,OAAO,CAAC,wBAAwB;IAKhC;;OAEG;YACW,kBAAkB;IAShC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,eAAe;IAoBV,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBhD,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAoBrC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC;IA0BhE,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBtB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IASxC;;OAEG;IACI,UAAU,IAAI,MAAM;IAI3B;;OAEG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAa9C;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAGnC"}
|