Creating a custom jaeger plugin to Monitor and troubleshoot complex distributed systems.

As on-the-ground micro-service practitioners are quickly realizing, the majority of operational problems that arise when moving to a distributed architecture are ultimately grounded in two areas: networking and observability. It is simply an orders of magnitude larger problem to network and debug a set of intertwined distributed services versus a single monolithic application.

Image for post
Image for post

Why open tracing?

Jaeger terminology and components

Image for post
Image for post
Image for post
Image for post
export function logger(span, event, data) {
span.log({ event: event, value: data })
span.finish();
}
export function head(request, name) {
let ctx = request.ctx;
return ctx.tracer.startSpan(name, { childOf: ctx.span });
}
import fastify from 'fastify';
import {Span, Tracer} from 'opentracing';
export default async function(req: fastify.FastifyRequest, res, next){
const ip = req.ips;
let source = req.headers['user-agent'] || ''

if (req.headers['x-ucbrowser-ua']) { //special case of UC Browser
source = req.headers['x-ucbrowser-ua'];
}
const tracer = req['jaeger']().tracer as Tracer;
const span = req['jaeger']().span as Span;
req['useragent'] = {
ip: ip,
userAgent: source
}
req['ctx'] = { span, tracer }
return
}

How to use it in your service

import jaegerCustomPlugin from './libraries/tracer/jaegerCustomPlugin';
const host = process.env.HOST || (require('../config/url.json')[process.env.NODE_ENV]).host;const scheme = process.env.SCHEME || (require('../config/url.json')[process.env.NODE_ENV]).scheme;const expose = process.env.NODE_ENV === 'production' ? false : true;const configs = (require('../config/url.json')[process.env.NODE_ENV]);app.register(jaegerCustomPlugin, {
serviceName: process.env.PROJECT_NAME,
reporter: {
agentHost: configs.jaeger.host,
agentPort: configs.jaeger.port
}
});
"jaeger": {
"host": "localhost",
"port": 6832
},
import {logger, head} from '../../../libraries/tracer/logger';
const createUserSchema: RouteSchema = {
tags: [`${action}`], summary: `Login to app`,
body: Requests.requestBody(userInterface, ['email', 'password']),
}
app.post('/auth', { schema: createUserSchema}, async(request, response) => {let span = head(request, 'GATEWAY USER AUTHENTICATION: Login user');
let user;
try {
user = await requestmaker({
service: 'auth',
action: 'user/auth',
method: 'POST',
data: request.body,
ctx: request['ctx']
})
} catch (ex) {
return response.code(400).send(ex)
}
logger(span, "login", user);
response.send(user);
});
done();
};

Written by

I am an experienced back-end software engineer adept in bringing forth expertise in design, installation, testing and maintenance of software systems.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store