@damngamerz/pi-otel 0.1.0-bootstrap.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/ACKNOWLEDGEMENTS.md +7 -0
  2. package/CHANGELOG.md +10 -0
  3. package/LICENSE +21 -0
  4. package/LICENSES/Apache-2.0.txt +202 -0
  5. package/NOTICE +15 -0
  6. package/README.md +120 -0
  7. package/SECURITY.md +24 -0
  8. package/dist/commands/flush.d.ts +4 -0
  9. package/dist/commands/flush.d.ts.map +1 -0
  10. package/dist/commands/flush.js +20 -0
  11. package/dist/commands/flush.js.map +1 -0
  12. package/dist/commands/status.d.ts +5 -0
  13. package/dist/commands/status.d.ts.map +1 -0
  14. package/dist/commands/status.js +47 -0
  15. package/dist/commands/status.js.map +1 -0
  16. package/dist/config.d.ts +41 -0
  17. package/dist/config.d.ts.map +1 -0
  18. package/dist/config.js +260 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/evaluation/evaluator.d.ts +11 -0
  21. package/dist/evaluation/evaluator.d.ts.map +1 -0
  22. package/dist/evaluation/evaluator.js +55 -0
  23. package/dist/evaluation/evaluator.js.map +1 -0
  24. package/dist/evaluation/parser.d.ts +3 -0
  25. package/dist/evaluation/parser.d.ts.map +1 -0
  26. package/dist/evaluation/parser.js +42 -0
  27. package/dist/evaluation/parser.js.map +1 -0
  28. package/dist/evaluation/prompt.d.ts +2 -0
  29. package/dist/evaluation/prompt.d.ts.map +1 -0
  30. package/dist/evaluation/prompt.js +16 -0
  31. package/dist/evaluation/prompt.js.map +1 -0
  32. package/dist/evaluation/sampling.d.ts +9 -0
  33. package/dist/evaluation/sampling.d.ts.map +1 -0
  34. package/dist/evaluation/sampling.js +25 -0
  35. package/dist/evaluation/sampling.js.map +1 -0
  36. package/dist/evaluation/types.d.ts +19 -0
  37. package/dist/evaluation/types.d.ts.map +1 -0
  38. package/dist/evaluation/types.js +2 -0
  39. package/dist/evaluation/types.js.map +1 -0
  40. package/dist/index.d.ts +4 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +151 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/lifecycle.d.ts +3 -0
  45. package/dist/lifecycle.d.ts.map +1 -0
  46. package/dist/lifecycle.js +15 -0
  47. package/dist/lifecycle.js.map +1 -0
  48. package/dist/privacy/content-policy.d.ts +8 -0
  49. package/dist/privacy/content-policy.d.ts.map +1 -0
  50. package/dist/privacy/content-policy.js +48 -0
  51. package/dist/privacy/content-policy.js.map +1 -0
  52. package/dist/privacy/sanitization.d.ts +5 -0
  53. package/dist/privacy/sanitization.d.ts.map +1 -0
  54. package/dist/privacy/sanitization.js +42 -0
  55. package/dist/privacy/sanitization.js.map +1 -0
  56. package/dist/privacy/secret-detector.d.ts +2 -0
  57. package/dist/privacy/secret-detector.d.ts.map +1 -0
  58. package/dist/privacy/secret-detector.js +14 -0
  59. package/dist/privacy/secret-detector.js.map +1 -0
  60. package/dist/telemetry/attributes.d.ts +11 -0
  61. package/dist/telemetry/attributes.d.ts.map +1 -0
  62. package/dist/telemetry/attributes.js +13 -0
  63. package/dist/telemetry/attributes.js.map +1 -0
  64. package/dist/telemetry/instruments.d.ts +17 -0
  65. package/dist/telemetry/instruments.d.ts.map +1 -0
  66. package/dist/telemetry/instruments.js +54 -0
  67. package/dist/telemetry/instruments.js.map +1 -0
  68. package/dist/telemetry/providers.d.ts +21 -0
  69. package/dist/telemetry/providers.d.ts.map +1 -0
  70. package/dist/telemetry/providers.js +88 -0
  71. package/dist/telemetry/providers.js.map +1 -0
  72. package/dist/telemetry/traces.d.ts +44 -0
  73. package/dist/telemetry/traces.d.ts.map +1 -0
  74. package/dist/telemetry/traces.js +265 -0
  75. package/dist/telemetry/traces.js.map +1 -0
  76. package/dist/telemetry/usage.d.ts +11 -0
  77. package/dist/telemetry/usage.d.ts.map +1 -0
  78. package/dist/telemetry/usage.js +25 -0
  79. package/dist/telemetry/usage.js.map +1 -0
  80. package/docs/configuration.md +61 -0
  81. package/docs/evaluation.md +38 -0
  82. package/docs/metrics.md +27 -0
  83. package/docs/operations.md +41 -0
  84. package/docs/privacy.md +38 -0
  85. package/examples/grafana-lgtm/LICENSE +6 -0
  86. package/examples/grafana-lgtm/README.md +47 -0
  87. package/examples/grafana-lgtm/compose.yaml +16 -0
  88. package/examples/grafana-lgtm/dashboard.json +616 -0
  89. package/examples/grafana-lgtm/provisioning.yaml +9 -0
  90. package/package.json +87 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traces.d.ts","sourceRoot":"","sources":["../../src/telemetry/traces.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAkBzD,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,gBAAgB;IAyBhB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAxBtC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAU1B;IAEF,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,yBAAyB,CAAsB;IACvD,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiC;IAC7D,OAAO,CAAC,uBAAuB,CAAK;gBAEP,SAAS,EAAE,kBAAkB;IAE1D,YAAY,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI;IAM/C,UAAU,IAAI,IAAI;IAqBlB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAelC,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAqBzD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI1C,cAAc,IAAI,IAAI;IAStB,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAoDtD,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAkBrD,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAwBtD,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAcnC,WAAW,IAAI,IAAI;IAenB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAsDxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAU/B"}
