@lensmcp/nest-instrumentation 1.25.31 → 1.25.32

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.
@@ -3,7 +3,9 @@ import { Observable } from 'rxjs';
3
3
  /**
4
4
  * Wraps every Nest HTTP request:
5
5
  * 1. Reads `x-request-id`, `x-lensmcp-flow-id`, `x-lensmcp-origin-node-id`,
6
- * `traceparent` headers from the incoming request.
6
+ * `traceparent` headers from the incoming request — and `x-lensmcp-request-id`
7
+ * first, the id a caller's egress tap minted for a hop between the cluster's own
8
+ * services (the app's `x-request-id` may be one it forwarded).
7
9
  * 2. Runs the rest of the request inside a new
8
10
  * `LensmcpRequestContext` so any `@TraceMethod`-decorated service
9
11
  * call, DB query, or queue job downstream inherits the same flow.
@@ -1,3 +1,3 @@
1
- "use strict";var Y=Object.defineProperty;var u=(t,e)=>Y(t,"name",{value:e,configurable:!0});var ee=Object.defineProperty,a=u((t,e)=>ee(t,"name",{value:e,configurable:!0}),"d");import{__decorate as te}from"tslib";import{Injectable as re}from"@nestjs/common";import{Observable as U}from"rxjs";import{catchError as se,tap as oe}from"rxjs/operators";import{fingerprint as $,headlessFlowId as ne,headlessFlowsEnabled as ae,isProbePath as ie,requestFacts as de,responseFacts as ue,shapeOf as z,ulid as y}from"@lensmcp/core";import{activeMemoryOptions as ce,onFlowStart as fe,onFlowSettled as le}from"@lensmcp/memory-tracker";import{LENSMCP_CONTEXT_STORAGE as pe}from"./context.js";import{attachContextEnd as me}from"./context-end.js";import{activeOptions as q}from"./state.js";const Ie=Symbol.for("lensmcp.exchangeId");let T=class{static{u(this,"S")}static{a(this,"TraceInterceptor")}intercept(t,e){const o=q();if(!o.trace.requests)return e.handle();const d=t.switchToHttp(),r=d.getRequest(),s=d.getResponse(),n=h(r.headers?.["x-request-id"])??y(),c=h(r.headers?.["x-lensmcp-flow-id"]),f=h(r.headers?.["x-internal-token"])!==void 0,I=c??(!f&&ae()&&!ie(r.url)?ne(n):void 0),i={sessionId:o.sessionId,requestId:n,parentRequestId:h(r.headers?.["x-lensmcp-parent-request-id"]),flowId:I,originNodeId:h(r.headers?.["x-lensmcp-origin-node-id"]),traceparent:h(r.headers?.traceparent),runId:y(),dbCallCount:0},m=r[Ie],l=(r.method??"GET").toUpperCase(),p=r.route?.path??r.url??"<unknown>",O=t.getClass?.()?.name,D=t.getHandler?.()?.name,v=Date.now();I&&!c&&K(i,l,p,v);const M=o.memory.mode!=="off";M&&fe(n);const P=a(()=>{if(!M)return;const g=ce()?.settleMs??1e3;setTimeout(()=>le(n,i.flowId),g).unref?.()},"settleAndCheck"),V=me(i);let E;typeof s?.once=="function"&&we()&&s.once("finish",()=>X(o.projectName,i,l,p,r,s,E));let A=!1,j=typeof s?.once!="function";const H=a(()=>{A&&j&&V()},"endIfOver");if(!j){const g=a(()=>{j=!0,H()},"responseOut");s.once?.("finish",g),s.once?.("close",g)}return new U(g=>{let F;return pe.run(i,()=>{F=e.handle().pipe(oe({next:a(w=>{E??={value:w},g.next(w)},"next"),complete:a(()=>{x(o.projectName,i,l,p,s.statusCode??200,v,void 0,m,k(s)),N(i,O,D,v,"ok"),P(),g.complete()},"complete")}),se(w=>{const _=w?.getResponse?.();_!==void 0&&(E??={value:_});const B=R(w);if(B!==void 0||typeof s.once!="function")x(o.projectName,i,l,p,B??S(s),v,w,m,k(s));else{let L=!1;const G=a(W=>{if(L)return;L=!0;const Z=W&&s.statusCode&&s.statusCode>=400?s.statusCode:S(s);x(o.projectName,i,l,p,Z,v,w,m,k(s))},"settle");s.once("finish",()=>G(!0)),s.once("close",()=>G(!1))}return N(i,O,D,v,"error"),P(),g.error(w),new U})).subscribe()}),()=>{F?.unsubscribe(),A=!0,H()}})}};T=te([re()],T);export{T as TraceInterceptor};const b=new Map,ge=6e4,we=a(()=>process.env.LENSMCP_HTTP_SHAPES!=="0","shapesOn");function X(t,e,o,d,r,s,n){try{const c=s.statusCode??200,f=`${o} ${d} ${Math.floor(c/100)}`,I=Date.now();if(I-(b.get(f)??0)<ge)return;b.set(f,I),b.size>2e3&&b.delete(b.keys().next().value);const i=r.headers??{},m=r.body!==void 0&&r.body!==null&&typeof r.body=="object"&&!Buffer.isBuffer(r.body)?z(r.body):void 0,l=n&&n.value!==void 0&&typeof n.value=="object"&&n.value!==null&&!Buffer.isBuffer(n.value)&&typeof n.value.pipe!="function"?z(n.value):void 0,p={id:y(),sessionId:e.sessionId,timestamp:I,source:"nestjs",category:"backend",severity:"info",context:{sessionId:e.sessionId,flowId:e.flowId,requestId:e.requestId,...e.runId?{runId:e.runId}:{}},fingerprint:$({kind:"http-exchange",identity:f}),title:`${o} ${d} \u2192 ${c} (its shape)`,raw:{kind:"http-exchange",method:o,route:d,status:c,request:{...de(i,r.query,r.params),...m?{body:m}:{}},response:{...ue(s.getHeaders?.()??{},typeof i.origin=="string"?i.origin:void 0),...l?{body:l}:{}}}};C(p,t),q().emit(p)}catch{}}u(X,"pe"),a(X,"recordExchange");function R(t){const e=t;if(typeof e?.getStatus=="function")return e.getStatus();if(typeof e?.status=="number"&&e.status>=100)return e.status;if(typeof e?.statusCode=="number"&&e.statusCode>=100)return e.statusCode}u(R,"U"),a(R,"ownStatus");const ye=new Set(["TypeError","ReferenceError","SyntaxError","RangeError","EvalError","URIError"]);export function requestOutcome(t,e){return e instanceof Error&&ye.has(e.name)&&R(e)===void 0?"fault":t<400?"ok":t<500?"refused":t===500?"fault":"declared"}u(requestOutcome,"requestOutcome"),a(requestOutcome,"requestOutcome");function J(t){return t==="ok"?"info":t==="refused"?"warning":"error"}u(J,"me"),a(J,"severityOf");function S(t){return t.statusCode&&t.statusCode>=400?t.statusCode:500}u(S,"X"),a(S,"inferStatus");function h(t){if(typeof t=="string")return t;if(Array.isArray(t)&&typeof t[0]=="string")return t[0]}u(h,"h"),a(h,"stringHeader");function K(t,e,o,d){const r=q(),s=`request:${e} ${o}`,n={id:y(),sessionId:t.sessionId,timestamp:d,source:"nestjs",category:"backend",severity:"info",context:{sessionId:t.sessionId,flowId:t.flowId,requestId:t.requestId,originType:"request",originNodeId:s},fingerprint:$({kind:"flow-origin",identity:`${e}:${o}`}),title:`${e} ${o}`,raw:{kind:"flow-origin",originNodeId:s,method:e,route:o}};C(n,r.projectName),r.emit(n)}u(K,"ye"),a(K,"emitRequestOrigin");function N(t,e,o,d,r){if(!e||!o)return;const s=q(),n=Date.now()-d,c=`${e}.${o}`,f={id:y(),sessionId:t.sessionId,timestamp:Date.now(),source:"nestjs",category:"backend",severity:r==="error"?"error":"info",context:{sessionId:t.sessionId,flowId:t.flowId,requestId:t.requestId,...t.runId?{runId:t.runId}:{}},fingerprint:$({kind:"method-call",identity:c}),title:`${c} (${n}ms)${r==="error"?" \u2717":""}`,raw:{kind:"span",span:{name:c,role:"controller",flowId:t.flowId,requestId:t.requestId,startTime:d,endTime:Date.now(),durationMs:n,status:r}}};C(f,q().projectName),s.emit(f)}u(N,"z"),a(N,"emitControllerSpan");function Q(t){if(!(t instanceof Error))return{message:String(t)};const e=t.stack?t.stack.split(`
1
+ "use strict";var V=Object.defineProperty;var u=(t,e)=>V(t,"name",{value:e,configurable:!0});var ee=Object.defineProperty,a=u((t,e)=>ee(t,"name",{value:e,configurable:!0}),"d");import{__decorate as te}from"tslib";import{Injectable as se}from"@nestjs/common";import{Observable as G}from"rxjs";import{catchError as re,tap as oe}from"rxjs/operators";import{fingerprint as $,headlessFlowId as ne,headlessFlowsEnabled as ae,isProbePath as ie,LENS_REQUEST_ID_HEADER as de,requestFacts as ue,responseFacts as ce,shapeOf as z,ulid as h}from"@lensmcp/core";import{activeMemoryOptions as fe,onFlowStart as le,onFlowSettled as pe}from"@lensmcp/memory-tracker";import{LENSMCP_CONTEXT_STORAGE as me}from"./context.js";import{attachContextEnd as Ie}from"./context-end.js";import{activeOptions as q}from"./state.js";const ge=Symbol.for("lensmcp.exchangeId");let j=class{static{u(this,"S")}static{a(this,"TraceInterceptor")}intercept(t,e){const o=q();if(!o.trace.requests)return e.handle();const d=t.switchToHttp(),s=d.getRequest(),r=d.getResponse(),n=y(s.headers?.[de])??y(s.headers?.["x-request-id"])??h(),c=y(s.headers?.["x-lensmcp-flow-id"]),f=y(s.headers?.["x-internal-token"])!==void 0,I=c??(!f&&ae()&&!ie(s.url)?ne(n):void 0),i={sessionId:o.sessionId,requestId:n,parentRequestId:y(s.headers?.["x-lensmcp-parent-request-id"]),flowId:I,originNodeId:y(s.headers?.["x-lensmcp-origin-node-id"]),traceparent:y(s.headers?.traceparent),runId:h(),dbCallCount:0},m=s[ge],l=(s.method??"GET").toUpperCase(),p=s.route?.path??s.url??"<unknown>",O=t.getClass?.()?.name,D=t.getHandler?.()?.name,v=Date.now();I&&!c&&J(i,l,p,v);const M=o.memory.mode!=="off";M&&le(n);const _=a(()=>{if(!M)return;const g=fe()?.settleMs??1e3;setTimeout(()=>pe(n,i.flowId),g).unref?.()},"settleAndCheck"),W=Ie(i);let E;typeof r?.once=="function"&&ye()&&r.once("finish",()=>Q(o.projectName,i,l,p,s,r,E));let A=!1,T=typeof r?.once!="function";const H=a(()=>{A&&T&&W()},"endIfOver");if(!T){const g=a(()=>{T=!0,H()},"responseOut");r.once?.("finish",g),r.once?.("close",g)}return new G(g=>{let P;return me.run(i,()=>{P=e.handle().pipe(oe({next:a(w=>{E??={value:w},g.next(w)},"next"),complete:a(()=>{x(o.projectName,i,l,p,r.statusCode??200,v,void 0,m,k(r)),N(i,O,D,v,"ok"),_(),g.complete()},"complete")}),re(w=>{const F=w?.getResponse?.();F!==void 0&&(E??={value:F});const B=R(w);if(B!==void 0||typeof r.once!="function")x(o.projectName,i,l,p,B??S(r),v,w,m,k(r));else{let L=!1;const U=a(Y=>{if(L)return;L=!0;const Z=Y&&r.statusCode&&r.statusCode>=400?r.statusCode:S(r);x(o.projectName,i,l,p,Z,v,w,m,k(r))},"settle");r.once("finish",()=>U(!0)),r.once("close",()=>U(!1))}return N(i,O,D,v,"error"),_(),g.error(w),new G})).subscribe()}),()=>{P?.unsubscribe(),A=!0,H()}})}};j=te([se()],j);export{j as TraceInterceptor};const b=new Map,we=6e4,ye=a(()=>process.env.LENSMCP_HTTP_SHAPES!=="0","shapesOn");function Q(t,e,o,d,s,r,n){try{const c=r.statusCode??200,f=`${o} ${d} ${Math.floor(c/100)}`,I=Date.now();if(I-(b.get(f)??0)<we)return;b.set(f,I),b.size>2e3&&b.delete(b.keys().next().value);const i=s.headers??{},m=s.body!==void 0&&s.body!==null&&typeof s.body=="object"&&!Buffer.isBuffer(s.body)?z(s.body):void 0,l=n&&n.value!==void 0&&typeof n.value=="object"&&n.value!==null&&!Buffer.isBuffer(n.value)&&typeof n.value.pipe!="function"?z(n.value):void 0,p={id:h(),sessionId:e.sessionId,timestamp:I,source:"nestjs",category:"backend",severity:"info",context:{sessionId:e.sessionId,flowId:e.flowId,requestId:e.requestId,...e.runId?{runId:e.runId}:{}},fingerprint:$({kind:"http-exchange",identity:f}),title:`${o} ${d} \u2192 ${c} (its shape)`,raw:{kind:"http-exchange",method:o,route:d,status:c,request:{...ue(i,s.query,s.params),...m?{body:m}:{}},response:{...ce(r.getHeaders?.()??{},typeof i.origin=="string"?i.origin:void 0),...l?{body:l}:{}}}};C(p,t),q().emit(p)}catch{}}u(Q,"Ie"),a(Q,"recordExchange");function R(t){const e=t;if(typeof e?.getStatus=="function")return e.getStatus();if(typeof e?.status=="number"&&e.status>=100)return e.status;if(typeof e?.statusCode=="number"&&e.statusCode>=100)return e.statusCode}u(R,"U"),a(R,"ownStatus");const he=new Set(["TypeError","ReferenceError","SyntaxError","RangeError","EvalError","URIError"]);export function requestOutcome(t,e){return e instanceof Error&&he.has(e.name)&&R(e)===void 0?"fault":t<400?"ok":t<500?"refused":t===500?"fault":"declared"}u(requestOutcome,"requestOutcome"),a(requestOutcome,"requestOutcome");function X(t){return t==="ok"?"info":t==="refused"?"warning":"error"}u(X,"ye"),a(X,"severityOf");function S(t){return t.statusCode&&t.statusCode>=400?t.statusCode:500}u(S,"X"),a(S,"inferStatus");function y(t){if(typeof t=="string")return t;if(Array.isArray(t)&&typeof t[0]=="string")return t[0]}u(y,"w"),a(y,"stringHeader");function J(t,e,o,d){const s=q(),r=`request:${e} ${o}`,n={id:h(),sessionId:t.sessionId,timestamp:d,source:"nestjs",category:"backend",severity:"info",context:{sessionId:t.sessionId,flowId:t.flowId,requestId:t.requestId,originType:"request",originNodeId:r},fingerprint:$({kind:"flow-origin",identity:`${e}:${o}`}),title:`${e} ${o}`,raw:{kind:"flow-origin",originNodeId:r,method:e,route:o}};C(n,s.projectName),s.emit(n)}u(J,"ge"),a(J,"emitRequestOrigin");function N(t,e,o,d,s){if(!e||!o)return;const r=q(),n=Date.now()-d,c=`${e}.${o}`,f={id:h(),sessionId:t.sessionId,timestamp:Date.now(),source:"nestjs",category:"backend",severity:s==="error"?"error":"info",context:{sessionId:t.sessionId,flowId:t.flowId,requestId:t.requestId,...t.runId?{runId:t.runId}:{}},fingerprint:$({kind:"method-call",identity:c}),title:`${c} (${n}ms)${s==="error"?" \u2717":""}`,raw:{kind:"span",span:{name:c,role:"controller",flowId:t.flowId,requestId:t.requestId,startTime:d,endTime:Date.now(),durationMs:n,status:s}}};C(f,q().projectName),r.emit(f)}u(N,"z"),a(N,"emitControllerSpan");function K(t){if(!(t instanceof Error))return{message:String(t)};const e=t.stack?t.stack.split(`
2
2
  `).slice(0,30).join(`
3
- `):void 0;return{...t.name?{name:t.name}:{},message:t.message,...e?{stack:e}:{}}}u(Q,"ge"),a(Q,"errorDetail");function C(t,e){if(!e)return;const o=t.raw;o&&o.project===void 0&&(o.project=e)}u(C,"E"),a(C,"stampProject");function k(t){try{const e=t.getHeaders?.()["content-type"];return typeof e=="string"?e.split(";")[0]?.trim().toLowerCase():void 0}catch{return}}u(k,"O"),a(k,"responseContentType");function x(t,e,o,d,r,s,n,c,f){const I=q(),i=Date.now()-s,m=requestOutcome(r,n),l={id:y(),sessionId:e.sessionId,timestamp:Date.now(),source:"nestjs",category:"backend",severity:J(m),context:{sessionId:e.sessionId,flowId:e.flowId,requestId:e.requestId,...e.runId?{runId:e.runId}:{},...e.parentRequestId?{parentRequestId:e.parentRequestId}:{},originNodeId:e.originNodeId,traceparent:e.traceparent},fingerprint:$({kind:"server-request",identity:`${o}:${d}:${Math.floor(r/100)}xx`}),title:`${o} ${d} \u2192 ${r} (${i}ms)`,message:n instanceof Error?n.message:void 0,raw:{kind:"server-request",request:{method:o,route:d,status:r,outcome:m,durationMs:i,startedAt:s,...f?{contentType:f,streaming:f==="text/event-stream"}:{},endedAt:Date.now(),flowId:e.flowId,requestId:e.requestId,...e.parentRequestId?{parentRequestId:e.parentRequestId}:{},...typeof c=="string"?{exchangeId:c}:{},...e.runId?{runId:e.runId}:{},...e.dbCallCount||e.redisCallCount?{calls:{...e.dbCallCount?{db:e.dbCallCount}:{},...e.redisCallCount?{cache:e.redisCallCount}:{}}}:{},...n?{error:Q(n)}:{}}}},p={...l,id:y(),raw:{kind:"span",span:{name:`nest.request ${o} ${d}`,traceId:e.traceparent,flowId:e.flowId,requestId:e.requestId,startTime:s,endTime:Date.now(),durationMs:i,status:m==="ok"?"ok":"error"}}};C(l,t),C(p,t),I.emit(l),I.emit(p)}u(x,"j"),a(x,"emitRequest");
3
+ `):void 0;return{...t.name?{name:t.name}:{},message:t.message,...e?{stack:e}:{}}}u(K,"we"),a(K,"errorDetail");function C(t,e){if(!e)return;const o=t.raw;o&&o.project===void 0&&(o.project=e)}u(C,"b"),a(C,"stampProject");function k(t){try{const e=t.getHeaders?.()["content-type"];return typeof e=="string"?e.split(";")[0]?.trim().toLowerCase():void 0}catch{return}}u(k,"D"),a(k,"responseContentType");function x(t,e,o,d,s,r,n,c,f){const I=q(),i=Date.now()-r,m=requestOutcome(s,n),l={id:h(),sessionId:e.sessionId,timestamp:Date.now(),source:"nestjs",category:"backend",severity:X(m),context:{sessionId:e.sessionId,flowId:e.flowId,requestId:e.requestId,...e.runId?{runId:e.runId}:{},...e.parentRequestId?{parentRequestId:e.parentRequestId}:{},originNodeId:e.originNodeId,traceparent:e.traceparent},fingerprint:$({kind:"server-request",identity:`${o}:${d}:${Math.floor(s/100)}xx`}),title:`${o} ${d} \u2192 ${s} (${i}ms)`,message:n instanceof Error?n.message:void 0,raw:{kind:"server-request",request:{method:o,route:d,status:s,outcome:m,durationMs:i,startedAt:r,...f?{contentType:f,streaming:f==="text/event-stream"}:{},endedAt:Date.now(),flowId:e.flowId,requestId:e.requestId,...e.parentRequestId?{parentRequestId:e.parentRequestId}:{},...typeof c=="string"?{exchangeId:c}:{},...e.runId?{runId:e.runId}:{},...e.dbCallCount||e.redisCallCount?{calls:{...e.dbCallCount?{db:e.dbCallCount}:{},...e.redisCallCount?{cache:e.redisCallCount}:{}}}:{},...n?{error:K(n)}:{}}}},p={...l,id:h(),raw:{kind:"span",span:{name:`nest.request ${o} ${d}`,traceId:e.traceparent,flowId:e.flowId,requestId:e.requestId,startTime:r,endTime:Date.now(),durationMs:i,status:m==="ok"?"ok":"error"}}};C(l,t),C(p,t),I.emit(l),I.emit(p)}u(x,"O"),a(x,"emitRequest");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/nest-instrumentation",
3
- "version": "1.25.31",
3
+ "version": "1.25.32",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -14,9 +14,9 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
- "@lensmcp/core": "1.25.31",
18
- "@lensmcp/memory-tracker": "1.25.31",
19
- "@lensmcp/protocol-types": "1.25.31",
17
+ "@lensmcp/core": "1.25.32",
18
+ "@lensmcp/memory-tracker": "1.25.32",
19
+ "@lensmcp/protocol-types": "1.25.32",
20
20
  "tslib": "^2.3.0"
21
21
  },
22
22
  "peerDependencies": {