opentelemetry-js icon indicating copy to clipboard operation
opentelemetry-js copied to clipboard

ConsoleSpanExporter not logging anything for Custom Spans for prebuilds

Open jinja12 opened this issue 1 year ago • 3 comments
trafficstars

I have a basic NextJS application, inside which there are some custom build scripts which run as prebuild alongside the default next build package.json:

  "scripts": {
    "dev": "next dev",
    "build": "node prebuild.js && next build",
    "start": next start",
    "lint": "next lint"
  },

The prebuild.js file:

const { execSync } = require("child_process");
const {
  diag,
  DiagConsoleLogger,
  DiagLogLevel,
  trace,
  context,
} = require("@opentelemetry/api");
const { NodeSDK } = require("@opentelemetry/sdk-node");
const {
  getNodeAutoInstrumentations,
} = require("@opentelemetry/auto-instrumentations-node");
const {
  ConsoleSpanExporter,
  SimpleSpanProcessor,
} = require("@opentelemetry/sdk-trace-base");
const {
  envDetectorSync,
  hostDetectorSync,
  processDetectorSync,
} = require("@opentelemetry/resources");

function awaitAttributes(detector) {
  return {
    async detect(config) {
      const resource = detector.detect(config);
      await resource.waitForAsyncAttributes?.();
      return resource;
    },
  };
}

diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);

// Initialize the OpenTelemetry SDK with ConsoleSpanExporter
const sdk = new NodeSDK({
  traceExporter: new ConsoleSpanExporter(),
  spanProcessors: [new SimpleSpanProcessor(new ConsoleSpanExporter())],
  instrumentations: [getNodeAutoInstrumentations()],
  resourceDetectors: [
    awaitAttributes(envDetectorSync),
    awaitAttributes(processDetectorSync),
    awaitAttributes(hostDetectorSync),
  ],
});

// Start the SDK
sdk.start();

async function buildPackage(packagePath) {
  const tracer = trace.getTracer("custom-tracer");
  const span = tracer.startSpan(`Building ${packagePath}`, {
    attributes: { packagePath },
  });
  return context.with(trace.setSpan(context.active(), span), async () => {
    try {
      console.log(`Building package at ${packagePath}...`);
      execSync(`cd ${packagePath} && npm run build`, { stdio: "inherit" });
      span.addEvent("Package build complete", {
        packagePath,
        timestamp: Date.now(),
      });
    } catch (error) {
      span.recordException(error);
      console.error(`Error building ${packagePath}: ${error}`);
    } finally {
      console.log("Logging span after finally");
      console.log("Span Context: " + JSON.stringify(span.spanContext()));
      span.end();
      console.log(`Span ended for package ${packagePath}`);
    }
  });
}

async function main() {
  const packages = ["./packages_test/package1", "./packages_test/package2"];
  for (const packagePath of packages) {
    await buildPackage(packagePath);
  }

  // Shutdown the OpenTelemetry SDK properly
  await sdk
    .shutdown()
    .then(() => {
      console.log("Tracing terminated");
      process.exit(0);
    })
    .catch((error) => {
      console.error("Error terminating tracing", error);
      process.exit(1);
    });
}

main();

So basically packages_test/package1 and packages_test/package2 are my custom packages which I build inside this script. Inside their package.json file: I just initiate a sleep of some short duration around 2-5s to simulate build time inside scripts build.

UseCase: Now my aim is to get relevant Telemetry data for my build process and get an idea about the build times and other data for all builds which happen including the prebuilds. I enclosed the build process in my prebuilds script inside a span and was hoping that after span.end(), the trace details are logged automatically on my console. Nothing of that sort is logged, to test if my trace was even being initialized or not, I added console logs for my span context. Following is the log:

image

I am not sure why is this not working as expected (trace details not logged after span end), any insights into this would be highly appreciated. Also, it would be great if one could suggest alternative better approaches to solve the use case which I am trying to solve. Thanks!

jinja12 avatar Jun 26 '24 19:06 jinja12