@@ -0,0 +1,265 @@
1
+ import { SpanKind, SpanStatusCode, context, trace } from "@opentelemetry/api";
2
+ import { safeTelemetryIdentifier } from "../privacy/sanitization.js";
3
+ import { BASE_GEN_AI_ATTRIBUTES, modelAttributes } from "./attributes.js";
4
+ import { extractUsage } from "./usage.js";
5
+ export class TelemetryRuntime {
6
+ providers;
7
+ stats = {
8
+ prompts: 0,
9
+ turns: 0,
10
+ toolCalls: 0,
11
+ toolErrors: 0,
12
+ inputTokens: 0,
13
+ outputTokens: 0,
14
+ costUsd: 0,
15
+ evaluationRuns: 0,
16
+ evaluationCostUsd: 0,
17
+ };
18
+ sessionContext = context.active();
19
+ sessionId = "ephemeral";
20
+ sessionStartedAt = 0;
21
+ agentSpan;
22
+ agentContext = context.active();
23
+ lastCompletedAgentContext;
24
+ turnSpan;
25
+ turnContext = context.active();
26
+ activeLlm;
27
+ activeTools = new Map();
28
+ toolsInCurrentOperation = 0;
29
+ constructor(providers) {
30
+ this.providers = providers;
31
+ }
32
+ startSession(anonymizedSessionId) {
33
+ this.sessionId = anonymizedSessionId;
34
+ this.sessionContext = context.active();
35
+ this.sessionStartedAt = performance.now();
36
+ }
37
+ startAgent() {
38
+ this.finishAgent();
39
+ this.stats.prompts++;
40
+ this.providers.instruments.promptCount.add(1, BASE_GEN_AI_ATTRIBUTES);
41
+ this.agentSpan = this.providers.tracer.startSpan("invoke_agent pi", {
42
+ kind: SpanKind.INTERNAL,
43
+ attributes: {
44
+ ...BASE_GEN_AI_ATTRIBUTES,
45
+ "gen_ai.operation.name": "invoke_agent",
46
+ "gen_ai.agent.name": "pi",
47
+ "gen_ai.conversation.id": this.sessionId,
48
+ },
49
+ }, this.sessionContext);
50
+ this.agentContext = trace.setSpan(this.sessionContext, this.agentSpan);
51
+ this.toolsInCurrentOperation = 0;
52
+ }
53
+ startTurn(turnIndex) {
54
+ this.finishTurn();
55
+ this.stats.turns++;
56
+ this.providers.instruments.turnCount.add(1, BASE_GEN_AI_ATTRIBUTES);
57
+ this.turnSpan = this.providers.tracer.startSpan("pi turn", {
58
+ kind: SpanKind.INTERNAL,
59
+ attributes: { "pi.turn.index": turnIndex },
60
+ }, this.agentContext);
61
+ this.turnContext = trace.setSpan(this.agentContext, this.turnSpan);
62
+ }
63
+ startLlm(providerValue, modelValue) {
64
+ this.finishLlm(undefined, "retry");
65
+ const provider = safeTelemetryIdentifier(providerValue);
66
+ const model = safeTelemetryIdentifier(modelValue, "redacted", 128);
67
+ const span = this.providers.tracer.startSpan(`chat ${model}`, {
68
+ kind: SpanKind.CLIENT,
69
+ attributes: modelAttributes(provider, model),
70
+ }, this.turnContext);
71
+ this.activeLlm = {
72
+ span,
73
+ startedAt: performance.now(),
74
+ provider,
75
+ model,
76
+ firstTokenSeen: false,
77
+ };
78
+ }
79
+ noteProviderResponse(status) {
80
+ if (this.activeLlm)
81
+ this.activeLlm.responseStatus = status;
82
+ }
83
+ noteFirstToken() {
84
+ if (!this.activeLlm || this.activeLlm.firstTokenSeen)
85
+ return;
86
+ this.activeLlm.firstTokenSeen = true;
87
+ this.providers.instruments.timeToFirstToken.record(Math.max(0, (performance.now() - this.activeLlm.startedAt) / 1_000), modelAttributes(this.activeLlm.provider, this.activeLlm.model));
88
+ }
89
+ finishLlm(message, errorType) {
90
+ if (!this.activeLlm)
91
+ return;
92
+ const llm = this.activeLlm;
93
+ this.activeLlm = undefined;
94
+ const usage = extractUsage(message, llm.provider, llm.model);
95
+ const provider = safeTelemetryIdentifier(usage.provider);
96
+ const model = safeTelemetryIdentifier(usage.model, "redacted", 128);
97
+ const attributes = modelAttributes(provider, model);
98
+ this.providers.instruments.operationDuration.record(Math.max(0, (performance.now() - llm.startedAt) / 1_000), {
99
+ ...attributes,
100
+ ...(errorType ? { "error.type": safeTelemetryIdentifier(errorType) } : {}),
101
+ });
102
+ for (const [tokenType, amount] of [
103
+ ["input", usage.input],
104
+ ["output", usage.output],
105
+ ["cache_read", usage.cacheRead],
106
+ ["cache_write", usage.cacheWrite],
107
+ ]) {
108
+ if (amount > 0) {
109
+ this.providers.instruments.tokenUsage.record(amount, {
110
+ ...attributes,
111
+ "gen_ai.token.type": tokenType,
112
+ });
113
+ }
114
+ }
115
+ if (usage.costUsd > 0)
116
+ this.providers.instruments.costUsd.add(usage.costUsd, attributes);
117
+ this.stats.inputTokens += usage.input;
118
+ this.stats.outputTokens += usage.output;
119
+ this.stats.costUsd += usage.costUsd;
120
+ llm.span.setAttributes({
121
+ ...attributes,
122
+ "gen_ai.usage.input_tokens": usage.input,
123
+ "gen_ai.usage.output_tokens": usage.output,
124
+ "pi.usage.cache_read_tokens": usage.cacheRead,
125
+ "pi.usage.cache_write_tokens": usage.cacheWrite,
126
+ "pi.cost.usd": usage.costUsd,
127
+ ...(llm.responseStatus != null ? { "http.response.status_code": llm.responseStatus } : {}),
128
+ });
129
+ if (errorType || (llm.responseStatus != null && llm.responseStatus >= 400)) {
130
+ llm.span.setStatus({
131
+ code: SpanStatusCode.ERROR,
132
+ message: errorType ?? `HTTP ${llm.responseStatus}`,
133
+ });
134
+ }
135
+ else {
136
+ llm.span.setStatus({ code: SpanStatusCode.OK });
137
+ }
138
+ llm.span.end();
139
+ }
140
+ startTool(toolCallId, toolName) {
141
+ const name = safeTelemetryIdentifier(toolName, "redacted", 64);
142
+ const attributes = {
143
+ ...BASE_GEN_AI_ATTRIBUTES,
144
+ "gen_ai.tool.name": name,
145
+ "tool.name": name,
146
+ };
147
+ this.stats.toolCalls++;
148
+ this.toolsInCurrentOperation++;
149
+ this.providers.instruments.toolCalls.add(1, attributes);
150
+ const span = this.providers.tracer.startSpan(`execute_tool ${name}`, { kind: SpanKind.INTERNAL, attributes }, this.turnContext);
151
+ this.activeTools.set(toolCallId, { span, startedAt: performance.now(), name });
152
+ }
153
+ finishTool(toolCallId, isError) {
154
+ const tool = this.activeTools.get(toolCallId);
155
+ if (!tool)
156
+ return;
157
+ this.activeTools.delete(toolCallId);
158
+ const attributes = {
159
+ ...BASE_GEN_AI_ATTRIBUTES,
160
+ "gen_ai.tool.name": tool.name,
161
+ "tool.name": tool.name,
162
+ };
163
+ this.providers.instruments.toolDuration.record(Math.max(0, (performance.now() - tool.startedAt) / 1_000), attributes);
164
+ if (isError) {
165
+ this.stats.toolErrors++;
166
+ this.providers.instruments.toolErrors.add(1, attributes);
167
+ tool.span.setAttribute("error.type", "tool_error");
168
+ tool.span.setStatus({ code: SpanStatusCode.ERROR, message: "Tool execution failed" });
169
+ }
170
+ else {
171
+ tool.span.setStatus({ code: SpanStatusCode.OK });
172
+ }
173
+ tool.span.end();
174
+ }
175
+ finishTurn(message) {
176
+ if (this.activeLlm && message)
177
+ this.finishLlm(message);
178
+ this.finishLlm(undefined, "incomplete");
179
+ for (const [toolCallId, tool] of this.activeTools) {
180
+ tool.span.setStatus({ code: SpanStatusCode.ERROR, message: "Tool span incomplete" });
181
+ tool.span.end();
182
+ this.activeTools.delete(toolCallId);
183
+ }
184
+ this.turnSpan?.setStatus({ code: SpanStatusCode.OK });
185
+ this.turnSpan?.end();
186
+ this.turnSpan = undefined;
187
+ this.turnContext = this.agentContext;
188
+ }
189
+ finishAgent() {
190
+ this.finishTurn();
191
+ if (!this.agentSpan)
192
+ return;
193
+ this.providers.instruments.toolCallsPerOperation.record(this.toolsInCurrentOperation, {
194
+ ...BASE_GEN_AI_ATTRIBUTES,
195
+ "gen_ai.operation.name": "invoke_agent",
196
+ });
197
+ this.lastCompletedAgentContext = this.agentContext;
198
+ this.agentSpan.setStatus({ code: SpanStatusCode.OK });
199
+ this.agentSpan.end();
200
+ this.agentSpan = undefined;
201
+ this.agentContext = this.sessionContext;
202
+ this.toolsInCurrentOperation = 0;
203
+ }
204
+ recordEvaluation(batch) {
205
+ const provider = safeTelemetryIdentifier(batch.provider);
206
+ const model = safeTelemetryIdentifier(batch.model, "redacted", 128);
207
+ const attributes = modelAttributes(provider, model, "evaluate");
208
+ this.providers.instruments.operationDuration.record(Math.max(0, batch.durationSeconds), attributes);
209
+ for (const [tokenType, amount] of [
210
+ ["input", batch.usage.input],
211
+ ["output", batch.usage.output],
212
+ ["cache_read", batch.usage.cacheRead],
213
+ ["cache_write", batch.usage.cacheWrite],
214
+ ]) {
215
+ if (amount > 0) {
216
+ this.providers.instruments.tokenUsage.record(amount, {
217
+ ...attributes,
218
+ "gen_ai.token.type": tokenType,
219
+ });
220
+ }
221
+ }
222
+ if (batch.usage.costUsd > 0) {
223
+ this.providers.instruments.costUsd.add(batch.usage.costUsd, attributes);
224
+ }
225
+ this.stats.evaluationRuns++;
226
+ this.stats.evaluationCostUsd += batch.usage.costUsd;
227
+ const span = this.providers.tracer.startSpan(`evaluate ${model}`, {
228
+ kind: SpanKind.CLIENT,
229
+ attributes: {
230
+ ...attributes,
231
+ "gen_ai.usage.input_tokens": batch.usage.input,
232
+ "gen_ai.usage.output_tokens": batch.usage.output,
233
+ "pi.cost.usd": batch.usage.costUsd,
234
+ },
235
+ }, this.lastCompletedAgentContext ?? this.sessionContext);
236
+ for (const result of batch.scores) {
237
+ if (result.score < 0 || result.score > 1)
238
+ continue;
239
+ const evaluationAttributes = {
240
+ "gen_ai.evaluation.name": safeTelemetryIdentifier(result.name, "redacted", 64),
241
+ "gen_ai.evaluation.score.label": safeTelemetryIdentifier(result.label, "redacted", 32),
242
+ "gen_ai.evaluation.evaluator.provider": provider,
243
+ "gen_ai.evaluation.evaluator.model": model,
244
+ };
245
+ this.providers.instruments.evaluationScore.record(result.score, evaluationAttributes);
246
+ span.addEvent("gen_ai.evaluation.result", {
247
+ ...evaluationAttributes,
248
+ "gen_ai.evaluation.score.value": result.score,
249
+ });
250
+ }
251
+ span.setStatus({ code: SpanStatusCode.OK });
252
+ span.end();
253
+ }
254
+ async forceFlush() {
255
+ await this.providers.forceFlush();
256
+ }
257
+ async shutdown() {
258
+ this.finishAgent();
259
+ if (this.sessionStartedAt > 0) {
260
+ this.providers.instruments.sessionDuration.record(Math.max(0, (performance.now() - this.sessionStartedAt) / 1_000), BASE_GEN_AI_ATTRIBUTES);
261
+ }
262
+ await this.providers.shutdown();
263
+ }
264
+ }
265
+ //# sourceMappingURL=traces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traces.js","sourceRoot":"","sources":["../../src/telemetry/traces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ModelUsage {
2
+ provider: string;
3
+ model: string;
4
+ input: number;
5
+ output: number;
6
+ cacheRead: number;
7
+ cacheWrite: number;
8
+ costUsd: number;
9
+ }
10
+ export declare function extractUsage(message: unknown, fallbackProvider?: string, fallbackModel?: string): ModelUsage;
11
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/telemetry/usage.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,YAAY,CAC3B,OAAO,EAAE,OAAO,EAChB,gBAAgB,SAAY,EAC5B,aAAa,SAAY,GACvB,UAAU,CAgCZ"}
@@ -0,0 +1,25 @@
1
+ import { finiteNumber, safeDimension } from "../privacy/sanitization.js";
2
+ export function extractUsage(message, fallbackProvider = "unknown", fallbackModel = "unknown") {
3
+ if (!message || typeof message !== "object") {
4
+ return {
5
+ provider: fallbackProvider,
6
+ model: fallbackModel,
7
+ input: 0,
8
+ output: 0,
9
+ cacheRead: 0,
10
+ cacheWrite: 0,
11
+ costUsd: 0,
12
+ };
13
+ }
14
+ const candidate = message;
15
+ return {
16
+ provider: safeDimension(candidate.provider, fallbackProvider),
17
+ model: safeDimension(candidate.model, fallbackModel),
18
+ input: finiteNumber(candidate.usage?.input),
19
+ output: finiteNumber(candidate.usage?.output),
20
+ cacheRead: finiteNumber(candidate.usage?.cacheRead),
21
+ cacheWrite: finiteNumber(candidate.usage?.cacheWrite),
22
+ costUsd: finiteNumber(candidate.usage?.cost?.total),
23
+ };
24
+ }
25
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/telemetry/usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAYzE,MAAM,UAAU,YAAY,CAC3B,OAAgB,EAChB,gBAAgB,GAAG,SAAS,EAC5B,aAAa,GAAG,SAAS;IAEzB,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7C,OAAO;YACN,QAAQ,EAAE,gBAAgB;YAC1B,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;SACV,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,OAUjB,CAAC;IACF,OAAO;QACN,QAAQ,EAAE,aAAa,CAAC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QAC7D,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC;QACpD,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;QAC3C,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC;QAC7C,SAAS,EAAE,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC;QACnD,UAAU,EAAE,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC;QACrD,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;KACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,61 @@
1
+ # Configuration
2
+
3
+ Configuration is read from `~/.pi/agent/settings.json` and, for trusted projects, `.pi/settings.json`. Project values override global values; environment variables override both.
4
+
5
+ ```jsonc
6
+ {
7
+ "piOtel": {
8
+ "enabled": true,
9
+ "endpoint": "http://127.0.0.1:4318",
10
+ "allowRemoteEndpoint": false,
11
+ "headers": {},
12
+ "serviceName": "pi",
13
+ "signals": {
14
+ "traces": true,
15
+ "metrics": true
16
+ },
17
+ "evaluation": {
18
+ "mode": "off",
19
+ "sampleRate": 0.1,
20
+ "provider": "openai-codex",
21
+ "model": "gpt-5.4-mini",
22
+ "maxCharsPerField": 12000,
23
+ "blockLikelySecrets": true
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ ## Evaluation modes
30
+
31
+ | Mode | Behavior |
32
+ |---|---|
33
+ | `off` | Default. No conversation content is sent to an evaluator. |
34
+ | `manual` | `/otel-eval-last` evaluates the latest exchange. |
35
+ | `sample` | Deterministically evaluates `sampleRate` of settled exchanges. Manual evaluation remains available. |
36
+ | `always` | Evaluates every settled exchange. Manual evaluation remains available. |
37
+
38
+ `sample` decisions are stable for the same exchange, so retries do not change selection.
39
+
40
+ ## Environment variables
41
+
42
+ | Variable | Purpose |
43
+ |---|---|
44
+ | `PI_OTEL_ENABLED` | Enable or disable the extension |
45
+ | `PI_OTEL_ENDPOINT` | OTLP base URL |
46
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Standard OTLP base URL fallback |
47
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Comma-separated `key=value` headers |
48
+ | `OTEL_SERVICE_NAME` | OTel service name |
49
+ | `PI_OTEL_ALLOW_REMOTE_ENDPOINT` | Permit non-loopback OTLP endpoints |
50
+ | `PI_OTEL_TRACES` | Enable traces |
51
+ | `PI_OTEL_METRICS` | Enable metrics |
52
+ | `PI_OTEL_EVALUATION_MODE` | `off`, `manual`, `sample`, or `always` |
53
+ | `PI_OTEL_EVALUATION_SAMPLE_RATE` | Number from `0` to `1` |
54
+ | `PI_OTEL_EVALUATION_PROVIDER` | Pi judge provider |
55
+ | `PI_OTEL_EVALUATION_MODEL` | Pi judge model ID |
56
+ | `PI_OTEL_EVALUATION_MAX_CHARS` | Per-field limit from `256` to `100000` |
57
+ | `PI_OTEL_EVALUATION_BLOCK_SECRETS` | Enable likely-secret blocking |
58
+
59
+ ## Remote collectors
60
+
61
+ Remote endpoints are rejected unless `allowRemoteEndpoint` is explicitly enabled, and non-loopback endpoints must use HTTPS. Use OTLP headers for remote credentials; credentials embedded in endpoint URLs are always rejected. Malformed or incorrectly typed `piOtel` settings are rejected rather than coerced.
@@ -0,0 +1,38 @@
1
+ # Response evaluation
2
+
3
+ The optional remote judge evaluates four dimensions:
4
+
5
+ - `task_success`
6
+ - `instruction_following`
7
+ - `relevance`
8
+ - `correctness`
9
+
10
+ Scores are validated numbers from `0` to `1`. Labels are restricted to `poor`, `fair`, `good`, and `excellent`. Invalid judge output is rejected rather than recorded.
11
+
12
+ ## Correlation
13
+
14
+ Evaluation spans inherit the evaluated agent trace context. This makes the quality score visible beside the original Pi request, LLM calls, and tool activity without adding trace IDs to metric labels.
15
+
16
+ ## Manual evaluation
17
+
18
+ Enable manual mode:
19
+
20
+ ```json
21
+ {
22
+ "piOtel": {
23
+ "evaluation": {
24
+ "mode": "manual"
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ Then run:
31
+
32
+ ```text
33
+ /otel-eval-last
34
+ ```
35
+
36
+ ## Cost
37
+
38
+ Judge requests consume additional provider tokens. Judge token usage, latency, and cost are recorded under `gen_ai.operation.name=evaluate`. Use `manual` or `sample` mode when cost must be bounded.
@@ -0,0 +1,27 @@
1
+ # Metrics
2
+
3
+ ## GenAI metrics
4
+
5
+ | Metric | Type | Unit |
6
+ |---|---|---|
7
+ | `gen_ai.client.operation.duration` | Histogram | seconds |
8
+ | `gen_ai.client.token.usage` | Histogram | tokens |
9
+ | `gen_ai.client.tool_calls_per_operation` | Histogram | calls |
10
+ | `gen_ai.client.tool.calls` | Counter | calls |
11
+ | `gen_ai.evaluation.score` | Histogram | ratio |
12
+
13
+ ## Pi metrics
14
+
15
+ | Metric | Type | Unit |
16
+ |---|---|---|
17
+ | `pi.agent.prompts` | Counter | prompts |
18
+ | `pi.agent.turns` | Counter | turns |
19
+ | `pi.agent.tool.duration` | Histogram | seconds |
20
+ | `pi.agent.tool.errors` | Counter | errors |
21
+ | `pi.agent.session.duration` | Histogram | seconds |
22
+ | `pi.agent.time_to_first_token` | Histogram | seconds |
23
+ | `pi.agent.cost` | Counter | USD |
24
+
25
+ Metric labels are intentionally low-cardinality. Session IDs, trace IDs, prompts, paths, and numeric evaluation values are not used as labels.
26
+
27
+ Evaluation results are represented both as score histograms and as `gen_ai.evaluation.result` events on a correlated evaluation span.
@@ -0,0 +1,41 @@
1
+ # Operations
2
+
3
+ ## Commands
4
+
5
+ - `/otel-status` — endpoint health, evaluation mode, and current-session counters
6
+ - `/otel-flush` — force-flush trace and metric buffers
7
+ - `/otel-eval-last` — evaluate the latest exchange when evaluation is enabled
8
+
9
+ ## Local backend
10
+
11
+ Use the pinned Compose stack under `examples/grafana-lgtm/`.
12
+
13
+ ```bash
14
+ cd examples/grafana-lgtm
15
+ docker compose up -d
16
+ docker compose ps
17
+ ```
18
+
19
+ The example binds OTLP and Grafana ports to `127.0.0.1` only.
20
+
21
+ ## Disable
22
+
23
+ Set this in Pi settings:
24
+
25
+ ```json
26
+ {
27
+ "piOtel": {
28
+ "enabled": false
29
+ }
30
+ }
31
+ ```
32
+
33
+ Or set `PI_OTEL_ENABLED=0`.
34
+
35
+ ## Uninstall
36
+
37
+ ```bash
38
+ pi remove npm:@damngamerz/pi-otel
39
+ ```
40
+
41
+ The package does not install or manage Docker services, systemd units, credentials, or data directories.
@@ -0,0 +1,38 @@
1
+ # Privacy model
2
+
3
+ ## Baseline telemetry
4
+
5
+ Baseline traces and metrics include only:
6
+
7
+ - provider and model names
8
+ - token and cache-token counts
9
+ - request, turn, tool, and session durations
10
+ - tool names and error status
11
+ - cost reported by Pi
12
+ - anonymized session identifiers
13
+
14
+ Provider, model, tool, error, and evaluation identifiers must match a bounded identifier syntax. Values containing path separators—including hierarchical model IDs—or resembling identity data, secrets, or free-form content are exported as `redacted`.
15
+
16
+ They exclude:
17
+
18
+ - prompts and responses
19
+ - thinking or reasoning text
20
+ - provider payloads
21
+ - tool arguments and results
22
+ - shell commands
23
+ - file paths and cwd
24
+ - usernames, hostnames, and email addresses
25
+
26
+ ## Remote evaluation
27
+
28
+ Remote evaluation is disabled by default. When enabled, the latest user request and assistant text are sent to the configured Pi model. Tool results, thinking blocks, images, provider payloads, and system prompts are not included.
29
+
30
+ Safeguards:
31
+
32
+ - likely credentials and private keys cause a hard skip by default
33
+ - each text field is capped before transmission
34
+ - duplicate exchanges are evaluated once
35
+ - judge prompts and explanations are not exported through OTel
36
+ - only bounded scores, score labels, judge model, usage, latency, and cost are recorded
37
+
38
+ Secret detection is defense in depth, not a guarantee. Do not enable remote evaluation for conversations that may contain sensitive data unless the configured provider and organizational policy permit it.
@@ -0,0 +1,6 @@
1
+ SPDX-License-Identifier: Apache-2.0
2
+
3
+ The dashboard.json file is adapted from https://github.com/NikiforovAll/pi-otel,
4
+ Copyright 2026 Oleksii Nikiforov, and remains subject to the Apache License 2.0.
5
+
6
+ See ../../NOTICE and ../../LICENSES/Apache-2.0.txt.
@@ -0,0 +1,47 @@
1
+ # Local Grafana LGTM example
2
+
3
+ This optional Compose stack provides Grafana, Tempo, Prometheus, Loki, and an OpenTelemetry Collector on loopback-only ports.
4
+
5
+ ## Start
6
+
7
+ ```bash
8
+ docker compose up -d
9
+ ```
10
+
11
+ Open <http://127.0.0.1:33000/d/damngamerz-pi-otel/atdamngamerz-pi-otel>.
12
+
13
+ Default endpoints:
14
+
15
+ - OTLP gRPC: `127.0.0.1:4317`
16
+ - OTLP HTTP: `http://127.0.0.1:4318`
17
+ - Grafana: `http://127.0.0.1:33000`
18
+
19
+ Override host ports when necessary:
20
+
21
+ ```bash
22
+ GRAFANA_PORT=34000 OTLP_HTTP_PORT=14318 docker compose up -d
23
+ ```
24
+
25
+ The image is pinned by version and digest, Linux capabilities are dropped, and all host bindings use `127.0.0.1`.
26
+
27
+ ## Start after reboot
28
+
29
+ The example uses `restart: unless-stopped`. Ensure Docker itself is enabled at boot:
30
+
31
+ ```bash
32
+ systemctl is-enabled docker
33
+ ```
34
+
35
+ Use `restart: always` if the container must restart after reboot even when it was manually stopped previously.
36
+
37
+ ## Stop and remove
38
+
39
+ ```bash
40
+ docker compose down
41
+ ```
42
+
43
+ Telemetry is ephemeral and is removed with the container.
44
+
45
+ ## Dashboard attribution
46
+
47
+ The dashboard is adapted from [`NikiforovAll/pi-otel`](https://github.com/NikiforovAll/pi-otel), Copyright 2026 Oleksii Nikiforov, under Apache-2.0. See the repository `NOTICE` and `LICENSES/Apache-2.0.txt` files.
@@ -0,0 +1,16 @@
1
+ services:
2
+ lgtm:
3
+ image: grafana/otel-lgtm:0.29.1@sha256:b4da8bf6b1b44f6f683883869619eb9781465c642ce5f2d70591fb27094ddb1c
4
+ container_name: damngamerz-pi-otel-lgtm
5
+ restart: unless-stopped
6
+ ports:
7
+ - "127.0.0.1:${OTLP_GRPC_PORT:-4317}:4317"
8
+ - "127.0.0.1:${OTLP_HTTP_PORT:-4318}:4318"
9
+ - "127.0.0.1:${GRAFANA_PORT:-33000}:3000"
10
+ volumes:
11
+ - ./dashboard.json:/dashboards/damngamerz-pi-otel.json:ro
12
+ - ./provisioning.yaml:/otel-lgtm/grafana/conf/provisioning/dashboards/damngamerz-pi-otel.yaml:ro
13
+ security_opt:
14
+ - no-new-privileges:true
15
+ cap_drop:
16
+ - ALL