Aspecto blog

On microservices, OpenTelemetry, and anything in between

Instrument Your Node.js Socket.io Apps with OpenTelemetry Like a PRO

socket.io opentelemetry

Share this post

Share on facebook
Share on twitter
Share on linkedin

Today we released a first-of-its-kind OpenTelemetry auto instrumentation plugin.

An OpenTelemetry Socket.io Instrumentation for Node.js.

What makes this instrumentation different?

Well, first, it’s the first full instrumentation for Socket.io ever written.
Second, there are no OpenTelemetry specs for Socket.io or WebSocket; usually, at Aspecto, we try to make our instrumentation as close to the specs as possible, but in this case, we had to improvise.

This is what we chose to do

It seemed reasonable to categorized Socket.io under the messaging specs since we have a producer (emit) a receiver (on) and a message.

Having looked at how other messaging systems with unique characteristics like Kafka do it, we added some custom attributes to the Socket.io traces:
messaging.socket.io.event_name with the event name
messaging.socket.io.rooms with an array of socket.io rooms
messaging.socket.io.namespace with the namespace

So what do you need to do?

First, create a Node.js Socket.io app (need one? We got you)

Now for the fun stuff.
Install OpenTelemetry in your app

npm install \
 @opentelemetry/core \
 @opentelemetry/node \
 @opentelemetry/tracing

Then install our Socket.io instrumentation.

npm install opentelemetry-instrumentation-socket.io

Now, this is the most essential part. Since the plugin patches Socket.io, you must initialize it before any module requires it, so we’re going to put our initialization code at the top of the `index.ts` file.

First, let’s import the files. It should look something like this:

import { NodeTracerProvider } from "@opentelemetry/node";
import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { SocketIoInstrumentation } from "opentelemetry-instrumentation-socket.io"; 
import { ConsoleSpanExporter, SimpleSpanProcessor } from "@opentelemetry/tracing";

And to the exciting part, register our Socket.io instrumentation:

const provider = new NodeTracerProvider();
registerInstrumentations({
 tracerProvider: provider,
 instrumentations: [new SocketIoInstrumentation()],
});

And we are done!

The complete initialization code should look like this:

import { NodeTracerProvider } from "@opentelemetry/node";
import { registerInstrumentations } from "@opentelemetry/instrumentation";
import { SocketIoInstrumentation } from "opentelemetry-instrumentation-socket.io";
import { ConsoleSpanExporter, SimpleSpanProcessor } from "@opentelemetry/tracing";
const provider = new NodeTracerProvider();
registerInstrumentations({
 tracerProvider: provider,
 instrumentations: [new SocketIoInstrumentation()],
});
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();

Now you can run the app and see the traces in the console thanks to the ConsoleSpanExporter.

Here’s is an example trace from stocker.

{
 traceId: ‘e05c479e3d3c7980a1290ef8a8c1d669’,
 parentId: undefined,
 name: ‘/[AAPL] send’,
 id: ‘327a29bf1d58469c’,
 kind: 3,
 timestamp: 1622705582441890,
 duration: 428,
 attributes: {
 ‘messaging.system’: ‘socket.io’,
 ‘messaging.destination_kind’: ‘topic’,
 ‘messaging.socket.io.event_name’: ‘price-update’,
 ‘messaging.socket.io.rooms’: [ ‘AAPL’ ],
 ‘messaging.socket.io.namespace’: ‘/’,
 ‘messaging.destination’: ‘/’
 },
 status: { code: 0 },
 events: []
}

You can find the source code on GitHub.

Isn’t that cool? 😎

Here’s how we visualize Socket.io traces in the Aspecto platform.  🤯

Check out our other awesome instrumentations made with ❤️ including Kafka and aws-sdk instrumentations.

Feel free to reach out to us with any feedback ✌️

Spread the word

Share on facebook
Share on twitter
Share on linkedin
Subscribe for more distributed applications tutorials and insights that will help you boost microservices troubleshooting.