UNPKG

microservice-support-toolkit

Version:

A global module with commons utilities for microservice support

86 lines (68 loc) 2.48 kB
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 };