microservice-support-toolkit
Version:
A global module with commons utilities for microservice support
86 lines (68 loc) • 2.48 kB
JavaScript
const { BatchRecorder, jsonEncoder, Tracer, Instrumentation } = require('zipkin');
const { expressMiddleware, wrapExpressHttpProxy } = require('zipkin-instrumentation-express');
const { HttpLogger } = require('zipkin-transport-http');
const axios = require('axios');
const proxy = require('express-http-proxy');
const CLSContext = require('zipkin-context-cls');
let tracer = null;
const zipkinMiddleware = (req, res, next, { serviceName, endpoint, enable }) => {
if (enable) {
const ctxImpl = new CLSContext();
const recorder = new BatchRecorder({
logger: new HttpLogger({
endpoint: endpoint,
jsonEncoder: jsonEncoder.JSON_V2,
})
});
tracer = new Tracer({ ctxImpl, recorder, localServiceName: serviceName });
zipkinAxiosInterceptorsSetup(serviceName);
return expressMiddleware({
tracer,
serviceName
});
} else {
return (req, res, next) => next()
}
};
const zipkinAxiosInterceptorsSetup = (serviceName) => {
let remoteServiceName = null;
let instrumentation = null;
const zipkinRecordRequest = (config) => {
return tracer.scoped(() => {
const url = new URL(config.url);
const searchParams = new URLSearchParams(url.search);
remoteServiceName = (searchParams.get('serviceName') || url.hostname || 'unknown');
instrumentation = new Instrumentation.HttpClient({ tracer, serviceName, remoteServiceName });
let newConfig = instrumentation.recordRequest(config, config.url, config.method);
newConfig.traceId = tracer.id;
return newConfig;
});
};
const zipkinRecordResponse = (res) => {
return tracer.scoped(() => {
instrumentation.recordResponse(res.config.traceId, res.status);
return res;
});
};
const zipkinRecordError = (error) => {
return tracer.scoped(() => {
if (error.config) {
const traceId = error.config.traceId;
if (error.response) {
instrumentation.recordResponse(traceId, error.response.status);
} else {
instrumentation.recordError(traceId, error);
}
}
return Promise.reject(error);
});
};
axios.interceptors.request.use(zipkinRecordRequest, zipkinRecordError);
axios.interceptors.response.use(zipkinRecordResponse, zipkinRecordError);
};
const zipkinProxy = (host, remoteServiceName) =>
wrapExpressHttpProxy(proxy(host), { tracer, remoteServiceName });
module.exports = {
zipkinMiddleware,
zipkinProxy
};