From a6ed26f8eb7e272592e6d9e146bd4b587623b99b Mon Sep 17 00:00:00 2001 From: elkaix Date: Mon, 24 Aug 2026 16:26:08 -0400 Subject: [PATCH 1/2] fix(telemetry): emit the pfc_ event prefix the ingest service routes on The telemetry ingest service selects crash events by the exact name `pfc_crash` and its dashboards query `pfc_*`. The client was emitting `kfc_*`, so every crash report was dropped at ingest and ordinary events were invisible to the dashboards. Restore both outbound prefixes and lock them with JSDoc so a future edit has to acknowledge the wire contract. --- .../src/app/telemetry/cloudTransport.ts | 6 +++-- .../test/app/telemetry/cloudAppender.test.ts | 4 ++-- packages/telemetry/src/transport.ts | 6 +++-- packages/telemetry/test/telemetry.test.ts | 24 +++++++++---------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/agent-core-v2/src/app/telemetry/cloudTransport.ts b/packages/agent-core-v2/src/app/telemetry/cloudTransport.ts index dfcc4781..95f1bfac 100644 --- a/packages/agent-core-v2/src/app/telemetry/cloudTransport.ts +++ b/packages/agent-core-v2/src/app/telemetry/cloudTransport.ts @@ -48,8 +48,10 @@ export interface CloudTransportOptions { } export const TELEMETRY_ENDPOINT = 'https://telemetry-logs.pythinker.com/v1/event'; -export const SERVER_EVENT_PREFIX = 'kfc_'; -export const USER_ID_PREFIX = 'kfc_device_id_'; +/** Do not change this Pythinker wire prefix. SigNoz dashboards query `pfc_*` events. */ +export const SERVER_EVENT_PREFIX = 'pfc_'; +/** Do not change this Pythinker identity prefix. SigNoz device queries depend on it. */ +export const USER_ID_PREFIX = 'pfc_device_id_'; export const DISK_EVENT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; export const RETRY_BACKOFFS_MS = [1_000, 4_000, 16_000] as const; diff --git a/packages/agent-core-v2/test/app/telemetry/cloudAppender.test.ts b/packages/agent-core-v2/test/app/telemetry/cloudAppender.test.ts index 212f6421..170999cd 100644 --- a/packages/agent-core-v2/test/app/telemetry/cloudAppender.test.ts +++ b/packages/agent-core-v2/test/app/telemetry/cloudAppender.test.ts @@ -96,9 +96,9 @@ describe('CloudAppender', () => { expect(requests).toHaveLength(1); expect(requests[0]?.url).toBe('https://telemetry-logs.pythinker.com/v1/event'); - expect(requests[0]?.body.user_id).toBe('kfc_device_id_dev123'); + expect(requests[0]?.body.user_id).toBe('pfc_device_id_dev123'); const event = requests[0]?.body.events[0]; - expect(event?.['event']).toBe('kfc_tool.call'); + expect(event?.['event']).toBe('pfc_tool.call'); expect(event?.['device_id']).toBe('dev123'); expect(event?.['session_id']).toBe('sess1'); expect(event?.['property_name']).toBe('bash'); diff --git a/packages/telemetry/src/transport.ts b/packages/telemetry/src/transport.ts index 8dd1ad87..4e8af111 100644 --- a/packages/telemetry/src/transport.ts +++ b/packages/telemetry/src/transport.ts @@ -14,8 +14,10 @@ import type { EnrichedTelemetryEvent, TelemetryPrimitive } from './types'; import { isTelemetryPrimitive } from './types'; export const TELEMETRY_ENDPOINT = 'https://telemetry-logs.pythinker.com/v1/event'; -export const SERVER_EVENT_PREFIX = 'kfc_'; -export const USER_ID_PREFIX = 'kfc_device_id_'; +/** Do not change this Pythinker wire prefix. SigNoz dashboards query `pfc_*` events. */ +export const SERVER_EVENT_PREFIX = 'pfc_'; +/** Do not change this Pythinker identity prefix. SigNoz device queries depend on it. */ +export const USER_ID_PREFIX = 'pfc_device_id_'; export const DISK_EVENT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; export const RETRY_BACKOFFS_MS = [1_000, 4_000, 16_000] as const; diff --git a/packages/telemetry/test/telemetry.test.ts b/packages/telemetry/test/telemetry.test.ts index ae794e88..b4903069 100644 --- a/packages/telemetry/test/telemetry.test.ts +++ b/packages/telemetry/test/telemetry.test.ts @@ -410,7 +410,7 @@ describe('payload assembly', () => { it('adds server event prefix, payload user id, and flattened fields', () => { const payload = buildPayload([sampleEvent('started')], 'device-1'); - expect(payload.user_id).toBe('kfc_device_id_device-1'); + expect(payload.user_id).toBe('pfc_device_id_device-1'); expect(payload.events[0]).toMatchObject({ event_id: 'event-1', device_id: 'device-1', @@ -426,9 +426,9 @@ describe('payload assembly', () => { }); it('does not double-prefix already-prefixed events', () => { - const payload = buildPayload([sampleEvent('kfc_started')], 'device-1'); + const payload = buildPayload([sampleEvent('pfc_started')], 'device-1'); - expect(payload.events[0]?.['event']).toBe('kfc_started'); + expect(payload.events[0]?.['event']).toBe('pfc_started'); }); it('rejects nested property values before outbound send', () => { @@ -484,7 +484,7 @@ describe('payload assembly', () => { const payload = buildPayload([event], 'device-1'); expect(payload.events[0]).toMatchObject({ - event: 'kfc_nullable', + event: 'pfc_nullable', property_empty: null, }); expect(event.properties).toBe(originalProperties); @@ -495,8 +495,8 @@ describe('payload assembly', () => { describe('server prefix application', () => { it('locks the outbound telemetry prefixes', () => { - expect(SERVER_EVENT_PREFIX).toBe('kfc_'); - expect(USER_ID_PREFIX).toBe('kfc_device_id_'); + expect(SERVER_EVENT_PREFIX).toBe('pfc_'); + expect(USER_ID_PREFIX).toBe('pfc_device_id_'); }); it('returns a new object only when adding the server prefix', () => { @@ -505,12 +505,12 @@ describe('server prefix application', () => { const prefixed = applyServerPrefix(event); expect(prefixed).not.toBe(event); - expect(prefixed.event).toBe('kfc_started'); + expect(prefixed.event).toBe('pfc_started'); expect(event.event).toBe('started'); }); it('passes already-prefixed and invalid event names through unchanged', () => { - const prefixed = sampleEvent('kfc_started'); + const prefixed = sampleEvent('pfc_started'); const emptyName = sampleEvent(''); const missingName = { ...sampleEvent('missing') } as unknown as Record; delete missingName['event']; @@ -547,7 +547,7 @@ describe('AsyncTransport', () => { const init = requestInitFrom(fetchImpl); expect(init.headers).toMatchObject({ Authorization: 'Bearer token-1' }); expect(JSON.parse(init.body as string)).toMatchObject({ - user_id: 'kfc_device_id_dev', + user_id: 'pfc_device_id_dev', }); }); @@ -696,7 +696,7 @@ describe('AsyncTransport', () => { const init = requestInitFrom(fetchImpl); const payload = JSON.parse(init.body as string) as { events: Array<{ event: string }> }; - expect(payload.events[0]?.['event']).toBe('kfc_from_disk'); + expect(payload.events[0]?.['event']).toBe('pfc_from_disk'); expect(() => statSync(file)).toThrow(); }); @@ -790,7 +790,7 @@ describe('AsyncTransport', () => { properties: { resumed: false, count: 2 }, }); expect(file).not.toContain('user_id'); - expect(file).not.toContain('kfc_first'); + expect(file).not.toContain('pfc_first'); }); it('does not create a disk file for an empty batch or a schema violation', async () => { @@ -867,7 +867,7 @@ describe('telemetry bootstrap', () => { events: Array<{ event: string; session_id: string }>; }; expect(payload.events[0]).toMatchObject({ - event: 'kfc_before_init', + event: 'pfc_before_init', session_id: 'ses', }); }); From b5ead8b1db7af387a7898cced361214d37e77f04 Mon Sep 17 00:00:00 2001 From: elkaix Date: Mon, 24 Aug 2026 16:30:48 -0400 Subject: [PATCH 2/2] chore: add telemetry dashboard changeset --- .changeset/fix-telemetry-dashboard.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fix-telemetry-dashboard.md diff --git a/.changeset/fix-telemetry-dashboard.md b/.changeset/fix-telemetry-dashboard.md new file mode 100644 index 00000000..69c6af0b --- /dev/null +++ b/.changeset/fix-telemetry-dashboard.md @@ -0,0 +1,5 @@ +--- +"@pymodel/pythinker-code": patch +--- + +Restore telemetry events and active devices in observability dashboards.