@townco/agent 0.1.51 → 0.1.52

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.
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * OpenTelemetry provider setup for @townco/agent
3
- * Initializes the trace provider, exporter, and propagator
3
+ * Initializes the trace provider, log provider, exporters, and propagator
4
4
  */
5
5
  import { propagation } from "@opentelemetry/api";
6
+ import { logs } from "@opentelemetry/api-logs";
6
7
  import { W3CTraceContextPropagator } from "@opentelemetry/core";
8
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
7
9
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
8
10
  import { Resource } from "@opentelemetry/resources";
11
+ import { BatchLogRecordProcessor, LoggerProvider, } from "@opentelemetry/sdk-logs";
9
12
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
10
13
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
11
14
  import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
@@ -83,13 +86,38 @@ export function initializeOpenTelemetry(options = {}) {
83
86
  const batchProcessor = new BatchSpanProcessor(loggingExporter, {
84
87
  maxQueueSize: 100,
85
88
  maxExportBatchSize: 10,
86
- scheduledDelayMillis: 5000, // Export every 5 seconds (default)
89
+ scheduledDelayMillis: 2000, // Export every 2 seconds
87
90
  });
88
91
  provider.addSpanProcessor(batchProcessor);
89
92
  // Register the provider globally
90
93
  provider.register();
91
94
  // Configure W3C Trace Context propagator for cross-process traces
92
95
  propagation.setGlobalPropagator(new W3CTraceContextPropagator());
96
+ // Set up LoggerProvider for OTLP log export
97
+ const logUrl = otlpEndpoint.endsWith("/")
98
+ ? `${otlpEndpoint}v1/logs`
99
+ : `${otlpEndpoint}/v1/logs`;
100
+ if (debug) {
101
+ console.log(`OTLP log URL: ${logUrl}`);
102
+ }
103
+ const logExporter = new OTLPLogExporter({
104
+ url: logUrl,
105
+ });
106
+ const loggerProvider = new LoggerProvider({
107
+ resource: new Resource({
108
+ [ATTR_SERVICE_NAME]: serviceName,
109
+ }),
110
+ });
111
+ loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter, {
112
+ maxQueueSize: 100,
113
+ maxExportBatchSize: 10,
114
+ scheduledDelayMillis: 2000,
115
+ }));
116
+ // Register the logger provider globally
117
+ logs.setGlobalLoggerProvider(loggerProvider);
118
+ if (debug) {
119
+ console.log("✓ Log exporter configured");
120
+ }
93
121
  // Now configure our telemetry wrapper
