@stoplight/moleculer
Version:
Fast & powerful microservices framework for Node.JS
148 lines (128 loc) • 3.38 kB
JavaScript
;
const _ = require("lodash");
const BaseTraceExporter = require("./base");
const { isObject, isFunction } = require("../../utils");
/**
* Event Trace Exporter. It sends same trace events as in Moleculer <= v0.13.
*
* @class EventLegacyTraceExporter
*/
class EventLegacyTraceExporter extends BaseTraceExporter {
/**
* Creates an instance of EventLegacyTraceExporter.
* @param {Object?} opts
* @memberof EventLegacyTraceExporter
*/
constructor(opts) {
super(opts);
this.opts = _.defaultsDeep(this.opts, {});
}
/**
* Initialize Trace Exporter.
*
* @param {Tracer} tracer
* @memberof EventLegacyTraceExporter
*/
init(tracer) {
super.init(tracer);
this.broker = tracer.broker;
}
/**
* Span is started.
*
* @param {Span} span
* @memberof BaseTraceExporter
*/
spanStarted(span) {
if (
span.tags.eventName == "metrics.trace.span.start" ||
span.tags.eventName == "metrics.trace.span.finish"
)
return;
const payload = this.generateMetricPayload(span);
this.broker.emit("metrics.trace.span.start", payload);
}
/**
* Span is finished.
*
* @param {Span} span
* @memberof EventLegacyTraceExporter
*/
spanFinished(span) {
if (
span.tags.eventName == "metrics.trace.span.start" ||
span.tags.eventName == "metrics.trace.span.finish"
)
return;
const payload = this.generateMetricPayload(span);
this.broker.emit("metrics.trace.span.finish", payload);
}
/**
* Generate metrics payload
*
* @param {Context} ctx
* @returns {Object}
*/
generateMetricPayload(span) {
let payload = {
id: span.id,
requestID: span.traceID,
level: span.tags.callingLevel,
startTime: span.startTime,
remoteCall: span.tags.remoteCall
};
// Process extra metrics
if (span.opts.ctx) this.processExtraMetrics(span.opts.ctx, payload);
payload.action = span.tags.action;
payload.service = span.service;
if (span.parentID) payload.parent = span.parentID;
payload.nodeID = this.broker.nodeID;
if (payload.remoteCall) payload.callerNodeID = span.tags.callerNodeID;
if (span.finishTime) {
payload.endTime = span.finishTime;
payload.duration = span.duration;
payload.fromCache = span.tags.fromCache;
if (span.error) {
payload.error = this.errorToObject(span.error);
}
}
return payload;
}
/**
* Assign extra metrics taking into account action definitions
*
* @param {Context} ctx
* @param {string} name Field of the context to be assigned.
* @param {any} payload Object for assignment.
*
* @private
*/
assignExtraMetrics(ctx, name, payload) {
let def = ctx.action.metrics[name];
// if metrics definitions is boolean do default, metrics=true
if (def === true) {
payload[name] = ctx[name];
} else if (Array.isArray(def)) {
payload[name] = _.pick(ctx[name], def);
} else if (isFunction(def)) {
payload[name] = def(ctx[name]);
}
}
/**
* Decide and process extra metrics taking into account action definitions
*
* @param {Context} ctx
* @param {any} payload Object for assignment.
*
* @private
*/
processExtraMetrics(ctx, payload) {
// extra metrics (params and meta)
if (isObject(ctx.action.metrics)) {
// custom metrics def
this.assignExtraMetrics(ctx, "params", payload);
this.assignExtraMetrics(ctx, "meta", payload);
}
}
}
module.exports = EventLegacyTraceExporter;