@pepys/source-telemetry 0.0.0-stage → 0.1.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 +35 -2
- package/package.json +30 -4
- package/src/consumers/products/find-claude-code-model-request.ts +41 -0
- package/src/consumers/products/find-codex-model-request.ts +34 -0
- package/src/consumers/products/find-codex-turn-cost.ts +21 -0
- package/src/consumers/products/find-record-number.ts +101 -0
- package/src/consumers/products/parse-fact-type.ts +21 -0
- package/src/consumers/products/types.ts +34 -0
- package/src/consumers/telemetry-model-request.ts +91 -0
- package/src/consumers/telemetry-turn-cost.ts +85 -0
- package/src/generated/telemetry-model-request-boundary.ts +368 -0
- package/src/generated/telemetry-model-request.sql +35 -0
- package/src/generated/telemetry-turn-cost-boundary.ts +361 -0
- package/src/generated/telemetry-turn-cost.sql +26 -0
- package/src/index.ts +26 -0
- package/src/log-record-family.ts +41 -0
- package/src/otlp/format-canonical-json.ts +24 -0
- package/src/otlp/parse-logs-export.ts +71 -0
- package/src/otlp/read-otlp-facts.ts +226 -0
- package/src/otlp/receive-otlp-logs.ts +130 -0
- package/src/otlp/to-attribute-map.ts +63 -0
- package/src/otlp/types.ts +36 -0
- package/src/products/claude-code/claude-code-product.ts +45 -0
- package/src/products/codex/codex-product.ts +37 -0
- package/src/products/define-telemetry-product.ts +7 -0
- package/src/products/find-attribute-text.ts +12 -0
- package/src/products/products.ts +8 -0
- package/src/products/types.ts +21 -0
- package/src/queries/session-model-requests-query.ts +55 -0
- package/src/telemetry-model-request-consumer.ts +59 -0
- package/src/telemetry-plugin.ts +44 -0
- package/src/telemetry-turn-cost-consumer.ts +42 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { defineConsumer, defineTable } from '@pepys/kit';
|
|
2
|
+
import { logRecordFamily } from './log-record-family.ts';
|
|
3
|
+
|
|
4
|
+
// Fact mode: one row comes from exactly one fact, and the row's key comes from the fact's ID, so
|
|
5
|
+
// the order of the facts changes nothing.
|
|
6
|
+
export const telemetryModelRequestConsumer = defineConsumer({
|
|
7
|
+
name: 'telemetry_model_request',
|
|
8
|
+
entry: new URL('consumers/telemetry-model-request.ts', import.meta.url),
|
|
9
|
+
input: { mode: 'fact', streams: [logRecordFamily.stream] },
|
|
10
|
+
tables: {
|
|
11
|
+
telemetry_model_request: defineTable({
|
|
12
|
+
columns: {
|
|
13
|
+
// `telemetry:model_request:<product>.<event>:<key>`
|
|
14
|
+
id: { kind: 'entityID' },
|
|
15
|
+
|
|
16
|
+
// The join key: `telemetry:session:<atc session ID>`, or the agent's own session ID when
|
|
17
|
+
// the record has no atc session ID.
|
|
18
|
+
session_id: { kind: 'entityID' },
|
|
19
|
+
|
|
20
|
+
// The agent's own session ID. It changes inside one atc session, so nothing joins on it.
|
|
21
|
+
agent_session: { kind: 'text', nullable: true },
|
|
22
|
+
product: { kind: 'text' },
|
|
23
|
+
model: { kind: 'text' },
|
|
24
|
+
|
|
25
|
+
// never holds a token that the cache read or wrote, for every product
|
|
26
|
+
input_tokens: { kind: 'integer' },
|
|
27
|
+
cache_read_tokens: { kind: 'integer' },
|
|
28
|
+
cache_creation_tokens: { kind: 'integer' },
|
|
29
|
+
output_tokens: { kind: 'integer' },
|
|
30
|
+
|
|
31
|
+
// null when the product reports no cost for one request; 0 never stands for unknown
|
|
32
|
+
cost_usd: { kind: 'real', nullable: true },
|
|
33
|
+
cost_basis: { kind: 'text' },
|
|
34
|
+
duration_ms: { kind: 'integer', nullable: true },
|
|
35
|
+
agent: { kind: 'text', nullable: true },
|
|
36
|
+
|
|
37
|
+
// the proven sender of the export that carried the record
|
|
38
|
+
origin_issuer: { kind: 'text' },
|
|
39
|
+
origin_subject: { kind: 'text' },
|
|
40
|
+
at: { kind: 'timestamp' },
|
|
41
|
+
},
|
|
42
|
+
primaryKey: ['id'],
|
|
43
|
+
indexes: [{ columns: ['session_id'] }, { columns: ['at'] }],
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
entityViews: [
|
|
47
|
+
{
|
|
48
|
+
table: 'telemetry_model_request',
|
|
49
|
+
kind: 'telemetry:model_request',
|
|
50
|
+
id: 'id',
|
|
51
|
+
title: 'model',
|
|
52
|
+
url: null,
|
|
53
|
+
actor: null,
|
|
54
|
+
updatedAt: 'at',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
reads: [],
|
|
58
|
+
links: [],
|
|
59
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { definePlugin, defineSource } from '@pepys/kit';
|
|
2
|
+
import { logRecordFamily } from './log-record-family.ts';
|
|
3
|
+
import { receiveOtlpLogs } from './otlp/receive-otlp-logs.ts';
|
|
4
|
+
import { products } from './products/products.ts';
|
|
5
|
+
import { sessionModelRequestsQuery } from './queries/session-model-requests-query.ts';
|
|
6
|
+
import { telemetryModelRequestConsumer } from './telemetry-model-request-consumer.ts';
|
|
7
|
+
import { telemetryTurnCostConsumer } from './telemetry-turn-cost-consumer.ts';
|
|
8
|
+
|
|
9
|
+
export const telemetrySource = defineSource({
|
|
10
|
+
name: 'telemetry',
|
|
11
|
+
families: [logRecordFamily],
|
|
12
|
+
|
|
13
|
+
// Push only. An OTLP exporter cannot sign a body, so the check is a token, and the route needs a
|
|
14
|
+
// proven sender, whom each fact then holds as its `origin`.
|
|
15
|
+
live: receiveOtlpLogs({
|
|
16
|
+
route: '/v1/logs',
|
|
17
|
+
|
|
18
|
+
// An exporter that gets a bare origin adds these paths itself, and retries a refusal for ever.
|
|
19
|
+
ignoredRoutes: ['/v1/metrics', '/v1/traces'],
|
|
20
|
+
check: { kind: 'token', header: 'authorization', secretEnv: 'PEPYS_TELEMETRY_TOKEN' },
|
|
21
|
+
sender: {
|
|
22
|
+
kind: 'imp-identity',
|
|
23
|
+
audienceEnv: 'PEPYS_IMP_IDENTITY_AUDIENCE',
|
|
24
|
+
issuersEnv: 'PEPYS_IMP_IDENTITY_ISSUERS',
|
|
25
|
+
},
|
|
26
|
+
products,
|
|
27
|
+
|
|
28
|
+
// atc stamps it on every record of a session it runs
|
|
29
|
+
sessionAttribute: 'atc.session.id',
|
|
30
|
+
factLimit: 1000,
|
|
31
|
+
bodyByteLimit: 4_194_304,
|
|
32
|
+
encodings: ['gzip'],
|
|
33
|
+
answer: 'empty',
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// `telemetry:session` is a kind of this plug-in, from the family, with no table: a link may point
|
|
38
|
+
// at a session, and no entity view finds one.
|
|
39
|
+
export const telemetryPlugin = definePlugin({
|
|
40
|
+
name: 'telemetry',
|
|
41
|
+
sources: [telemetrySource],
|
|
42
|
+
consumers: [telemetryModelRequestConsumer, telemetryTurnCostConsumer],
|
|
43
|
+
queries: [sessionModelRequestsQuery],
|
|
44
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { defineConsumer, defineTable } from '@pepys/kit';
|
|
2
|
+
import { logRecordFamily } from './log-record-family.ts';
|
|
3
|
+
|
|
4
|
+
// The cost a product reports per turn: a second consumer on the same stream.
|
|
5
|
+
export const telemetryTurnCostConsumer = defineConsumer({
|
|
6
|
+
name: 'telemetry_turn_cost',
|
|
7
|
+
entry: new URL('consumers/telemetry-turn-cost.ts', import.meta.url),
|
|
8
|
+
input: { mode: 'fact', streams: [logRecordFamily.stream] },
|
|
9
|
+
tables: {
|
|
10
|
+
telemetry_turn_cost: defineTable({
|
|
11
|
+
columns: {
|
|
12
|
+
// `telemetry:turn_cost:<product>.<event>:<key>`
|
|
13
|
+
id: { kind: 'entityID' },
|
|
14
|
+
session_id: { kind: 'entityID' },
|
|
15
|
+
agent_session: { kind: 'text', nullable: true },
|
|
16
|
+
product: { kind: 'text' },
|
|
17
|
+
|
|
18
|
+
// the model the record names, so a report can group turn costs by model; null when absent
|
|
19
|
+
model: { kind: 'text', nullable: true },
|
|
20
|
+
cost_usd: { kind: 'real' },
|
|
21
|
+
origin_issuer: { kind: 'text' },
|
|
22
|
+
origin_subject: { kind: 'text' },
|
|
23
|
+
at: { kind: 'timestamp' },
|
|
24
|
+
},
|
|
25
|
+
primaryKey: ['id'],
|
|
26
|
+
indexes: [{ columns: ['session_id'] }],
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
entityViews: [
|
|
30
|
+
{
|
|
31
|
+
table: 'telemetry_turn_cost',
|
|
32
|
+
kind: 'telemetry:turn_cost',
|
|
33
|
+
id: 'id',
|
|
34
|
+
title: 'product',
|
|
35
|
+
url: null,
|
|
36
|
+
actor: null,
|
|
37
|
+
updatedAt: 'at',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
reads: [],
|
|
41
|
+
links: [],
|
|
42
|
+
});
|