Repository URL to install this package:
|
Version:
0.7.0 ▾
|
// (c) Copyright 2023 Supertenant Ltd. - all rights reserved.
// See LICENSE file in project root for license terms.
"use strict";const http2=require("http2"),shimmer=require("shimmer"),cls=require("../../cls"),constants=require("../../constants"),{getExtraHeadersFromNormalizedObjectLiteral,mergeExtraHeadersCaseInsensitive}=require("./captureHttpHeadersUtil"),readSymbolProperty=require("../../../util/readSymbolProperty"),tracingHeaders=require("../../tracingHeaders"),{filterParams,sanitizeUrl}=require("../../../util/url");let extraHttpHeadersToCapture,isActive=!1;exports.spanName="node.http.server";const sentHeadersS="Symbol(sent-headers)",HTTP2_HEADER_AUTHORITY=http2.constants.HTTP2_HEADER_AUTHORITY,HTTP2_HEADER_METHOD=http2.constants.HTTP2_HEADER_METHOD,HTTP2_HEADER_PATH=http2.constants.HTTP2_HEADER_PATH,HTTP2_HEADER_STATUS=http2.constants.HTTP2_HEADER_STATUS;function instrument(coreModule){instrumentCreateServer(coreModule,"createServer"),instrumentCreateServer(coreModule,"createSecureServer")}function instrumentCreateServer(coreModule,name){const original=coreModule[name];coreModule[name]=function(){var server=original.apply(this,arguments);return shimmer.wrap(server,"emit",shimEmit),server}}function shimEmit(realEmit){return function(eventType,stream,headers){if("stream"!==eventType||!isActive)return realEmit.apply(this,arguments);const originalThis=this,originalArgs=arguments;return cls.ns.runAndReturn(()=>{stream&&stream.on&&stream.addListener&&stream.emit&&cls.ns.bindEmitter(stream);var processedHeaders=tracingHeaders.fromHeaders(headers),w3cTraceContext=processedHeaders.w3cTraceContext;if("string"==typeof processedHeaders.level&&0===processedHeaders.level.indexOf("0")&&(cls.setTracingLevel("0"),w3cTraceContext)&&w3cTraceContext.disableSampling(),w3cTraceContext&&cls.setW3cTraceContext(w3cTraceContext),!cls.tracingSuppressed()){const span=cls.startSpan(exports.spanName,constants.ENTRY,processedHeaders.traceId,processedHeaders.parentId,w3cTraceContext);tracingHeaders.setSpanAttributes(span,processedHeaders);var w3cTraceContext=headers[HTTP2_HEADER_AUTHORITY],processedHeaders=headers[HTTP2_HEADER_PATH]||"/",method=headers[HTTP2_HEADER_METHOD]||"GET",processedHeaders=processedHeaders.split("?"),method=(2<=processedHeaders.length&&(processedHeaders[1]=filterParams(processedHeaders[1])),span.data.http={method:method,url:sanitizeUrl(processedHeaders.shift()),params:0<processedHeaders.length?processedHeaders.join("?"):void 0,host:w3cTraceContext,header:getExtraHeadersFromNormalizedObjectLiteral(headers,extraHttpHeadersToCapture)},span.data.http.header&&span.data.http.header[constants.serviceNameHeaderNameLowerCase]),processedHeaders=(null!=method&&(span.data.service=method),headers["x-supertenant-t"]||(headers["x-supertenant-t"]=span.t),"stid;desc="+span.t);function finishSpan(){if(!span.transmitted){let status;var resHeaders=readSymbolProperty(stream,sentHeadersS);resHeaders&&(status=resHeaders[HTTP2_HEADER_STATUS]),span.data.http=span.data.http||{},span.data.http.status=status,span.data.http.header=mergeExtraHeadersCaseInsensitive(span.data.http.header,resHeaders,extraHttpHeadersToCapture),span.ec=500<=status?1:0,span.d=Date.now()-span.ts,span.transmit()}}instrumentResponseMethod(stream,"respond",0,processedHeaders),instrumentResponseMethod(stream,"respondWithFD",1,processedHeaders),instrumentResponseMethod(stream,"respondWithFile",1,processedHeaders),stream.on("aborted",()=>{finishSpan()}),stream.on("close",()=>{finishSpan()})}return realEmit.apply(originalThis,originalArgs)})}}function instrumentResponseMethod(stream,method,headerArgumentIndex,serverTimingValue){"function"==typeof stream[method]&&shimmer.wrap(stream,method,original=>function(){var existingKey,existingValue,headers=arguments[headerArgumentIndex];return headers&&"object"==typeof headers&&headers[HTTP2_HEADER_STATUS]&&(null==(existingValue=(existingKey=Object.keys(headers).filter(key=>"server-timing"===key.toLowerCase())[0])?headers[existingKey]:null)?headers["Server-Timing"]=serverTimingValue:Array.isArray(existingValue)?existingValue.find(kv=>0===kv.indexOf("stid;"))||(headers[existingKey]=existingValue.concat(serverTimingValue)):"string"==typeof existingValue&&existingValue.indexOf("stid;")<0&&(headers[existingKey]=existingValue+", "+serverTimingValue)),original.apply(this,arguments)})}exports.init=function(config){instrument(http2),extraHttpHeadersToCapture=config.tracing.http.extraHttpHeadersToCapture},exports.updateConfig=function(config){extraHttpHeadersToCapture=config.tracing.http.extraHttpHeadersToCapture},exports.activate=function(extraConfig){extraConfig&&extraConfig.tracing&&extraConfig.tracing.http&&Array.isArray(extraConfig.tracing.http.extraHttpHeadersToCapture)&&(extraHttpHeadersToCapture=extraConfig.tracing.http.extraHttpHeadersToCapture),isActive=!0},exports.deactivate=function(){isActive=!1};