APM integration with ElysiaJS and Bun

Hi,

Has anyone successfully integrated the APM with ElysiaJS and Bun runtime? We kept getting the following message in the console:

APM Server transport error: premature apm-server response with statusCode=202

We tried to manually set the transaction name on our onRequest hook but nothing shows up in the dashboard:

const url = new URL(request.url);
apm.setTransactionName(${request.method} ${url.pathname});

I am also getting this, will post f I find a solution

apm.ts

import apm from 'elastic-apm-node';
export default apm.start({
  serviceName: 'search-service',
  secretToken: process.env.ELASTIC_APM_SECRET_TOKEN!!,
  serverUrl: process.env.ELASTIC_APM_SERVER_URL!!,
  environment: process.env.ELASTIC_APM_ENVIRONMENT!!,
  captureBody: process.env.ELASTIC_APM_CAPTURE_BODY!! as any,
  ignoreUrls: ['/ping'],
  logLevel: process.env.NODE_ENV === 'development' ? 'debug' : 'error'
});

server.ts

import cors from '@elysiajs/cors';
import Elysia from 'elysia';
import apm from './lib/apm';

new Elysia()
  .use(
    cors({
      origin: true,
      methods: ['OPTIONS', 'GET', 'DELETE'],
      allowedHeaders: ['Content-Type'],
      exposedHeaders: '*',
      credentials: false,
      preflight: true,
      maxAge: 86400
    })
  )
  .onRequest(({ request }) => {
    const url = new URL(request.url),
      pathname = url.pathname;

    if (pathname !== '/ping') {
      apm.startTransaction();
      apm.setTransactionName(`${request.method} ${pathname}`);
    }
  })
  .onAfterHandle(() => {
    apm.endTransaction();
  })

  .get('/ping', ({ set }) => {
    set.status = 200;
    return 'pong';
  })
  .listen(process.env.SERVICE_PORT ?? 5001);

@zx8086 I finally was able to capture stuff. It's more of a manual effort since the apm doesn't seem to be able to hook into Elysia's framework. If you want to capture requests downstream, you're going to have to instrument it yourself:

async function downStreamCall() {
const span: Span | null = apm.startSpan(`GET ${url.pathname}`);
// fetch()
span.end();
}

I was getting there since using Opentelemetry Bridge

Also work-around for the error is to set this in your apm.ts->

contextPropagationOnly: true,

import * as https from 'https';
import * as otel from '@opentelemetry/api';

const tracer = otel.trace.getTracer('trace-https-request');

tracer.startActiveSpan('makeRequest', span => {
  https.get('https://httpstat.us/200', (response) => {
    console.log('STATUS:', response.statusCode);
    const body: Buffer[] = [];
    response.on('data', (chunk: Buffer) => body.push(chunk));
    response.on('end', () => {
      console.log('BODY:', Buffer.concat(body).toString());
      span.end();
    });
  });
});

Ahh make sense. Not too familiar but looks very similar.

Are you sending the APM logs / specifying a logger ?

nope just the console log. I’m using the Bun runtime and the node apm doesn’t auto send transactions so I had to manually instrument them.