@shrub/express-tracing 0.5.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 jjvainav
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ export * from "./middleware";
2
+ export * from "./module";
3
+ export { TraceHeaders } from "./service";
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxVQUFVLENBQUM7QUFDekIsT0FBTyxFQUEwQixZQUFZLEVBQUUsTUFBTSxXQUFXLENBQUMifQ==
@@ -0,0 +1,57 @@
1
+ import { IExpressTracingService } from "./service";
2
+ attachErrorListener();
3
+ /** @internal */
4
+ export const addSpanRequestBuilder = (context, span) => ({ ...context, span });
5
+ /** Request tracing middleware that will start a new span for a request. */
6
+ export const useRequestTracing = (options) => {
7
+ return (req, res, next) => {
8
+ const service = req.context.services.tryGet(IExpressTracingService);
9
+ if (!service) {
10
+ return next(new Error("express-tracing-service not registered, make sure the ExpressTracingModule is loaded when using request tracing."));
11
+ }
12
+ const span = service.startSpan(req, options);
13
+ req.contextBuilder.addSpan(span);
14
+ // if a request connection is 'keep-alive' the response will never finish;
15
+ // so instead, listen for the close event for when the connection has been closed
16
+ // https://nodejs.org/api/http.html#http_event_close_1
17
+ res.once("close", () => service.endSpan(span, req, res));
18
+ // https://nodejs.org/api/http.html#http_event_finish
19
+ res.once("finish", () => {
20
+ if (res.statusCode >= 300 && res.statusCode < 400) {
21
+ const location = res.getHeader("location");
22
+ if (location) {
23
+ span.tag("http.location", location);
24
+ }
25
+ }
26
+ service.endSpan(span, req, res);
27
+ });
28
+ const ref = res.writeHead;
29
+ res.writeHead = function writeHead() {
30
+ // gets invoked just before writing headers
31
+ if (res.getHeader("connection") === "keep-alive") {
32
+ span.tag("http.keepAlive", true);
33
+ }
34
+ return ref.apply(res, arguments);
35
+ };
36
+ next();
37
+ };
38
+ };
39
+ /**
40
+ * Overrides the express internal handle_error function that gets invoked when an error has occurred.
41
+ * There are no global error events exposed by express and the only way to handle errors is via express middleware.
42
+ * By monkey patching the internal handle_error function we can 'listen' for errors and not have to worry
43
+ * about error handling middleware not passing the error down to next.
44
+ *
45
+ * Note: the node http request/response define an error event (e.g. req.on("error")) but these do not seem to get invoked.
46
+ *
47
+ * https://github.com/expressjs/express/blob/3ed5090ca91f6a387e66370d57ead94d886275e1/lib/router/layer.js#L62
48
+ */
49
+ function attachErrorListener() {
50
+ const Layer = require("express/lib/router/layer");
51
+ const ref = Layer.prototype.handle_error;
52
+ Layer.prototype.handle_error = function handle_error(error, req, res, next) {
53
+ req.context.bag.__error = error;
54
+ return ref.call(this, error, req, res, next);
55
+ };
56
+ }
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWRkbGV3YXJlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBRSxzQkFBc0IsRUFBMEIsTUFBTSxXQUFXLENBQUM7QUFZM0UsbUJBQW1CLEVBQUUsQ0FBQztBQUV0QixnQkFBZ0I7QUFDaEIsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxPQUF3QixFQUFFLElBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFFdkcsMkVBQTJFO0FBQzNFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsT0FBZ0MsRUFBa0IsRUFBRTtJQUNsRixPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRTtRQUN0QixNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1YsT0FBTyxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsa0hBQWtILENBQUMsQ0FBQyxDQUFDO1NBQzlJO1FBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0MsR0FBRyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFakMsMEVBQTBFO1FBQzFFLGlGQUFpRjtRQUVqRixzREFBc0Q7UUFDdEQsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFekQscURBQXFEO1FBQ3JELEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtZQUNwQixJQUFJLEdBQUcsQ0FBQyxVQUFVLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEdBQUcsR0FBRyxFQUFFO2dCQUMvQyxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUMzQyxJQUFJLFFBQVEsRUFBRTtvQkFDVixJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBVSxRQUFRLENBQUMsQ0FBQztpQkFDL0M7YUFDSjtZQUVELE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQyxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUM7UUFDMUIsR0FBRyxDQUFDLFNBQVMsR0FBRyxTQUFTLFNBQVM7WUFDOUIsMkNBQTJDO1lBQzNDLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsS0FBSyxZQUFZLEVBQUU7Z0JBQzlDLElBQUksQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDcEM7WUFFRCxPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFNBQWdCLENBQUMsQ0FBQztRQUM1QyxDQUFDLENBQUM7UUFFRixJQUFJLEVBQUUsQ0FBQztJQUNYLENBQUMsQ0FBQztBQUNOLENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsbUJBQW1CO0lBQ3hCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ2xELE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDO0lBQ3pDLEtBQUssQ0FBQyxTQUFTLENBQUMsWUFBWSxHQUFHLFNBQVMsWUFBWSxDQUFDLEtBQVksRUFBRSxHQUFZLEVBQUUsR0FBYSxFQUFFLElBQWtCO1FBQzlHLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDaEMsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNqRCxDQUFDLENBQUE7QUFDTCxDQUFDIn0=
@@ -0,0 +1,20 @@
1
+ import { ExpressModule, IExpressConfiguration } from "@shrub/express";
2
+ import { TracingModule } from "@shrub/tracing";
3
+ import { addSpanRequestBuilder } from "./middleware";
4
+ import { ExpressTracingService, IExpressTracingService } from "./service";
5
+ export class ExpressTracingModule {
6
+ constructor() {
7
+ this.name = "express-tracing";
8
+ this.dependencies = [
9
+ ExpressModule,
10
+ TracingModule
11
+ ];
12
+ }
13
+ configureServices(registration) {
14
+ registration.register(IExpressTracingService, ExpressTracingService);
15
+ }
16
+ configure({ config }) {
17
+ config.get(IExpressConfiguration).useRequestBuilder("addSpan", addSpanRequestBuilder);
18
+ }
19
+ }
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsYUFBYSxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNyRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFMUUsTUFBTSxPQUFPLG9CQUFvQjtJQUFqQztRQUNhLFNBQUksR0FBRyxpQkFBaUIsQ0FBQztRQUN6QixpQkFBWSxHQUFHO1lBQ3BCLGFBQWE7WUFDYixhQUFhO1NBQ2hCLENBQUM7SUFTTixDQUFDO0lBUEcsaUJBQWlCLENBQUMsWUFBa0M7UUFDaEQsWUFBWSxDQUFDLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0lBQ3pFLENBQUM7SUFFRCxTQUFTLENBQUMsRUFBRSxNQUFNLEVBQXVCO1FBQ3JDLE1BQU0sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUscUJBQXFCLENBQUMsQ0FBQztJQUMxRixDQUFDO0NBQ0oifQ==
@@ -0,0 +1,85 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { createService, Singleton } from "@shrub/core";
11
+ import { ITracingService } from "@shrub/tracing";
12
+ export var TraceHeaders;
13
+ (function (TraceHeaders) {
14
+ TraceHeaders["traceId"] = "X-Trace-ID";
15
+ TraceHeaders["spanId"] = "X-Span-ID";
16
+ })(TraceHeaders || (TraceHeaders = {}));
17
+ export const IExpressTracingService = createService("express-tracing-service");
18
+ function isRequestContextScope(scope) {
19
+ return scope.bag !== undefined && scope.services !== undefined;
20
+ }
21
+ function isRequestScope(scope) {
22
+ return scope.url !== undefined && scope.method !== undefined;
23
+ }
24
+ let ExpressTracingService = class ExpressTracingService {
25
+ constructor(tracingService) {
26
+ this.tracingService = tracingService;
27
+ }
28
+ startSpan(req, options) {
29
+ const builder = options && options.external
30
+ ? this.getExternalBuilder()
31
+ : this.getInternalBuilder();
32
+ const tags = {
33
+ "http.url": req.originalUrl,
34
+ "http.method": req.method
35
+ };
36
+ this.addHeaderFieldTag(tags, req, "http.id", "X-Request-ID");
37
+ return builder.build(req).startSpan("http.request", tags);
38
+ }
39
+ endSpan(span, req, res) {
40
+ span.tag("http.status", res.statusCode);
41
+ span.done(req.context.bag.__error);
42
+ }
43
+ getExternalBuilder() {
44
+ this.externalBuilder = this.externalBuilder || this.tracingService.getBuilder();
45
+ return this.externalBuilder;
46
+ }
47
+ getInternalBuilder() {
48
+ this.internalBuilder = this.internalBuilder || this.tracingService.getBuilder().useContextProvider({
49
+ getSpanContext: scope => {
50
+ if (isRequestScope(scope)) {
51
+ const traceId = scope.get(TraceHeaders.traceId);
52
+ const scopeId = scope.get(TraceHeaders.spanId);
53
+ if (traceId && scopeId) {
54
+ return {
55
+ getParentSpanId: () => scopeId,
56
+ getTraceId: () => traceId
57
+ };
58
+ }
59
+ }
60
+ else if (isRequestContextScope(scope) && scope.span) {
61
+ const scopeId = scope.span.id;
62
+ const traceId = scope.span.traceId;
63
+ return {
64
+ getParentSpanId: () => scopeId,
65
+ getTraceId: () => traceId
66
+ };
67
+ }
68
+ return undefined;
69
+ }
70
+ });
71
+ return this.internalBuilder;
72
+ }
73
+ addHeaderFieldTag(tags, req, tagName, headerName) {
74
+ const value = req.get(headerName);
75
+ if (value !== undefined) {
76
+ tags[tagName] = value;
77
+ }
78
+ }
79
+ };
80
+ ExpressTracingService = __decorate([
81
+ Singleton,
82
+ __param(0, ITracingService)
83
+ ], ExpressTracingService);
84
+ export { ExpressTracingService };
85
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUNBLE9BQU8sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXZELE9BQU8sRUFBZ0MsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFrQi9FLE1BQU0sQ0FBTixJQUFZLFlBR1g7QUFIRCxXQUFZLFlBQVk7SUFDcEIsc0NBQXNCLENBQUE7SUFDdEIsb0NBQW9CLENBQUE7QUFDeEIsQ0FBQyxFQUhXLFlBQVksS0FBWixZQUFZLFFBR3ZCO0FBRUQsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsYUFBYSxDQUF5Qix5QkFBeUIsQ0FBQyxDQUFDO0FBRXZHLFNBQVMscUJBQXFCLENBQUMsS0FBVTtJQUNyQyxPQUF5QixLQUFNLENBQUMsR0FBRyxLQUFLLFNBQVMsSUFBc0IsS0FBTSxDQUFDLFFBQVEsS0FBSyxTQUFTLENBQUM7QUFDekcsQ0FBQztBQUVELFNBQVMsY0FBYyxDQUFDLEtBQVU7SUFDOUIsT0FBaUIsS0FBTSxDQUFDLEdBQUcsS0FBSyxTQUFTLElBQWMsS0FBTSxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUM7QUFDdkYsQ0FBQztBQUdELElBQWEscUJBQXFCLEdBQWxDLE1BQWEscUJBQXFCO0lBSTlCLFlBQThDLGNBQStCO1FBQS9CLG1CQUFjLEdBQWQsY0FBYyxDQUFpQjtJQUM3RSxDQUFDO0lBRUQsU0FBUyxDQUFDLEdBQVksRUFBRSxPQUFnQztRQUNwRCxNQUFNLE9BQU8sR0FBRyxPQUFPLElBQUksT0FBTyxDQUFDLFFBQVE7WUFDdkMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUMzQixDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFaEMsTUFBTSxJQUFJLEdBQVU7WUFDaEIsVUFBVSxFQUFFLEdBQUcsQ0FB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
@@ -0,0 +1,3 @@
1
+ export * from "./middleware";
2
+ export * from "./module";
3
+ export { IRequestTracingOptions, TraceHeaders } from "./service";
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TraceHeaders = void 0;
14
+ __exportStar(require("./middleware"), exports);
15
+ __exportStar(require("./module"), exports);
16
+ var service_1 = require("./service");
17
+ Object.defineProperty(exports, "TraceHeaders", { enumerable: true, get: function () { return service_1.TraceHeaders; } });
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQUFBLCtDQUE2QjtBQUM3QiwyQ0FBeUI7QUFDekIscUNBQWlFO0FBQWhDLHVHQUFBLFlBQVksT0FBQSJ9
@@ -0,0 +1,13 @@
1
+ import { ISpan } from "@shrub/tracing";
2
+ import { RequestHandler } from "express";
3
+ import { IRequestTracingOptions } from "./service";
4
+ declare module "@shrub/express/dist/request-context" {
5
+ interface IRequestContext {
6
+ readonly span?: ISpan;
7
+ }
8
+ interface IRequestContextBuilder {
9
+ addSpan(span: ISpan): IRequestContextBuilder;
10
+ }
11
+ }
12
+ /** Request tracing middleware that will start a new span for a request. */
13
+ export declare const useRequestTracing: (options?: IRequestTracingOptions | undefined) => RequestHandler;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRequestTracing = exports.addSpanRequestBuilder = void 0;
4
+ const service_1 = require("./service");
5
+ attachErrorListener();
6
+ /** @internal */
7
+ const addSpanRequestBuilder = (context, span) => ({ ...context, span });
8
+ exports.addSpanRequestBuilder = addSpanRequestBuilder;
9
+ /** Request tracing middleware that will start a new span for a request. */
10
+ const useRequestTracing = (options) => {
11
+ return (req, res, next) => {
12
+ const service = req.context.services.tryGet(service_1.IExpressTracingService);
13
+ if (!service) {
14
+ return next(new Error("express-tracing-service not registered, make sure the ExpressTracingModule is loaded when using request tracing."));
15
+ }
16
+ const span = service.startSpan(req, options);
17
+ req.contextBuilder.addSpan(span);
18
+ // if a request connection is 'keep-alive' the response will never finish;
19
+ // so instead, listen for the close event for when the connection has been closed
20
+ // https://nodejs.org/api/http.html#http_event_close_1
21
+ res.once("close", () => service.endSpan(span, req, res));
22
+ // https://nodejs.org/api/http.html#http_event_finish
23
+ res.once("finish", () => {
24
+ if (res.statusCode >= 300 && res.statusCode < 400) {
25
+ const location = res.getHeader("location");
26
+ if (location) {
27
+ span.tag("http.location", location);
28
+ }
29
+ }
30
+ service.endSpan(span, req, res);
31
+ });
32
+ const ref = res.writeHead;
33
+ res.writeHead = function writeHead() {
34
+ // gets invoked just before writing headers
35
+ if (res.getHeader("connection") === "keep-alive") {
36
+ span.tag("http.keepAlive", true);
37
+ }
38
+ return ref.apply(res, arguments);
39
+ };
40
+ next();
41
+ };
42
+ };
43
+ exports.useRequestTracing = useRequestTracing;
44
+ /**
45
+ * Overrides the express internal handle_error function that gets invoked when an error has occurred.
46
+ * There are no global error events exposed by express and the only way to handle errors is via express middleware.
47
+ * By monkey patching the internal handle_error function we can 'listen' for errors and not have to worry
48
+ * about error handling middleware not passing the error down to next.
49
+ *
50
+ * Note: the node http request/response define an error event (e.g. req.on("error")) but these do not seem to get invoked.
51
+ *
52
+ * https://github.com/expressjs/express/blob/3ed5090ca91f6a387e66370d57ead94d886275e1/lib/router/layer.js#L62
53
+ */
54
+ function attachErrorListener() {
55
+ const Layer = require("express/lib/router/layer");
56
+ const ref = Layer.prototype.handle_error;
57
+ Layer.prototype.handle_error = function handle_error(error, req, res, next) {
58
+ req.context.bag.__error = error;
59
+ return ref.call(this, error, req, res, next);
60
+ };
61
+ }
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9taWRkbGV3YXJlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUdBLHVDQUEyRTtBQVkzRSxtQkFBbUIsRUFBRSxDQUFDO0FBRXRCLGdCQUFnQjtBQUNULE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxPQUF3QixFQUFFLElBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFBMUYsUUFBQSxxQkFBcUIseUJBQXFFO0FBRXZHLDJFQUEyRTtBQUNwRSxNQUFNLGlCQUFpQixHQUFHLENBQUMsT0FBZ0MsRUFBa0IsRUFBRTtJQUNsRixPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRTtRQUN0QixNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsZ0NBQXNCLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1YsT0FBTyxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsa0hBQWtILENBQUMsQ0FBQyxDQUFDO1NBQzlJO1FBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0MsR0FBRyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFakMsMEVBQTBFO1FBQzFFLGlGQUFpRjtRQUVqRixzREFBc0Q7UUFDdEQsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFekQscURBQXFEO1FBQ3JELEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtZQUNwQixJQUFJLEdBQUcsQ0FBQyxVQUFVLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEdBQUcsR0FBRyxFQUFFO2dCQUMvQyxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUMzQyxJQUFJLFFBQVEsRUFBRTtvQkFDVixJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBVSxRQUFRLENBQUMsQ0FBQztpQkFDL0M7YUFDSjtZQUVELE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQyxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUM7UUFDMUIsR0FBRyxDQUFDLFNBQVMsR0FBRyxTQUFTLFNBQVM7WUFDOUIsMkNBQTJDO1lBQzNDLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsS0FBSyxZQUFZLEVBQUU7Z0JBQzlDLElBQUksQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDcEM7WUFFRCxPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFNBQWdCLENBQUMsQ0FBQztRQUM1QyxDQUFDLENBQUM7UUFFRixJQUFJLEVBQUUsQ0FBQztJQUNYLENBQUMsQ0FBQztBQUNOLENBQUMsQ0FBQztBQXhDVyxRQUFBLGlCQUFpQixxQkF3QzVCO0FBRUY7Ozs7Ozs7OztHQVNHO0FBQ0gsU0FBUyxtQkFBbUI7SUFDeEIsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLDBCQUEwQixDQUFDLENBQUM7SUFDbEQsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUM7SUFDekMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxZQUFZLEdBQUcsU0FBUyxZQUFZLENBQUMsS0FBWSxFQUFFLEdBQVksRUFBRSxHQUFhLEVBQUUsSUFBa0I7UUFDOUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNoQyxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQTtBQUNMLENBQUMifQ==
@@ -0,0 +1,9 @@
1
+ import { IModule, IModuleConfigurator, IServiceRegistration } from "@shrub/core";
2
+ import { ExpressModule } from "@shrub/express";
3
+ import { TracingModule } from "@shrub/tracing";
4
+ export declare class ExpressTracingModule implements IModule {
5
+ readonly name = "express-tracing";
6
+ readonly dependencies: (typeof ExpressModule | typeof TracingModule)[];
7
+ configureServices(registration: IServiceRegistration): void;
8
+ configure({ config }: IModuleConfigurator): void;
9
+ }
package/dist/module.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExpressTracingModule = void 0;
4
+ const express_1 = require("@shrub/express");
5
+ const tracing_1 = require("@shrub/tracing");
6
+ const middleware_1 = require("./middleware");
7
+ const service_1 = require("./service");
8
+ class ExpressTracingModule {
9
+ constructor() {
10
+ this.name = "express-tracing";
11
+ this.dependencies = [
12
+ express_1.ExpressModule,
13
+ tracing_1.TracingModule
14
+ ];
15
+ }
16
+ configureServices(registration) {
17
+ registration.register(service_1.IExpressTracingService, service_1.ExpressTracingService);
18
+ }
19
+ configure({ config }) {
20
+ config.get(express_1.IExpressConfiguration).useRequestBuilder("addSpan", middleware_1.addSpanRequestBuilder);
21
+ }
22
+ }
23
+ exports.ExpressTracingModule = ExpressTracingModule;
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSw0Q0FBc0U7QUFDdEUsNENBQStDO0FBQy9DLDZDQUFxRDtBQUNyRCx1Q0FBMEU7QUFFMUUsTUFBYSxvQkFBb0I7SUFBakM7UUFDYSxTQUFJLEdBQUcsaUJBQWlCLENBQUM7UUFDekIsaUJBQVksR0FBRztZQUNwQix1QkFBYTtZQUNiLHVCQUFhO1NBQ2hCLENBQUM7SUFTTixDQUFDO0lBUEcsaUJBQWlCLENBQUMsWUFBa0M7UUFDaEQsWUFBWSxDQUFDLFFBQVEsQ0FBQyxnQ0FBc0IsRUFBRSwrQkFBcUIsQ0FBQyxDQUFDO0lBQ3pFLENBQUM7SUFFRCxTQUFTLENBQUMsRUFBRSxNQUFNLEVBQXVCO1FBQ3JDLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQXFCLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsa0NBQXFCLENBQUMsQ0FBQztJQUMxRixDQUFDO0NBQ0o7QUFkRCxvREFjQyJ9
@@ -0,0 +1,30 @@
1
+ import { Request, Response } from "express";
2
+ import { ISpan, ITracingService } from "@shrub/tracing";
3
+ /** Internal service used by the middleware for starting and ending spans. */
4
+ export interface IExpressTracingService {
5
+ endSpan(span: ISpan, req: Request, res: Response): void;
6
+ startSpan(req: Request, options?: IRequestTracingOptions): ISpan;
7
+ }
8
+ export interface IRequestTracingOptions {
9
+ /**
10
+ * True if the requests are expected to be from an external client and will disable searching the
11
+ * request for the X-Trace-ID and X-Span-ID headers; the default is false.
12
+ */
13
+ readonly external?: boolean;
14
+ }
15
+ export declare enum TraceHeaders {
16
+ traceId = "X-Trace-ID",
17
+ spanId = "X-Span-ID"
18
+ }
19
+ export declare const IExpressTracingService: import("@shrub/core").IService<IExpressTracingService>;
20
+ export declare class ExpressTracingService implements IExpressTracingService {
21
+ private readonly tracingService;
22
+ private externalBuilder?;
23
+ private internalBuilder?;
24
+ constructor(tracingService: ITracingService);
25
+ startSpan(req: Request, options?: IRequestTracingOptions): ISpan;
26
+ endSpan(span: ISpan, req: Request, res: Response): void;
27
+ private getExternalBuilder;
28
+ private getInternalBuilder;
29
+ private addHeaderFieldTag;
30
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
9
+ return function (target, key) { decorator(target, key, paramIndex); }
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ExpressTracingService = exports.IExpressTracingService = exports.TraceHeaders = void 0;
13
+ const core_1 = require("@shrub/core");
14
+ const tracing_1 = require("@shrub/tracing");
15
+ var TraceHeaders;
16
+ (function (TraceHeaders) {
17
+ TraceHeaders["traceId"] = "X-Trace-ID";
18
+ TraceHeaders["spanId"] = "X-Span-ID";
19
+ })(TraceHeaders = exports.TraceHeaders || (exports.TraceHeaders = {}));
20
+ exports.IExpressTracingService = core_1.createService("express-tracing-service");
21
+ function isRequestContextScope(scope) {
22
+ return scope.bag !== undefined && scope.services !== undefined;
23
+ }
24
+ function isRequestScope(scope) {
25
+ return scope.url !== undefined && scope.method !== undefined;
26
+ }
27
+ let ExpressTracingService = class ExpressTracingService {
28
+ constructor(tracingService) {
29
+ this.tracingService = tracingService;
30
+ }
31
+ startSpan(req, options) {
32
+ const builder = options && options.external
33
+ ? this.getExternalBuilder()
34
+ : this.getInternalBuilder();
35
+ const tags = {
36
+ "http.url": req.originalUrl,
37
+ "http.method": req.method
38
+ };
39
+ this.addHeaderFieldTag(tags, req, "http.id", "X-Request-ID");
40
+ return builder.build(req).startSpan("http.request", tags);
41
+ }
42
+ endSpan(span, req, res) {
43
+ span.tag("http.status", res.statusCode);
44
+ span.done(req.context.bag.__error);
45
+ }
46
+ getExternalBuilder() {
47
+ this.externalBuilder = this.externalBuilder || this.tracingService.getBuilder();
48
+ return this.externalBuilder;
49
+ }
50
+ getInternalBuilder() {
51
+ this.internalBuilder = this.internalBuilder || this.tracingService.getBuilder().useContextProvider({
52
+ getSpanContext: scope => {
53
+ if (isRequestScope(scope)) {
54
+ const traceId = scope.get(TraceHeaders.traceId);
55
+ const scopeId = scope.get(TraceHeaders.spanId);
56
+ if (traceId && scopeId) {
57
+ return {
58
+ getParentSpanId: () => scopeId,
59
+ getTraceId: () => traceId
60
+ };
61
+ }
62
+ }
63
+ else if (isRequestContextScope(scope) && scope.span) {
64
+ const scopeId = scope.span.id;
65
+ const traceId = scope.span.traceId;
66
+ return {
67
+ getParentSpanId: () => scopeId,
68
+ getTraceId: () => traceId
69
+ };
70
+ }
71
+ return undefined;
72
+ }
73
+ });
74
+ return this.internalBuilder;
75
+ }
76
+ addHeaderFieldTag(tags, req, tagName, headerName) {
77
+ const value = req.get(headerName);
78
+ if (value !== undefined) {
79
+ tags[tagName] = value;
80
+ }
81
+ }
82
+ };
83
+ ExpressTracingService = __decorate([
84
+ core_1.Singleton,
85
+ __param(0, tracing_1.ITracingService)
86
+ ], ExpressTracingService);
87
+ exports.ExpressTracingService = ExpressTracingService;
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUNBLHNDQUF1RDtBQUV2RCw0Q0FBK0U7QUFrQi9FLElBQVksWUFHWDtBQUhELFdBQVksWUFBWTtJQUNwQixzQ0FBc0IsQ0FBQTtJQUN0QixvQ0FBb0IsQ0FBQTtBQUN4QixDQUFDLEVBSFcsWUFBWSxHQUFaLG9CQUFZLEtBQVosb0JBQVksUUFHdkI7QUFFWSxRQUFBLHNCQUFzQixHQUFHLG9CQUFhLENBQXlCLHlCQUF5QixDQUFDLENBQUM7QUFFdkcsU0FBUyxxQkFBcUIsQ0FBQyxLQUFVO0lBQ3JDLE9BQXlCLEtBQU0sQ0FBQyxHQUFHLEtBQUssU0FBUyxJQUFzQixLQUFNLENBQUMsUUFBUSxLQUFLLFNBQVMsQ0FBQztBQUN6RyxDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsS0FBVTtJQUM5QixPQUFpQixLQUFNLENBQUMsR0FBRyxLQUFLLFNBQVMsSUFBYyxLQUFNLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQztBQUN2RixDQUFDO0FBR0QsSUFBYSxxQkFBcUIsR0FBbEMsTUFBYSxxQkFBcUI7SUFJOUIsWUFBOEMsY0FBK0I7UUFBL0IsbUJBQWMsR0FBZCxjQUFjLENBQWlCO0lBQzdFLENBQUM7SUFFRCxTQUFTLENBQUMsR0FBWSxFQUFFLE9BQWdDO1FBQ3BELE1BQU0sT0FBTyxHQUFHLE9BQU8sSUFBSSxPQUFPLENBQUMsUUFBUTtZQUN2QyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzNCLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUVoQyxNQUFNLElBQUksR0FBVTtZQUNoQixVQUFVLEVBQUUsR0FBRyxDQUFDLFdBQVc7WUFDM0IsYUFBYSxFQUFFLEdBQUcsQ0FBQyxNQUFNO1NBQzVCLENBQUM7UUFFRixJQUFJLENBQUMsaUJBQWlCLENBQUMs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
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@shrub/express-tracing",
3
+ "description": "A module that provides middleware for tracing express requests.",
4
+ "version": "0.5.26",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/jjvainav/shrub.git"
9
+ },
10
+ "main": "dist/index.js",
11
+ "typings": "dist/index.d.ts",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "engines": {
19
+ "node": ">=10.18.0"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc -b .",
23
+ "build:esm": "tsc -p tsconfig.esm.json",
24
+ "clean": "rimraf ./dist && rimraf tsconfig.tsbuildinfo",
25
+ "test": "jest"
26
+ },
27
+ "devDependencies": {
28
+ "@sprig/event-emitter": "^0.1.69",
29
+ "@types/express": "4.17.9"
30
+ },
31
+ "dependencies": {
32
+ "@shrub/core": "0.5.26",
33
+ "@shrub/express": "0.5.26",
34
+ "@shrub/logging": "0.5.26",
35
+ "@shrub/tracing": "0.5.26",
36
+ "express": "^4.17.1"
37
+ },
38
+ "gitHead": "bd8e68fee891bb035f6506401851cf993c1c614e"
39
+ }