94
122
  configureTelemetry({
95
123
  enabled: true,
@@ -106,6 +134,8 @@ export function initializeOpenTelemetry(options = {}) {
106
134
  try {
107
135
  await provider.forceFlush();
108
136
  await provider.shutdown();
137
+ await loggerProvider.forceFlush();
138
+ await loggerProvider.shutdown();
109
139
  if (debug) {
110
140
  console.log("✓ Telemetry flushed");
111
141
  }
@@ -114,7 +144,7 @@ export function initializeOpenTelemetry(options = {}) {
114
144
  console.error("Error flushing telemetry:", error);
115
145
  }
116
146
  };
117
- return { provider, shutdown };
147
+ return { provider, loggerProvider, shutdown };
118
148
  }
119
149
  /**
120
150
  * Initialize OpenTelemetry from environment variables and register shutdown handlers
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Simple test script to verify OpenTelemetry is working
3
+ * Run with: ENABLE_TELEMETRY=true DEBUG_TELEMETRY=true bun test-telemetry.ts
4
+ */
5
+ export {};
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Simple test script to verify OpenTelemetry is working
3
+ * Run with: ENABLE_TELEMETRY=true DEBUG_TELEMETRY=true bun test-telemetry.ts
4
+ */
5
+ import { makeRunnerFromDefinition } from "./runner/index.js";
6
+ import { configureTelemetry } from "./telemetry/index.js";
7
+ // Initialize OpenTelemetry
8
+ console.log("🔧 Initializing OpenTelemetry...");
9
+ const { NodeTracerProvider } = await import("@opentelemetry/sdk-trace-node");
10
+ const { BatchSpanProcessor } = await import("@opentelemetry/sdk-trace-base");
11
+ const { OTLPTraceExporter } = await import("@opentelemetry/exporter-trace-otlp-grpc");
12
+ const { Resource } = await import("@opentelemetry/resources");
13
+ const { ATTR_SERVICE_NAME } = await import("@opentelemetry/semantic-conventions");
14
+ const serviceName = "test-agent";
15
+ const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://localhost:4317";
16
+ console.log(`📡 Service: ${serviceName}`);
17
+ console.log(`📡 Endpoint: ${otlpEndpoint}`);
18
+ const provider = new NodeTracerProvider({
19
+ resource: new Resource({
20
+ [ATTR_SERVICE_NAME]: serviceName,
21
+ }),
22
+ });
23
+ const exporter = new OTLPTraceExporter({
24
+ url: otlpEndpoint,
25
+ });
26
+ provider.addSpanProcessor(new BatchSpanProcessor(exporter));
27
+ provider.register();
28
+ configureTelemetry({
29
+ enabled: true,
30
+ serviceName,
31
+ attributes: {
32
+ "test.run": "true",
33
+ },
34
+ });
35
+ console.log("✅ OpenTelemetry initialized\n");
36
+ // Create a simple test agent
37
+ console.log("🤖 Creating test agent...");
38
+ const runner = makeRunnerFromDefinition({
39
+ model: "claude-sonnet-4-5-20250929",
40
+ systemPrompt: "You are a helpful assistant. Keep responses brief.",
41
+ tools: ["get_weather"],
42
+ });
43
+ console.log("✅ Agent created\n");
44
+ // Run a simple test invocation
45
+ console.log("🚀 Running test invocation...");
46
+ const result = runner.invoke({
47
+ prompt: [
48
+ {
49
+ type: "text",
50
+ text: "What's the weather like in San Francisco?",
51
+ },
52
+ ],
53
+ sessionId: "test-session-123",
54
+ messageId: "test-msg-1",
55
+ });
56
+ console.log("📨 Processing response...\n");
57
+ let tokenCount = 0;
58
+ let toolCalls = 0;
59
+ for await (const chunk of result) {
60
+ if (chunk.sessionUpdate === "tool_call") {
61
+ console.log(`🔧 Tool called: ${chunk.title}`);
62
+ toolCalls++;
63
+ }
64
+ else if (chunk.sessionUpdate === "agent_message_chunk") {
65
+ if (chunk.content.type === "text") {
66
+ process.stdout.write(chunk.content.text);
67
+ }
68
+ if (chunk._meta &&
69
+ "tokenUsage" in chunk._meta &&
70
+ chunk._meta.tokenUsage &&
71
+ typeof chunk._meta.tokenUsage === "object" &&
72
+ "outputTokens" in chunk._meta.tokenUsage) {
73
+ tokenCount += chunk._meta.tokenUsage.outputTokens ?? 0;
74
+ }
75
+ }
76
+ }
77
+ console.log("\n\n✅ Test completed!");
78
+ console.log(`📊 Stats: ${toolCalls} tool calls, ~${tokenCount} output tokens`);
79
+ // Force flush before exit
80
+ console.log("\n⏳ Flushing telemetry data...");
81
+ await provider.forceFlush();
82
+ console.log("✅ Telemetry flushed!");
83
+ console.log("\n🎯 Check Jaeger UI at: http://localhost:16686");
84
+ console.log(` Service: ${serviceName}`);
85
+ console.log(` Look for "agent.invoke" spans`);
86
+ // Give a moment for final flush
87
+ await new Promise((resolve) => setTimeout(resolve, 1000));
88
+ process.exit(0);