@geekmidas/telescope 1.1.1 → 10.0.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/README.md +14 -4
- package/dist/{hono-Bz9PQQzj.mjs → hono-Bw-ey6CT.mjs} +2 -2
- package/dist/{hono-Bz9PQQzj.mjs.map → hono-Bw-ey6CT.mjs.map} +1 -1
- package/dist/{hono-Z_JIICmt.cjs → hono-CPHX7FAm.cjs} +2 -2
- package/dist/{hono-Z_JIICmt.cjs.map → hono-CPHX7FAm.cjs.map} +1 -1
- package/dist/{http-Crsriv32.mjs → http-BIvr0YdI.mjs} +1 -1
- package/dist/{http-Crsriv32.mjs.map → http-BIvr0YdI.mjs.map} +1 -1
- package/dist/{http-JycFRfSe.cjs → http-BsqmhurZ.cjs} +1 -1
- package/dist/{http-JycFRfSe.cjs.map → http-BsqmhurZ.cjs.map} +1 -1
- package/dist/{http-D5kn3_Mt.d.mts → http-DULM1u2L.d.cts} +3 -3
- package/dist/{http-D5kn3_Mt.d.mts.map → http-DULM1u2L.d.cts.map} +1 -1
- package/dist/{http-Dvca6fC3.d.cts → http-GB-Nlvwc.d.mts} +3 -3
- package/dist/{http-Dvca6fC3.d.cts.map → http-GB-Nlvwc.d.mts.map} +1 -1
- package/dist/instrumentation/hono.cjs +2 -2
- package/dist/instrumentation/hono.mjs +2 -2
- package/dist/instrumentation/http.cjs +1 -1
- package/dist/instrumentation/http.d.cts +1 -1
- package/dist/instrumentation/http.d.mts +1 -1
- package/dist/instrumentation/http.mjs +1 -1
- package/dist/instrumentation/index.cjs +5 -5
- package/dist/instrumentation/index.d.cts +3 -3
- package/dist/instrumentation/index.d.mts +3 -3
- package/dist/instrumentation/index.mjs +5 -5
- package/dist/instrumentation/middleware.cjs +2 -2
- package/dist/instrumentation/middleware.d.cts +1 -1
- package/dist/instrumentation/middleware.d.mts +1 -1
- package/dist/instrumentation/middleware.mjs +2 -2
- package/dist/instrumentation/otel.cjs +2 -2
- package/dist/instrumentation/otel.d.cts +1 -1
- package/dist/instrumentation/otel.d.mts +1 -1
- package/dist/instrumentation/otel.mjs +2 -2
- package/dist/instrumentation/setup.cjs +1 -1
- package/dist/instrumentation/setup.mjs +1 -1
- package/dist/logger/console.d.cts.map +1 -1
- package/dist/{middleware-D3v5SnSs.cjs → middleware-Bcq6XXGG.cjs} +3 -3
- package/dist/middleware-Bcq6XXGG.cjs.map +1 -0
- package/dist/{middleware-Dy1ctr2N.mjs → middleware-D1XEHvyy.mjs} +3 -3
- package/dist/middleware-D1XEHvyy.mjs.map +1 -0
- package/dist/{middleware-CA84nsNN.d.cts → middleware-PeyS-9Ny.d.cts} +2 -2
- package/dist/{middleware-CA84nsNN.d.cts.map → middleware-PeyS-9Ny.d.cts.map} +1 -1
- package/dist/{middleware-DAceVpfw.d.mts → middleware-oHvo_ZgU.d.mts} +2 -2
- package/dist/{middleware-DAceVpfw.d.mts.map → middleware-oHvo_ZgU.d.mts.map} +1 -1
- package/dist/{otel-DPKNyJ0t.mjs → otel-B9bNoeZ2.mjs} +4 -4
- package/dist/otel-B9bNoeZ2.mjs.map +1 -0
- package/dist/{otel-1bJPb2Z7.d.mts → otel-Bk89b1lX.d.cts} +3 -3
- package/dist/{otel-1bJPb2Z7.d.mts.map → otel-Bk89b1lX.d.cts.map} +1 -1
- package/dist/{otel-DuiBeBPU.cjs → otel-BzjOtVxZ.cjs} +4 -4
- package/dist/otel-BzjOtVxZ.cjs.map +1 -0
- package/dist/{otel-SBVoVEHr.d.cts → otel-lPMsM26e.d.mts} +3 -3
- package/dist/{otel-SBVoVEHr.d.cts.map → otel-lPMsM26e.d.mts.map} +1 -1
- package/dist/otlp/hono.cjs +3 -3
- package/dist/otlp/hono.mjs +3 -3
- package/dist/otlp/index.cjs +3 -3
- package/dist/otlp/index.mjs +3 -3
- package/dist/otlp/receiver.cjs +3 -3
- package/dist/otlp/receiver.mjs +3 -3
- package/dist/otlp/transformer.cjs +2 -2
- package/dist/otlp/transformer.mjs +2 -2
- package/dist/otlp/types.cjs +1 -1
- package/dist/otlp/types.mjs +1 -1
- package/dist/{receiver-q4f7eirs.mjs → receiver-D46dfkYI.mjs} +2 -2
- package/dist/{receiver-q4f7eirs.mjs.map → receiver-D46dfkYI.mjs.map} +1 -1
- package/dist/{receiver-BW_4go_X.cjs → receiver-slCoAFat.cjs} +2 -2
- package/dist/{receiver-BW_4go_X.cjs.map → receiver-slCoAFat.cjs.map} +1 -1
- package/dist/{setup-BhCp2LUp.mjs → setup-DC9JMEYZ.mjs} +1 -1
- package/dist/{setup-BhCp2LUp.mjs.map → setup-DC9JMEYZ.mjs.map} +1 -1
- package/dist/{setup-_uT4L_x5.cjs → setup-DufxQpi9.cjs} +1 -1
- package/dist/{setup-_uT4L_x5.cjs.map → setup-DufxQpi9.cjs.map} +1 -1
- package/dist/storage/kysely.cjs +48 -38
- package/dist/storage/kysely.cjs.map +1 -1
- package/dist/storage/kysely.d.cts +29 -9
- package/dist/storage/kysely.d.cts.map +1 -1
- package/dist/storage/kysely.d.mts +29 -9
- package/dist/storage/kysely.d.mts.map +1 -1
- package/dist/storage/kysely.mjs +48 -38
- package/dist/storage/kysely.mjs.map +1 -1
- package/dist/tracing-BX8uY2nR.d.cts.map +1 -1
- package/dist/tracing-PnECEbEu.d.mts.map +1 -1
- package/dist/{transformer-CFrJQkUg.mjs → transformer-CFQ4WFk6.mjs} +2 -2
- package/dist/{transformer-CFrJQkUg.mjs.map → transformer-CFQ4WFk6.mjs.map} +1 -1
- package/dist/{transformer-DvDYyFRQ.cjs → transformer-Csl6fbgv.cjs} +2 -2
- package/dist/{transformer-DvDYyFRQ.cjs.map → transformer-Csl6fbgv.cjs.map} +1 -1
- package/dist/types-B1EIa_cQ.d.mts.map +1 -1
- package/dist/{types-BBeTDpHr.cjs → types-BMiHgsi4.cjs} +1 -1
- package/dist/{types-BBeTDpHr.cjs.map → types-BMiHgsi4.cjs.map} +1 -1
- package/dist/{types-CXYLhG_G.mjs → types-Cj59nqy7.mjs} +1 -1
- package/dist/{types-CXYLhG_G.mjs.map → types-Cj59nqy7.mjs.map} +1 -1
- package/dist/types-l7Rlb5Mg.d.cts.map +1 -1
- package/package.json +6 -3
- package/CHANGELOG.md +0 -51
- package/dist/middleware-D3v5SnSs.cjs.map +0 -1
- package/dist/middleware-Dy1ctr2N.mjs.map +0 -1
- package/dist/otel-DPKNyJ0t.mjs.map +0 -1
- package/dist/otel-DuiBeBPU.cjs.map +0 -1
- package/src/Telescope.ts +0 -561
- package/src/__tests__/Telescope.spec.ts +0 -438
- package/src/__tests__/pino-transport.spec.ts +0 -115
- package/src/__tests__/redact.spec.ts +0 -336
- package/src/adapters/__tests__/lambda.spec.ts +0 -318
- package/src/adapters/__tests__/middy.spec.ts +0 -741
- package/src/adapters/index.ts +0 -22
- package/src/adapters/lambda.ts +0 -432
- package/src/adapters/middy.ts +0 -402
- package/src/adapters/types.ts +0 -181
- package/src/core.ts +0 -51
- package/src/index.ts +0 -34
- package/src/instrumentation/__tests__/core.spec.ts +0 -248
- package/src/instrumentation/__tests__/hono.spec.ts +0 -348
- package/src/instrumentation/__tests__/middleware.spec.ts +0 -528
- package/src/instrumentation/__tests__/otel.spec.ts +0 -291
- package/src/instrumentation/__tests__/tracing.spec.ts +0 -208
- package/src/instrumentation/core.ts +0 -228
- package/src/instrumentation/hono.ts +0 -270
- package/src/instrumentation/http.ts +0 -306
- package/src/instrumentation/index.ts +0 -90
- package/src/instrumentation/middleware.ts +0 -297
- package/src/instrumentation/otel.ts +0 -271
- package/src/instrumentation/setup.ts +0 -246
- package/src/instrumentation/tracing.ts +0 -145
- package/src/logger/__tests__/console.spec.ts +0 -366
- package/src/logger/__tests__/pino.spec.ts +0 -217
- package/src/logger/console.ts +0 -230
- package/src/logger/pino.ts +0 -201
- package/src/metrics/MetricsAggregator.ts +0 -555
- package/src/metrics/__tests__/MetricsAggregator.spec.ts +0 -298
- package/src/metrics/index.ts +0 -2
- package/src/metrics/storage/InMemoryMetricsStorage.ts +0 -380
- package/src/metrics/storage/MetricsStorage.ts +0 -74
- package/src/metrics/storage/index.ts +0 -3
- package/src/metrics/storage/types.ts +0 -243
- package/src/otlp/__tests__/receiver.spec.ts +0 -367
- package/src/otlp/__tests__/transformer.spec.ts +0 -455
- package/src/otlp/hono.ts +0 -120
- package/src/otlp/index.ts +0 -22
- package/src/otlp/receiver.ts +0 -162
- package/src/otlp/transformer.ts +0 -367
- package/src/otlp/types.ts +0 -364
- package/src/redact.ts +0 -116
- package/src/server/__tests__/hono.spec.ts +0 -814
- package/src/server/hono.ts +0 -442
- package/src/storage/__tests__/kysely.spec.ts +0 -715
- package/src/storage/__tests__/memory.spec.ts +0 -694
- package/src/storage/kysely.ts +0 -599
- package/src/storage/memory.ts +0 -204
- package/src/types.ts +0 -447
- package/src/ui-assets.ts +0 -40
- package/tsconfig.json +0 -9
- package/ui/CHANGELOG.md +0 -7
- package/ui/index.html +0 -12
- package/ui/node_modules/.bin/tsc +0 -21
- package/ui/node_modules/.bin/tsserver +0 -21
- package/ui/node_modules/.bin/vite +0 -21
- package/ui/package.json +0 -24
- package/ui/src/App.tsx +0 -595
- package/ui/src/api.ts +0 -88
- package/ui/src/components/ExceptionDetail.tsx +0 -100
- package/ui/src/components/FilterBar.tsx +0 -162
- package/ui/src/components/LogDetail.tsx +0 -91
- package/ui/src/components/RequestDetail.tsx +0 -143
- package/ui/src/main.tsx +0 -10
- package/ui/src/styles.css +0 -11
- package/ui/src/types.ts +0 -63
- package/ui/src/vite-env.d.ts +0 -1
- package/ui/src/vite-plugin-gkm-config.ts +0 -54
- package/ui/tsconfig.json +0 -20
- package/ui/tsconfig.tsbuildinfo +0 -1
- package/ui/vite.config.ts +0 -13
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
MetricBucket,
|
|
3
|
-
MetricPoint,
|
|
4
|
-
MetricQuery,
|
|
5
|
-
MetricResult,
|
|
6
|
-
MetricsStorageConfig,
|
|
7
|
-
PartitionInfo,
|
|
8
|
-
RollupOptions,
|
|
9
|
-
} from './types';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Interface for metrics storage backends.
|
|
13
|
-
*
|
|
14
|
-
* Implementations can use different storage technologies:
|
|
15
|
-
* - In-memory (development/testing)
|
|
16
|
-
* - PostgreSQL with TimescaleDB
|
|
17
|
-
* - ClickHouse
|
|
18
|
-
* - InfluxDB
|
|
19
|
-
*/
|
|
20
|
-
export interface MetricsStorage {
|
|
21
|
-
/**
|
|
22
|
-
* Write raw metric points to storage.
|
|
23
|
-
* Points are typically buffered and flushed in batches.
|
|
24
|
-
*/
|
|
25
|
-
write(points: MetricPoint[]): Promise<void>;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Query metrics with aggregation.
|
|
29
|
-
* Returns time series data with statistics.
|
|
30
|
-
*/
|
|
31
|
-
query(query: MetricQuery): Promise<MetricResult[]>;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get a single aggregated bucket for a specific time range.
|
|
35
|
-
* Useful for dashboards showing current values.
|
|
36
|
-
*/
|
|
37
|
-
getBucket(
|
|
38
|
-
projectId: string,
|
|
39
|
-
name: string,
|
|
40
|
-
bucket: Date,
|
|
41
|
-
): Promise<MetricBucket | null>;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Roll up data from one tier to another.
|
|
45
|
-
* Aggregates fine-grained data into coarser buckets.
|
|
46
|
-
*/
|
|
47
|
-
rollup(options: RollupOptions): Promise<number>;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Prune old data based on retention policies.
|
|
51
|
-
* Returns the number of records deleted.
|
|
52
|
-
*/
|
|
53
|
-
prune(): Promise<number>;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* List partitions for management and monitoring.
|
|
57
|
-
*/
|
|
58
|
-
listPartitions(tier?: string): Promise<PartitionInfo[]>;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Get storage configuration.
|
|
62
|
-
*/
|
|
63
|
-
getConfig(): MetricsStorageConfig;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Flush any buffered data to storage.
|
|
67
|
-
*/
|
|
68
|
-
flush(): Promise<void>;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Close the storage connection and clean up resources.
|
|
72
|
-
*/
|
|
73
|
-
close(): Promise<void>;
|
|
74
|
-
}
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Metric types supported by the storage system
|
|
3
|
-
*/
|
|
4
|
-
export type MetricType = 'counter' | 'gauge' | 'histogram';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Labels/dimensions for metric filtering and grouping
|
|
8
|
-
*/
|
|
9
|
-
export type MetricLabels = Record<string, string>;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* A single metric data point
|
|
13
|
-
*/
|
|
14
|
-
export interface MetricPoint {
|
|
15
|
-
/** Timestamp of the metric */
|
|
16
|
-
timestamp: Date;
|
|
17
|
-
/** Project/app identifier for multi-tenant isolation */
|
|
18
|
-
projectId: string;
|
|
19
|
-
/** Service name (e.g., 'api', 'worker', 'cron') */
|
|
20
|
-
service: string;
|
|
21
|
-
/** Environment (e.g., 'development', 'staging', 'production') */
|
|
22
|
-
environment: string;
|
|
23
|
-
/** Metric name (e.g., 'http.request.duration', 'orders.created') */
|
|
24
|
-
name: string;
|
|
25
|
-
/** Metric type */
|
|
26
|
-
type: MetricType;
|
|
27
|
-
/** Numeric value */
|
|
28
|
-
value: number;
|
|
29
|
-
/** Dimensions for filtering/grouping */
|
|
30
|
-
labels: MetricLabels;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Aggregated metric bucket (pre-computed for efficient queries)
|
|
35
|
-
*/
|
|
36
|
-
export interface MetricBucket {
|
|
37
|
-
/** Bucket start timestamp */
|
|
38
|
-
bucket: Date;
|
|
39
|
-
/** Project identifier */
|
|
40
|
-
projectId: string;
|
|
41
|
-
/** Service name */
|
|
42
|
-
service: string;
|
|
43
|
-
/** Environment */
|
|
44
|
-
environment: string;
|
|
45
|
-
/** Metric name */
|
|
46
|
-
name: string;
|
|
47
|
-
/** Hash of labels for grouping */
|
|
48
|
-
labelsHash: string;
|
|
49
|
-
/** Original labels */
|
|
50
|
-
labels: MetricLabels;
|
|
51
|
-
/** Number of data points in bucket */
|
|
52
|
-
count: number;
|
|
53
|
-
/** Sum of values */
|
|
54
|
-
sum: number;
|
|
55
|
-
/** Minimum value */
|
|
56
|
-
min: number;
|
|
57
|
-
/** Maximum value */
|
|
58
|
-
max: number;
|
|
59
|
-
/** T-Digest sketch for percentile calculations (serialized) */
|
|
60
|
-
sketch?: TDigestData;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Serialized T-Digest data structure for percentile calculations
|
|
65
|
-
* Stores centroids (mean, weight) that can be merged across buckets
|
|
66
|
-
*/
|
|
67
|
-
export interface TDigestData {
|
|
68
|
-
/** Centroids: [mean, weight][] */
|
|
69
|
-
centroids: [number, number][];
|
|
70
|
-
/** Compression factor (higher = more accuracy, more memory) */
|
|
71
|
-
compression: number;
|
|
72
|
-
/** Total count of values */
|
|
73
|
-
count: number;
|
|
74
|
-
/** Minimum value seen */
|
|
75
|
-
min: number;
|
|
76
|
-
/** Maximum value seen */
|
|
77
|
-
max: number;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Time range for queries
|
|
82
|
-
*/
|
|
83
|
-
export interface TimeRange {
|
|
84
|
-
start: Date;
|
|
85
|
-
end: Date;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Aggregation granularity
|
|
90
|
-
*/
|
|
91
|
-
export type AggregationInterval = '1m' | '5m' | '15m' | '1h' | '6h' | '1d';
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Query parameters for retrieving metrics
|
|
95
|
-
*/
|
|
96
|
-
export interface MetricQuery {
|
|
97
|
-
/** Project filter (required for multi-tenant) */
|
|
98
|
-
projectId: string;
|
|
99
|
-
/** Optional service filter */
|
|
100
|
-
service?: string;
|
|
101
|
-
/** Optional environment filter */
|
|
102
|
-
environment?: string;
|
|
103
|
-
/** Metric name pattern (supports wildcards like 'http.*') */
|
|
104
|
-
name?: string;
|
|
105
|
-
/** Label filters */
|
|
106
|
-
labels?: MetricLabels;
|
|
107
|
-
/** Time range */
|
|
108
|
-
range: TimeRange;
|
|
109
|
-
/** Aggregation interval */
|
|
110
|
-
interval?: AggregationInterval;
|
|
111
|
-
/** Group by these label keys */
|
|
112
|
-
groupBy?: string[];
|
|
113
|
-
/** Maximum number of results */
|
|
114
|
-
limit?: number;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Query result with aggregated values
|
|
119
|
-
*/
|
|
120
|
-
export interface MetricResult {
|
|
121
|
-
/** Metric name */
|
|
122
|
-
name: string;
|
|
123
|
-
/** Labels (grouped by keys if specified) */
|
|
124
|
-
labels: MetricLabels;
|
|
125
|
-
/** Time series data points */
|
|
126
|
-
timeSeries: MetricTimeSeriesPoint[];
|
|
127
|
-
/** Overall statistics for the query range */
|
|
128
|
-
stats: {
|
|
129
|
-
count: number;
|
|
130
|
-
sum: number;
|
|
131
|
-
avg: number;
|
|
132
|
-
min: number;
|
|
133
|
-
max: number;
|
|
134
|
-
p50: number;
|
|
135
|
-
p95: number;
|
|
136
|
-
p99: number;
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Single point in a time series result
|
|
142
|
-
*/
|
|
143
|
-
export interface MetricTimeSeriesPoint {
|
|
144
|
-
timestamp: Date;
|
|
145
|
-
count: number;
|
|
146
|
-
sum: number;
|
|
147
|
-
avg: number;
|
|
148
|
-
min: number;
|
|
149
|
-
max: number;
|
|
150
|
-
p50?: number;
|
|
151
|
-
p95?: number;
|
|
152
|
-
p99?: number;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Storage tier configuration
|
|
157
|
-
*/
|
|
158
|
-
export interface StorageTier {
|
|
159
|
-
/** Table/collection name for this tier */
|
|
160
|
-
name: string;
|
|
161
|
-
/** Bucket interval for aggregation */
|
|
162
|
-
interval: AggregationInterval;
|
|
163
|
-
/** Retention duration in milliseconds (0 = forever) */
|
|
164
|
-
retention: number;
|
|
165
|
-
/** Partition interval for efficient pruning */
|
|
166
|
-
partitionInterval: 'hourly' | 'daily' | 'weekly' | 'monthly';
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Metrics storage configuration
|
|
171
|
-
*/
|
|
172
|
-
export interface MetricsStorageConfig {
|
|
173
|
-
/** Storage tiers (raw, minute, hourly, etc.) */
|
|
174
|
-
tiers: StorageTier[];
|
|
175
|
-
/** Flush interval in milliseconds */
|
|
176
|
-
flushInterval: number;
|
|
177
|
-
/** Maximum batch size for writes */
|
|
178
|
-
maxBatchSize: number;
|
|
179
|
-
/** Enable automatic rollup between tiers */
|
|
180
|
-
autoRollup: boolean;
|
|
181
|
-
/** T-Digest compression factor (default: 100) */
|
|
182
|
-
tdigestCompression: number;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Default configuration with hybrid storage strategy
|
|
187
|
-
*/
|
|
188
|
-
export const DEFAULT_METRICS_CONFIG: MetricsStorageConfig = {
|
|
189
|
-
tiers: [
|
|
190
|
-
{
|
|
191
|
-
name: 'raw',
|
|
192
|
-
interval: '1m',
|
|
193
|
-
retention: 60 * 60 * 1000, // 1 hour
|
|
194
|
-
partitionInterval: 'hourly',
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
name: '1m',
|
|
198
|
-
interval: '1m',
|
|
199
|
-
retention: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
200
|
-
partitionInterval: 'daily',
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
name: '1h',
|
|
204
|
-
interval: '1h',
|
|
205
|
-
retention: 0, // Forever
|
|
206
|
-
partitionInterval: 'monthly',
|
|
207
|
-
},
|
|
208
|
-
],
|
|
209
|
-
flushInterval: 10_000, // 10 seconds
|
|
210
|
-
maxBatchSize: 1000,
|
|
211
|
-
autoRollup: true,
|
|
212
|
-
tdigestCompression: 100,
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Rollup options for aggregating data between tiers
|
|
217
|
-
*/
|
|
218
|
-
export interface RollupOptions {
|
|
219
|
-
/** Source tier */
|
|
220
|
-
from: string;
|
|
221
|
-
/** Target tier */
|
|
222
|
-
to: string;
|
|
223
|
-
/** Only rollup data older than this */
|
|
224
|
-
olderThan: Date;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Partition info for management
|
|
229
|
-
*/
|
|
230
|
-
export interface PartitionInfo {
|
|
231
|
-
/** Partition name */
|
|
232
|
-
name: string;
|
|
233
|
-
/** Tier this partition belongs to */
|
|
234
|
-
tier: string;
|
|
235
|
-
/** Partition start time */
|
|
236
|
-
start: Date;
|
|
237
|
-
/** Partition end time */
|
|
238
|
-
end: Date;
|
|
239
|
-
/** Approximate row count */
|
|
240
|
-
rowCount?: number;
|
|
241
|
-
/** Size in bytes */
|
|
242
|
-
sizeBytes?: number;
|
|
243
|
-
}
|
|
@@ -1,367 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { InMemoryStorage } from '../../storage/memory';
|
|
3
|
-
import { Telescope } from '../../Telescope';
|
|
4
|
-
import { OTLPReceiver } from '../receiver';
|
|
5
|
-
import {
|
|
6
|
-
type ExportLogsServiceRequest,
|
|
7
|
-
type ExportMetricsServiceRequest,
|
|
8
|
-
type ExportTraceServiceRequest,
|
|
9
|
-
SeverityNumber,
|
|
10
|
-
SpanKind,
|
|
11
|
-
SpanStatusCode,
|
|
12
|
-
} from '../types';
|
|
13
|
-
|
|
14
|
-
describe('OTLPReceiver', () => {
|
|
15
|
-
let telescope: Telescope;
|
|
16
|
-
let storage: InMemoryStorage;
|
|
17
|
-
let receiver: OTLPReceiver;
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
storage = new InMemoryStorage();
|
|
21
|
-
telescope = new Telescope({ storage });
|
|
22
|
-
receiver = new OTLPReceiver({ telescope });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
telescope.destroy();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe('receiveTraces', () => {
|
|
30
|
-
it('should record HTTP server spans as requests', async () => {
|
|
31
|
-
const request: ExportTraceServiceRequest = {
|
|
32
|
-
resourceSpans: [
|
|
33
|
-
{
|
|
34
|
-
resource: {
|
|
35
|
-
attributes: [
|
|
36
|
-
{ key: 'service.name', value: { stringValue: 'test-api' } },
|
|
37
|
-
],
|
|
38
|
-
},
|
|
39
|
-
scopeSpans: [
|
|
40
|
-
{
|
|
41
|
-
spans: [
|
|
42
|
-
{
|
|
43
|
-
traceId: 'abc123',
|
|
44
|
-
spanId: 'def456',
|
|
45
|
-
name: 'GET /users',
|
|
46
|
-
kind: SpanKind.SPAN_KIND_SERVER,
|
|
47
|
-
startTimeUnixNano: '1704067200000000000',
|
|
48
|
-
endTimeUnixNano: '1704067200050000000',
|
|
49
|
-
attributes: [
|
|
50
|
-
{ key: 'http.method', value: { stringValue: 'GET' } },
|
|
51
|
-
{ key: 'http.target', value: { stringValue: '/users' } },
|
|
52
|
-
{ key: 'http.status_code', value: { intValue: '200' } },
|
|
53
|
-
],
|
|
54
|
-
status: { code: SpanStatusCode.STATUS_CODE_OK },
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const response = await receiver.receiveTraces(request);
|
|
64
|
-
|
|
65
|
-
expect(response.partialSuccess).toBeUndefined();
|
|
66
|
-
|
|
67
|
-
const requests = await telescope.getRequests();
|
|
68
|
-
expect(requests).toHaveLength(1);
|
|
69
|
-
expect(requests[0].method).toBe('GET');
|
|
70
|
-
expect(requests[0].path).toBe('/users');
|
|
71
|
-
expect(requests[0].status).toBe(200);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should handle multiple spans', async () => {
|
|
75
|
-
const request: ExportTraceServiceRequest = {
|
|
76
|
-
resourceSpans: [
|
|
77
|
-
{
|
|
78
|
-
scopeSpans: [
|
|
79
|
-
{
|
|
80
|
-
spans: [
|
|
81
|
-
{
|
|
82
|
-
traceId: 'abc123',
|
|
83
|
-
spanId: 'span1',
|
|
84
|
-
name: 'GET /users',
|
|
85
|
-
kind: SpanKind.SPAN_KIND_SERVER,
|
|
86
|
-
startTimeUnixNano: '1704067200000000000',
|
|
87
|
-
endTimeUnixNano: '1704067200050000000',
|
|
88
|
-
attributes: [
|
|
89
|
-
{ key: 'http.method', value: { stringValue: 'GET' } },
|
|
90
|
-
{ key: 'http.target', value: { stringValue: '/users' } },
|
|
91
|
-
{ key: 'http.status_code', value: { intValue: '200' } },
|
|
92
|
-
],
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
traceId: 'abc123',
|
|
96
|
-
spanId: 'span2',
|
|
97
|
-
name: 'POST /users',
|
|
98
|
-
kind: SpanKind.SPAN_KIND_SERVER,
|
|
99
|
-
startTimeUnixNano: '1704067200100000000',
|
|
100
|
-
endTimeUnixNano: '1704067200200000000',
|
|
101
|
-
attributes: [
|
|
102
|
-
{ key: 'http.method', value: { stringValue: 'POST' } },
|
|
103
|
-
{ key: 'http.target', value: { stringValue: '/users' } },
|
|
104
|
-
{ key: 'http.status_code', value: { intValue: '201' } },
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
],
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
await receiver.receiveTraces(request);
|
|
115
|
-
|
|
116
|
-
const requests = await telescope.getRequests();
|
|
117
|
-
expect(requests).toHaveLength(2);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should return empty response for empty request', async () => {
|
|
121
|
-
const response = await receiver.receiveTraces({});
|
|
122
|
-
expect(response).toEqual({});
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('receiveLogs', () => {
|
|
127
|
-
it('should record log entries', async () => {
|
|
128
|
-
const request: ExportLogsServiceRequest = {
|
|
129
|
-
resourceLogs: [
|
|
130
|
-
{
|
|
131
|
-
scopeLogs: [
|
|
132
|
-
{
|
|
133
|
-
logRecords: [
|
|
134
|
-
{
|
|
135
|
-
observedTimeUnixNano: '1704067200000000000',
|
|
136
|
-
severityNumber: SeverityNumber.SEVERITY_NUMBER_INFO,
|
|
137
|
-
body: { stringValue: 'User logged in' },
|
|
138
|
-
attributes: [
|
|
139
|
-
{ key: 'userId', value: { stringValue: '123' } },
|
|
140
|
-
],
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const response = await receiver.receiveLogs(request);
|
|
150
|
-
|
|
151
|
-
expect(response.partialSuccess).toBeUndefined();
|
|
152
|
-
|
|
153
|
-
const logs = await telescope.getLogs();
|
|
154
|
-
expect(logs).toHaveLength(1);
|
|
155
|
-
expect(logs[0].level).toBe('info');
|
|
156
|
-
expect(logs[0].message).toBe('User logged in');
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('should batch multiple log records', async () => {
|
|
160
|
-
const request: ExportLogsServiceRequest = {
|
|
161
|
-
resourceLogs: [
|
|
162
|
-
{
|
|
163
|
-
scopeLogs: [
|
|
164
|
-
{
|
|
165
|
-
logRecords: [
|
|
166
|
-
{
|
|
167
|
-
observedTimeUnixNano: '1704067200000000000',
|
|
168
|
-
severityNumber: SeverityNumber.SEVERITY_NUMBER_INFO,
|
|
169
|
-
body: { stringValue: 'Log 1' },
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
observedTimeUnixNano: '1704067200001000000',
|
|
173
|
-
severityNumber: SeverityNumber.SEVERITY_NUMBER_DEBUG,
|
|
174
|
-
body: { stringValue: 'Log 2' },
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
observedTimeUnixNano: '1704067200002000000',
|
|
178
|
-
severityNumber: SeverityNumber.SEVERITY_NUMBER_WARN,
|
|
179
|
-
body: { stringValue: 'Log 3' },
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
},
|
|
185
|
-
],
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
await receiver.receiveLogs(request);
|
|
189
|
-
|
|
190
|
-
const logs = await telescope.getLogs();
|
|
191
|
-
expect(logs).toHaveLength(3);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should return empty response for empty request', async () => {
|
|
195
|
-
const response = await receiver.receiveLogs({});
|
|
196
|
-
expect(response).toEqual({});
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
describe('receiveMetrics', () => {
|
|
201
|
-
it('should call onMetrics handler', async () => {
|
|
202
|
-
const onMetrics = vi.fn();
|
|
203
|
-
const receiverWithHandler = new OTLPReceiver({
|
|
204
|
-
telescope,
|
|
205
|
-
onMetrics,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
const request: ExportMetricsServiceRequest = {
|
|
209
|
-
resourceMetrics: [
|
|
210
|
-
{
|
|
211
|
-
scopeMetrics: [
|
|
212
|
-
{
|
|
213
|
-
metrics: [
|
|
214
|
-
{
|
|
215
|
-
name: 'http_requests_total',
|
|
216
|
-
sum: {
|
|
217
|
-
dataPoints: [
|
|
218
|
-
{
|
|
219
|
-
timeUnixNano: '1704067200000000000',
|
|
220
|
-
asInt: '100',
|
|
221
|
-
},
|
|
222
|
-
],
|
|
223
|
-
aggregationTemporality: 2,
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
],
|
|
227
|
-
},
|
|
228
|
-
],
|
|
229
|
-
},
|
|
230
|
-
],
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
const response = await receiverWithHandler.receiveMetrics(request);
|
|
234
|
-
|
|
235
|
-
expect(response.partialSuccess).toBeUndefined();
|
|
236
|
-
expect(onMetrics).toHaveBeenCalledTimes(1);
|
|
237
|
-
expect(onMetrics).toHaveBeenCalledWith(
|
|
238
|
-
expect.arrayContaining([
|
|
239
|
-
expect.objectContaining({
|
|
240
|
-
name: 'http_requests_total',
|
|
241
|
-
value: 100,
|
|
242
|
-
type: 'sum',
|
|
243
|
-
}),
|
|
244
|
-
]),
|
|
245
|
-
);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it('should log metrics when logMetrics is enabled', async () => {
|
|
249
|
-
const receiverWithLogging = new OTLPReceiver({
|
|
250
|
-
telescope,
|
|
251
|
-
logMetrics: true,
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const request: ExportMetricsServiceRequest = {
|
|
255
|
-
resourceMetrics: [
|
|
256
|
-
{
|
|
257
|
-
scopeMetrics: [
|
|
258
|
-
{
|
|
259
|
-
metrics: [
|
|
260
|
-
{
|
|
261
|
-
name: 'cpu_usage',
|
|
262
|
-
gauge: {
|
|
263
|
-
dataPoints: [
|
|
264
|
-
{
|
|
265
|
-
timeUnixNano: '1704067200000000000',
|
|
266
|
-
asDouble: 45.5,
|
|
267
|
-
},
|
|
268
|
-
],
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
],
|
|
272
|
-
},
|
|
273
|
-
],
|
|
274
|
-
},
|
|
275
|
-
],
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
await receiverWithLogging.receiveMetrics(request);
|
|
279
|
-
|
|
280
|
-
const logs = await telescope.getLogs();
|
|
281
|
-
expect(logs).toHaveLength(1);
|
|
282
|
-
expect(logs[0].message).toBe('OTLP Metric: cpu_usage');
|
|
283
|
-
expect(logs[0].level).toBe('debug');
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('should return empty response when no handler', async () => {
|
|
287
|
-
const response = await receiver.receiveMetrics({});
|
|
288
|
-
expect(response).toEqual({});
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it('should report partial success on handler error', async () => {
|
|
292
|
-
const onMetrics = vi.fn().mockRejectedValue(new Error('Handler failed'));
|
|
293
|
-
const receiverWithHandler = new OTLPReceiver({
|
|
294
|
-
telescope,
|
|
295
|
-
onMetrics,
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
const request: ExportMetricsServiceRequest = {
|
|
299
|
-
resourceMetrics: [
|
|
300
|
-
{
|
|
301
|
-
scopeMetrics: [
|
|
302
|
-
{
|
|
303
|
-
metrics: [
|
|
304
|
-
{
|
|
305
|
-
name: 'test_metric',
|
|
306
|
-
gauge: {
|
|
307
|
-
dataPoints: [
|
|
308
|
-
{
|
|
309
|
-
timeUnixNano: '1704067200000000000',
|
|
310
|
-
asDouble: 1,
|
|
311
|
-
},
|
|
312
|
-
],
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
],
|
|
316
|
-
},
|
|
317
|
-
],
|
|
318
|
-
},
|
|
319
|
-
],
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
const response = await receiverWithHandler.receiveMetrics(request);
|
|
323
|
-
|
|
324
|
-
expect(response.partialSuccess).toBeDefined();
|
|
325
|
-
expect(response.partialSuccess?.rejectedDataPoints).toBe('1');
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
describe('integration with Telescope', () => {
|
|
330
|
-
it('should update metrics aggregator via recordRequest', async () => {
|
|
331
|
-
const request: ExportTraceServiceRequest = {
|
|
332
|
-
resourceSpans: [
|
|
333
|
-
{
|
|
334
|
-
scopeSpans: [
|
|
335
|
-
{
|
|
336
|
-
spans: [
|
|
337
|
-
{
|
|
338
|
-
traceId: 'abc123',
|
|
339
|
-
spanId: 'def456',
|
|
340
|
-
name: 'GET /api/test',
|
|
341
|
-
kind: SpanKind.SPAN_KIND_SERVER,
|
|
342
|
-
startTimeUnixNano: '1704067200000000000',
|
|
343
|
-
endTimeUnixNano: '1704067200100000000',
|
|
344
|
-
attributes: [
|
|
345
|
-
{ key: 'http.method', value: { stringValue: 'GET' } },
|
|
346
|
-
{
|
|
347
|
-
key: 'http.target',
|
|
348
|
-
value: { stringValue: '/api/test' },
|
|
349
|
-
},
|
|
350
|
-
{ key: 'http.status_code', value: { intValue: '200' } },
|
|
351
|
-
],
|
|
352
|
-
},
|
|
353
|
-
],
|
|
354
|
-
},
|
|
355
|
-
],
|
|
356
|
-
},
|
|
357
|
-
],
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
await receiver.receiveTraces(request);
|
|
361
|
-
|
|
362
|
-
// The Telescope's metrics aggregator should have the request
|
|
363
|
-
const metrics = telescope.getMetrics();
|
|
364
|
-
expect(metrics.totalRequests).toBe(1);
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
});
|