@testdriverai/runner 7.11.70-test → 7.11.71-test

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.
@@ -20,6 +20,7 @@
20
20
  */
21
21
  const Ably = require('ably');
22
22
  const Sentry = require('@sentry/node');
23
+ const betterstack = require('../../shared/betterstack-otel');
23
24
  const http = require('http');
24
25
  const https = require('https');
25
26
  const { EventEmitter } = require('events');
@@ -55,8 +56,12 @@ async function uploadToS3(apiRoot, apiKey, sandboxId, payload, label = 'screensh
55
56
  const fileName = `${label}-${Date.now()}.png`;
56
57
 
57
58
  // Get presigned upload URL from API
58
- // Propagate Sentry trace context so this request appears under the active command span
59
- const traceHeaders = Sentry.getTraceData ? Sentry.getTraceData() : {};
59
+ // Propagate Sentry trace context (sentry-trace + baggage) and W3C traceparent
60
+ // so this request appears under the active span in both Sentry and BetterStack.
61
+ const traceHeaders = {
62
+ ...(Sentry.getTraceData ? Sentry.getTraceData() : {}),
63
+ ...betterstack.getTraceparentHeaders(sandboxId),
64
+ };
60
65
  const uploadUrlResponse = await httpPost(apiRoot, '/api/v7/runner/upload-url', {
61
66
  apiKey,
62
67
  sandboxId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testdriverai/runner",
3
- "version": "7.11.70-test",
3
+ "version": "7.11.71-test",
4
4
  "description": "TestDriver Runner - Ably-based remote automation agent with Node.js automation",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -28,6 +28,14 @@
28
28
  "test:auto-upgrade": "cd ../sdk && npx vitest run --config vitest.runner.config.mjs runner/packer/test/auto-upgrade.test.mjs"
29
29
  },
30
30
  "dependencies": {
31
+ "@opentelemetry/api": "^1.9.0",
32
+ "@opentelemetry/api-logs": "^0.208.0",
33
+ "@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
34
+ "@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
35
+ "@opentelemetry/resources": "^2.2.0",
36
+ "@opentelemetry/sdk-logs": "^0.208.0",
37
+ "@opentelemetry/sdk-trace-base": "^2.2.0",
38
+ "@opentelemetry/sdk-trace-node": "^2.2.0",
31
39
  "@sentry/node": "^10.37.0",
32
40
  "ably": "^2.6.0",
33
41
  "dashcam": "beta",
package/sandbox-agent.js CHANGED
@@ -33,6 +33,7 @@
33
33
  */
34
34
  require('dotenv').config();
35
35
  const Sentry = require('@sentry/node');
36
+ const betterstack = require('../shared/betterstack-otel');
36
37
  const crypto = require('crypto');
37
38
  const fs = require('fs');
38
39
  const os = require('os');
@@ -191,6 +192,29 @@ async function main() {
191
192
  // for stable) BEFORE writing the config, so by this point we're up to date.
192
193
  const config = await waitForConfig(300000);
193
194
 
195
+ // Propagate BetterStack OTLP credentials from the API-supplied config into the
196
+ // process env so betterstack-otel's createSpanProcessor()/init() can pick them
197
+ // up (the sandbox VM has no .env of its own).
198
+ if (config.betterstackSourceToken && !process.env.BETTERSTACK_SOURCE_TOKEN) {
199
+ process.env.BETTERSTACK_SOURCE_TOKEN = config.betterstackSourceToken;
200
+ }
201
+ if (config.betterstackIngestUrl && !process.env.BETTERSTACK_INGEST_URL) {
202
+ process.env.BETTERSTACK_INGEST_URL = config.betterstackIngestUrl;
203
+ }
204
+ if (config.betterstackErrorDsn && !process.env.BETTERSTACK_ERROR_DSN) {
205
+ process.env.BETTERSTACK_ERROR_DSN = config.betterstackErrorDsn;
206
+ }
207
+ if (config.betterstackForce && !process.env.TD_BETTERSTACK_FORCE) {
208
+ process.env.TD_BETTERSTACK_FORCE = 'true';
209
+ }
210
+
211
+ // Build BetterStack's span processor before Sentry.init so it attaches to
212
+ // Sentry's OTel provider (openTelemetrySpanProcessors) and mirrors 100% of spans.
213
+ const betterstackSpanProcessor = betterstack.createSpanProcessor({
214
+ service: 'runner',
215
+ version: require('./package.json').version,
216
+ });
217
+
194
218
  // Initialize Sentry for distributed tracing
195
219
  const sentryDsn = process.env.SENTRY_DSN || config.sentryDsn || 'https://452bd5a00dbd83a38ee8813e11c57694@o4510262629236736.ingest.us.sentry.io/4510480443637760';
196
220
  const runnerChannel = config.sentryChannel || process.env.TD_CHANNEL;
@@ -199,6 +223,7 @@ async function main() {
199
223
  const { version } = require('./package.json');
200
224
  Sentry.init({
201
225
  dsn: sentryDsn,
226
+ openTelemetrySpanProcessors: [betterstackSpanProcessor].filter(Boolean),
202
227
  // Use tracesSampler to inherit parent sampling decisions
203
228
  // This ensures SDK → API → Runner traces stay connected
204
229
  tracesSampler: (samplingContext) => {
@@ -249,6 +274,26 @@ async function main() {
249
274
 
250
275
  Sentry.setTag('sandbox', config.sandboxId);
251
276
  log('Sentry initialized');
277
+
278
+ // Attach BetterStack after Sentry so it shares Sentry's OTel provider and
279
+ // the runner.session span/trace id above is exported to both backends.
280
+ betterstack.init({
281
+ service: 'runner',
282
+ version: require('./package.json').version,
283
+ attributes: {
284
+ 'sandbox.id': config.sandboxId,
285
+ ...(config.sessionId ? { 'session.id': config.sessionId } : {}),
286
+ },
287
+ });
288
+ // Forward errors to BetterStack's error app so releases populate.
289
+ betterstack.initErrorReporting({
290
+ service: 'runner',
291
+ version: require('./package.json').version,
292
+ attributes: {
293
+ 'sandbox.id': config.sandboxId,
294
+ ...(config.sessionId ? { 'session.id': config.sessionId } : {}),
295
+ },
296
+ });
252
297
  }
253
298
  log(`Sandbox ID: ${config.sandboxId}`);
254
299
  log(`Transport: Ably`);
@@ -290,6 +335,7 @@ async function main() {
290
335
  }
291
336
  await ablyService.close();
292
337
  automation.cleanup();
338
+ await betterstack.flush(2000);
293
339
  await Sentry.close(2000);
294
340
  process.exit(0);
295
341
  };