From 90fb1c4e7d3c8e93d9929b788758c09a84716836 Mon Sep 17 00:00:00 2001 From: Thiago Matar Date: Fri, 14 Feb 2025 10:39:20 -0300 Subject: [PATCH 1/3] Fix: Ensure compatibility with Express 4.x and 5.x in ExpressPlugin --- src/plugins/ExpressPlugin.ts | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/plugins/ExpressPlugin.ts b/src/plugins/ExpressPlugin.ts index d8e7651..f62cce6 100644 --- a/src/plugins/ExpressPlugin.ts +++ b/src/plugins/ExpressPlugin.ts @@ -38,7 +38,27 @@ class ExpressPlugin implements SwPlugin { } private interceptServerRequest(installer: PluginInstaller) { - const router = installer.require?.('express/lib/router') ?? require('express/lib/router'); + let router; + + try { + // Express 4.x and older versions + router = installer.require?.('express/lib/router') ?? require('express/lib/router'); + } catch (error) { + try { + // Express 5+ (uses dynamic import) + const express = require('express'); + router = express.Router ? express.Router() : null; + } catch (err) { + console.error('⚠️ SkyWalking: Failed to load Express router - Express may not be installed.'); + return; + } + } + + if (!router) { + console.warn('⚠️ SkyWalking: Unable to determine Express structure. Instrumentation is disabled.'); + return; + } + const _handle = router.handle; router.handle = function (req: Request, res: ServerResponse, next: any) { @@ -51,19 +71,20 @@ class ExpressPlugin implements SwPlugin { span.component = Component.EXPRESS; - if (span.depth) - // if we inherited from http then just change component ID and let http do the work + if (span.depth) { + // If inherited from HTTP, just change the component ID and let HTTP handle it return _handle.apply(this, arguments); + } return HttpPlugin.wrapHttpResponse(span, req, res, () => { - // http plugin disabled, we use its mechanism anyway + // If HTTP plugin is disabled, we use this mechanism anyway try { return _handle.call(this, req, res, (err: Error) => { span.error(err); next.call(this, err); }); } finally { - // req.protocol is only possibly available after call to _handle() + // req.protocol might only be available after calling _handle() span.tag( Tag.httpURL( ((req as any).protocol ? (req as any).protocol + '://' : '') + (req.headers.host || '') + req.url, From 85c998f2bca14e8b68b29761f48de99ac6d768b3 Mon Sep 17 00:00:00 2001 From: Thiago Matar Date: Fri, 14 Feb 2025 11:22:47 -0300 Subject: [PATCH 2/3] simplifying the code --- src/plugins/ExpressPlugin.ts | 132 ++++++++++++++--------------------- 1 file changed, 53 insertions(+), 79 deletions(-) diff --git a/src/plugins/ExpressPlugin.ts b/src/plugins/ExpressPlugin.ts index f62cce6..b9d2fe8 100644 --- a/src/plugins/ExpressPlugin.ts +++ b/src/plugins/ExpressPlugin.ts @@ -1,3 +1,4 @@ +"use strict"; /*! * * Licensed to the Apache Software Foundation (ASF) under one or more @@ -16,85 +17,58 @@ * limitations under the License. * */ - -import SwPlugin from '../core/SwPlugin'; -import { ServerResponse } from 'http'; -import ContextManager from '../trace/context/ContextManager'; -import { Component } from '../trace/Component'; -import Tag from '../Tag'; -import { ContextCarrier } from '../trace/context/ContextCarrier'; -import DummySpan from '../trace/span/DummySpan'; -import { ignoreHttpMethodCheck } from '../config/AgentConfig'; -import PluginInstaller from '../core/PluginInstaller'; -import HttpPlugin from './HttpPlugin'; -import { Request } from 'express'; - -class ExpressPlugin implements SwPlugin { - readonly module = 'express'; - readonly versions = '*'; - - install(installer: PluginInstaller): void { - this.interceptServerRequest(installer); - } - - private interceptServerRequest(installer: PluginInstaller) { - let router; - - try { - // Express 4.x and older versions - router = installer.require?.('express/lib/router') ?? require('express/lib/router'); - } catch (error) { - try { - // Express 5+ (uses dynamic import) - const express = require('express'); - router = express.Router ? express.Router() : null; - } catch (err) { - console.error('⚠️ SkyWalking: Failed to load Express router - Express may not be installed.'); - return; - } +Object.defineProperty(exports, "__esModule", { value: true }); +var tslib_1 = require("tslib"); +var ContextManager_1 = tslib_1.__importDefault(require("../trace/context/ContextManager")); +var Component_1 = require("../trace/Component"); +var Tag_1 = tslib_1.__importDefault(require("../Tag")); +var ContextCarrier_1 = require("../trace/context/ContextCarrier"); +var DummySpan_1 = tslib_1.__importDefault(require("../trace/span/DummySpan")); +var AgentConfig_1 = require("../config/AgentConfig"); +var HttpPlugin_1 = tslib_1.__importDefault(require("./HttpPlugin")); +var ExpressPlugin = /** @class */ (function () { + function ExpressPlugin() { + this.module = 'express'; + this.versions = '*'; } - - if (!router) { - console.warn('⚠️ SkyWalking: Unable to determine Express structure. Instrumentation is disabled.'); - return; - } - - const _handle = router.handle; - - router.handle = function (req: Request, res: ServerResponse, next: any) { - const carrier = ContextCarrier.from((req as any).headers || {}); - const reqMethod = req.method ?? 'GET'; - const operation = reqMethod + ':' + (req.originalUrl || req.url || '/').replace(/\?.*/g, ''); - const span = ignoreHttpMethodCheck(reqMethod) - ? DummySpan.create() - : ContextManager.current.newEntrySpan(operation, carrier, [Component.HTTP_SERVER, Component.EXPRESS]); - - span.component = Component.EXPRESS; - - if (span.depth) { - // If inherited from HTTP, just change the component ID and let HTTP handle it - return _handle.apply(this, arguments); - } - - return HttpPlugin.wrapHttpResponse(span, req, res, () => { - // If HTTP plugin is disabled, we use this mechanism anyway - try { - return _handle.call(this, req, res, (err: Error) => { - span.error(err); - next.call(this, err); - }); - } finally { - // req.protocol might only be available after calling _handle() - span.tag( - Tag.httpURL( - ((req as any).protocol ? (req as any).protocol + '://' : '') + (req.headers.host || '') + req.url, - ), - ); - } - }); + ExpressPlugin.prototype.install = function (installer) { + this.interceptServerRequest(installer); + }; + ExpressPlugin.prototype.interceptServerRequest = function (installer) { + var _a, _b; + var express = require('express'); + var router = express.Router ? express.Router() : require('express/lib/router'); + var _handle = router.handle; + router.handle = function (req, res, next) { + var _this = this; + var _a; + var carrier = ContextCarrier_1.ContextCarrier.from(req.headers || {}); + var reqMethod = (_a = req.method) !== null && _a !== void 0 ? _a : 'GET'; + var operation = reqMethod + ':' + (req.originalUrl || req.url || '/').replace(/\?.*/g, ''); + var span = AgentConfig_1.ignoreHttpMethodCheck(reqMethod) + ? DummySpan_1.default.create() + : ContextManager_1.default.current.newEntrySpan(operation, carrier, [Component_1.Component.HTTP_SERVER, Component_1.Component.EXPRESS]); + span.component = Component_1.Component.EXPRESS; + if (span.depth) + // if we inherited from http then just change component ID and let http do the work + return _handle.apply(this, arguments); + return HttpPlugin_1.default.wrapHttpResponse(span, req, res, function () { + // http plugin disabled, we use its mechanism anyway + try { + return _handle.call(_this, req, res, function (err) { + span.error(err); + next.call(_this, err); + }); + } + finally { + // req.protocol is only possibly available after call to _handle() + span.tag(Tag_1.default.httpURL((req.protocol ? req.protocol + '://' : '') + (req.headers.host || '') + req.url)); + } + }); + }; }; - } -} - + return ExpressPlugin; +}()); // noinspection JSUnusedGlobalSymbols -export default new ExpressPlugin(); +exports.default = new ExpressPlugin(); +//# sourceMappingURL=ExpressPlugin.js.map From 9918a29db8e9c03efc7511b5147adc3cdd6f5409 Mon Sep 17 00:00:00 2001 From: Thiago Matar Date: Fri, 14 Feb 2025 12:50:17 -0300 Subject: [PATCH 3/3] Ensure compatibility with Express 4.x and 5.x in ExpressPlugin