trigger.dev icon indicating copy to clipboard operation
trigger.dev copied to clipboard

bug: Laminar traces missing in span view but present in export

Open p3droml opened this issue 4 months ago • 3 comments

Provide environment information

System: OS: Linux 6.6 Ubuntu 22.04.5 LTS 22.04.5 LTS (Jammy Jellyfish) CPU: (12) x64 Intel(R) Core(TM) i7-10710U CPU @ 1.10GHz Memory: 11.96 GB / 15.52 GB Container: Yes Shell: 5.1.16 - /bin/bash Binaries: Node: 20.18.2 - ~/.nvm/versions/node/v20.18.2/bin/node npm: 11.5.2 - ~/.nvm/versions/node/v20.18.2/bin/npm

Describe the bug

run_cmfp1ifv801dl2fn21qsxa70b.log

Image

Reproduction repo

NA

To reproduce

// @ts-ignore - Laminar observe import issue for testing purposes
import { task } from "@trigger.dev/sdk/v3";
import { Laminar, observe } from "@lmnr-ai/lmnr";


// Example task to reproduce console.log issue inside Laminar observe
export const consoleLogTest = task({
    id: "console-log-test",
    maxDuration: 300,
    machine: "small-1x",
    run: async (payload: { message: string }) => {
        console.log("=== OUTSIDE OBSERVE ===");
        console.log("This console.log should appear on trigger.dev");
        console.info("This console.info should appear on trigger.dev");

        Laminar.initialize({
            projectApiKey: process.env.LMNR_PROJECT_API_KEY,
            disableBatch: true
        });

        console.log("=== BEFORE OBSERVE ===");
        console.log("About to enter Laminar observe block");

        await observe({ name: "test-observe-block", sessionId: "test-session-123" }, async () => {
            console.log("=== INSIDE OBSERVE BLOCK ===");
            console.log("This console.log is INSIDE observe - does it appear?");
            console.info("This console.info is INSIDE observe - does it appear?");
            console.warn("This console.warn is INSIDE observe - does it appear?");
            console.error("This console.error is INSIDE observe - does it appear?");

            // Simulate some work
            await new Promise(resolve => setTimeout(resolve, 1000));

            console.log("Still inside observe, after 1 second delay");
            console.log(`Payload message: ${payload.message}`);

            // Nested operations
            const result = await observe({ name: "nested-observe", sessionId: "nested-session-456" }, async () => {
                console.log("=== INSIDE NESTED OBSERVE ===");
                console.log("This is a nested observe block");
                console.info("Nested console.info test");

                return { nestedResult: "completed" };
            });

            console.log("Back in main observe block");
            console.log(`Nested result: ${JSON.stringify(result)}`);

            return { mainResult: "completed", payload: payload.message };
        });

        console.log("=== AFTER OBSERVE ===");
        console.log("Exited Laminar observe block");
        console.log("This should appear after observe completes");

        return {
            success: true,
            message: "Console log test completed",
            payloadMessage: payload.message
        };
    }
});

Additional information

No response

p3droml avatar Sep 18 '25 06:09 p3droml

Hi @p3droml - thanks for reporting this!

Looks like observe() implicitly creates its own trace context, as we can see from the differing trace IDs here:

Image

Probably best for @ericallam to have a look

nicktrn avatar Sep 18 '25 07:09 nicktrn

@p3droml I'm wondering if you need to use the observe function, and if you can use our span function instead.

  1. Add the Laminar OpenTelemetry exporter to your trigger.config file https://trigger.dev/docs/config/config-file#telemetry-exporters
  2. Use our logger.trace function: https://trigger.dev/docs/logging#add-custom-traces

We should try figure out how to play nicely with Laminar, but it might be tricky given they don't respect the existing OTEL trace context.

matt-aitken avatar Sep 18 '25 11:09 matt-aitken

hey @matt-aitken, Robert from Laminar here. We moved to managing our own context when we discovered that auto-instrumentation from DataDog "poisons" global otel context. They had extremely small and stupid bug that they haven't patched for ages.

We also have an option to use global context instead, we will write better docs about it. @p3droml thank you for raising this!

skull8888888 avatar Sep 18 '25 15:09 skull8888888