Usage
Inngest supports OpenTelemetry for distributed tracing and observability across your functions. The extendedTracesMiddleware automatically instruments your Inngest functions and integrates with your existing OpenTelemetry providers, giving you deep insights into function execution, step timing, and performance. It includes automatic instrumentation for many popular libraries.
Basic Usage
Import and run the extendedTracesMiddleware() before any other code.
This ensures that the tracer
provider
and any
instrumentation has
time to patch code in order to collect traces and spans from all parts of your
application. Loading running extendedTracesMiddleware() after any other code risks not
instrumenting it.
For example,
// Import this first
import { extendedTracesMiddleware } from "inngest/experimental";
const extendedTraces = extendedTracesMiddleware();
// Then everything else
import { Inngest } from "inngest";
const inngest = new Inngest({
id: "my-app",
middleware: [extendedTraces],
});
Serverless
If you're using serverless, the entrypoint of your app will likely be the file
for a particular endpoint, for example /api/inngest.
If you have your client set up as in the example above, make sure you import that first so that the provider has a chance to initialize.
// Import the client first
import { inngest } from "@/inngest";
// Then import everything else
import { serve } from "inngest/next";
import { myFn } from "@/inngest/functions";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: [myFn],
});
Extending existing providers
A JavaScript process can only have a single OpenTelemetry Provider. Some libraries such as Sentry also create their own provider.
extendedTracesMiddleware() will first try to extend an existing provider and will only
create one if none has been found. If an existing provider is extended, we won't
contribute any automatic instrumentation.
In the case of Sentry, extendedTracesMiddleware() will extend Sentry's provider as long
as it's run after Sentry.init().
This extension should also work for OpenTelemetry providers that originate within the runtime, like Deno's OpenTelemetry.
This behaviour can be changed:
extendedTracesMiddleware({
behaviour: "auto",
});
The options are:
"auto"(default): Attempt to extend a provider if one exists, else create one, fails if neither worked"extendProvider": Only attempt to extend a provider and fails if none exists"createProvider": Only attempt to create a provider and fails if we couldn't"off": Do nothing
If you're intending to only use extendedTracesMiddleware() to extend an existing
provider, you no longer need to ensure that it is called before any other code.
Manually extend
If you're already manually creating your own trace provider and import ordering
is an issue, you may want to manually add Inngest's InngestSpanProcessor to
your existing setup.
Add an InngestSpanExporter to your provider:
// Create your client the same as you would normally
import { Inngest } from "inngest";
import { extendedTracesMiddleware } from "inngest/experimental";
export const inngest = new Inngest({
id: "my-app",
middleware: [
extendedTracesMiddleware({
// Make sure the middleware doesn't try to automatically instrument
behaviour: "off",
}),
],
});
```ts
// Then when you create your provider, pass the client to it
import { inngest } from "@/inngest";
import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
import { InngestSpanProcessor } from "inngest/experimental";
const provider = new BasicTracerProvider({
// Add the span processor when creating your provider
spanProcessors: [new InngestSpanProcessor(inngest)],
});
// Register the provider globally
provider.register();
Instrumentation
extendedTracesMiddleware() will automatically instrument common code for you if it's
used to create your provider.
Here's a list of automatic supported instrumentation:
- amqplib
- AWS Lambda
- AWS SDK for JavaScript v3
- bunyan
- cassandra-driver
- connect
- @cucumber/cucumber
- dataloader
- dns
- express
- fs
- generic-pool
- graphql
- @grpc/grpc-js
- Hapi framework
- http and https
- ioredis
- kafkajs
- knex
- Koa
- lru-memoizer
- memcached
- mongodb
- mongoose
- mysql
- mysql2
- NestJS framework
- net
- pg
- pino
- redis
- restify
- socket.io
- undici (Node.js global fetch API)
- winston
Custom instrumentation
You can add additional custom instrumentations to gain more insight into your stack.
For example, here's an example of adding Prisma OpenTelemetry:
import { PrismaInstrumentation } from "@prisma/instrumentation";
import { extendedTracesMiddleware } from "inngest/experimental";
const extendedTraces = extendedTracesMiddleware({
instrumentations: [new PrismaInstrumentation()],
});