@senzops/apm-node 1.1.15 → 1.1.17
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/CHANGELOG.md +37 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/core/client.ts +132 -96
- package/src/core/transport.ts +30 -9
- package/src/core/types.ts +12 -0
- package/src/instrumentation/http.ts +19 -41
- package/src/utils/traceContext.ts +44 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 1.1.17
|
|
2
|
+
|
|
3
|
+
feat: add logs monitoring
|
|
4
|
+
|
|
5
|
+
# 1.1.16
|
|
6
|
+
|
|
7
|
+
feat: support traceparent of RUM
|
|
8
|
+
|
|
9
|
+
# 1.1.15
|
|
10
|
+
|
|
11
|
+
feat: make setupGlobalErrorHandlers more robust and send much refined data
|
|
12
|
+
|
|
13
|
+
# 1.1.14
|
|
14
|
+
|
|
15
|
+
chore: make task auto instrumentation more robust
|
|
16
|
+
fix: ESM module patching
|
|
17
|
+
fix: module importing and patching for cron and bullmq auto instrumentation
|
|
18
|
+
|
|
19
|
+
# 1.1.12
|
|
20
|
+
|
|
21
|
+
feat: add advanced features in task monitoring
|
|
22
|
+
|
|
23
|
+
# 1.1.10
|
|
24
|
+
|
|
25
|
+
fix: module resolution for task monitoring instrumentations
|
|
26
|
+
|
|
27
|
+
# 1.1.9
|
|
28
|
+
|
|
29
|
+
feat: add task monitoring
|
|
30
|
+
|
|
31
|
+
# 1.1.8
|
|
32
|
+
|
|
33
|
+
feat: add error tracking in apm
|
|
34
|
+
|
|
35
|
+
# 1.1.7
|
|
36
|
+
|
|
37
|
+
stable working code
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.global.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";(()=>{var st=Object.create;var $=Object.defineProperty;var at=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var ct=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var S=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var ut=(r,t,n,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of it(t))!pt.call(r,o)&&o!==n&&$(r,o,{get:()=>t[o],enumerable:!(e=at(t,o))||e.enumerable});return r};var M=(r,t,n)=>(n=r!=null?st(ct(r)):{},ut(t||!r||!r.__esModule?$(n,"default",{value:r,enumerable:!0}):n,r));var v=class{constructor(t){this.config=t;this.traceQueue=[];this.apmErrorQueue=[];this.taskQueue=[];this.taskErrorQueue=[];this.timer=null;let n=t.endpoint||"https://api.senzor.dev";this.apmEndpoint=n.includes("/api/ingest")?n:`${n}/api/ingest/apm`,this.taskEndpoint=n.includes("/api/ingest")?n.replace("/apm","/task"):`${n}/api/ingest/task`,typeof setInterval<"u"&&(this.timer=setInterval(()=>this.flush(),t.flushInterval||1e4),this.timer&&typeof this.timer.unref=="function"&&this.timer.unref())}addTrace(t){this.traceQueue.push(t),this.checkFlush()}addTask(t){this.taskQueue.push(t),this.checkFlush()}addError(t,n="apm"){n==="task"?this.taskErrorQueue.push(t):this.apmErrorQueue.push(t),this.checkFlush()}checkFlush(){let t=this.traceQueue.length+this.apmErrorQueue.length,n=this.taskQueue.length+this.taskErrorQueue.length;(t>=(this.config.batchSize||100)||n>=(this.config.batchSize||100))&&this.flush()}async flush(){let t={traces:[...this.traceQueue],errors:[...this.apmErrorQueue]},n={runs:[...this.taskQueue],errors:[...this.taskErrorQueue]};this.traceQueue=[],this.apmErrorQueue=[],this.taskQueue=[],this.taskErrorQueue=[];let e={"Content-Type":"application/json","x-service-api-key":this.config.apiKey};try{let o=[];(t.traces.length>0||t.errors.length>0)&&o.push(fetch(this.apmEndpoint,{method:"POST",headers:e,body:JSON.stringify(t),keepalive:!0})),(n.runs.length>0||n.errors.length>0)&&o.push(fetch(this.taskEndpoint,{method:"POST",headers:e,body:JSON.stringify(n),keepalive:!0})),await Promise.allSettled(o),this.config.debug&&console.log(`[Senzor] Flushed: ${t.traces.length} traces, ${n.runs.length} tasks`)}catch(o){this.config.debug&&console.error("[Senzor] Transport Flush Error:",o)}}};var G=S("async_hooks"),F=new G.AsyncLocalStorage,l={run:(r,t)=>F.run(r,t),current:()=>F.getStore(),addSpan:r=>{let t=F.getStore();t&&t.spans.push(r)}};var b=S("crypto");var R=M(S("http")),O=M(S("https")),E=S("url");var P=S("crypto"),z=(r,t,n)=>{if(!r[t])return;let e=r[t];r[t]=n(e)},_=(r,t=!1)=>{if(!globalThis.fetch)return;let n="";try{n=new E.URL(r).hostname}catch{}let e=globalThis.fetch;globalThis.fetch=async(o,s)=>{let a="";if(typeof o=="string"?a=o:o instanceof E.URL?a=o.toString():o&&o.url&&(a=o.url),n&&a.includes(n))return e(o,s);let c=l.current();if(!c)return e(o,s);let i=(s?.method||"GET").toUpperCase(),u=performance.now()-c.startTime,g=performance.now(),m=(0,P.randomUUID)(),y="unknown";try{y=new E.URL(a).hostname}catch{}let h={...s};h.headers||(h.headers={});let T=(d,f)=>{h.headers instanceof Headers?h.headers.set(d,f):Array.isArray(h.headers)?h.headers.push([d,f]):h.headers[d]=f};T("x-senzor-trace-id",c.id),T("x-senzor-parent-span-id",m);try{let d=await e(o,h),f=performance.now()-g;return l.addSpan({spanId:m,name:`${i} ${y}`,type:"http",startTime:u,duration:f,status:d.status,meta:{url:a,method:i,library:"fetch"}}),d}catch(d){let f=performance.now()-g;throw l.addSpan({spanId:m,name:`${i} ${y}`,type:"http",startTime:u,duration:f,status:500,meta:{error:d.message,url:a,library:"fetch"}}),d}}},L=(r,t=!1)=>{let n="";try{n=new E.URL(r).hostname}catch{}let e=o=>function(...s){let a={},c="",i=0;if(typeof s[0]=="string"||s[0]instanceof E.URL?(c=s[0].toString(),i=1):i=0,(!s[i]||typeof s[i]!="object")&&(s[i]={}),a=s[i],!c){let w=a.protocol||(a.port===443?"https:":"http:"),k=a.hostname||a.host||"localhost",H=a.path||"/";c=`${w}//${k}${H}`}if(n&&(c.includes(n)||a.hostname&&a.hostname.includes(n)))return o.apply(this,s);let u=l.current();if(!u)return o.apply(this,s);let g=(a.method||"GET").toUpperCase(),m=performance.now()-u.startTime,y=performance.now(),h=(0,P.randomUUID)(),T="unknown";try{T=new E.URL(c).hostname}catch{T=a.hostname||"unknown"}a.headers||(a.headers={}),a.headers["x-senzor-trace-id"]=u.id,a.headers["x-senzor-parent-span-id"]=h,t&&console.log(`[Senzor] Injecting headers to ${c}`);let d=o.apply(this,s),f=(w,k)=>{let H=performance.now()-y;l.addSpan({spanId:h,name:`${g} ${T}`,type:"http",startTime:m,duration:H,status:k?500:w?.statusCode||0,meta:{url:c,method:g,library:"http"}})};return d.on("response",w=>{w.once("end",()=>f(w)),w.once("close",()=>f(w)),w.once("error",k=>f(w,k))}),d.on("error",w=>f(null,w)),d};z(R.default,"request",e),z(R.default,"get",e),z(O.default,"request",e),z(O.default,"get",e)};var K=(r=!1)=>{try{let t=S("mongodb"),n=t.Collection,e=t.FindCursor||S("mongodb/lib/cursor/find_cursor").FindCursor,o=t.AggregationCursor||S("mongodb/lib/cursor/aggregation_cursor").AggregationCursor;r&&console.log("[Senzor] Instrumenting MongoDB (Collection + Cursors)...");let s=(i,u,g,m,y,h)=>{let T=performance.now()-m;l.addSpan({name:`MongoDB ${i}`,type:"db",startTime:performance.now()-y-T,duration:T,status:h?500:0,meta:{collection:g,operation:u,error:h?h.message:void 0}}),r&&console.log(`[Senzor] Captured Mongo: ${i} (${T.toFixed(2)}ms)`)};["insertOne","insertMany","updateOne","updateMany","deleteOne","deleteMany","countDocuments"].forEach(i=>{if(!n.prototype[i])return;let u=n.prototype[i];n.prototype[i]=function(...g){let m=l.current();if(!m)return u.apply(this,g);let y=performance.now(),h=m.startTime,T=this.collectionName;try{let d=u.apply(this,g);return d&&typeof d.then=="function"?d.then(f=>(s(i,i,T,y,h),f),f=>{throw s(i,i,T,y,h,f),f}):d}catch(d){throw s(i,i,T,y,h,d),d}}});let c=(i,u)=>{if(!i||!i.prototype.toArray)return;let g=i.prototype.toArray;i.prototype.toArray=function(...m){let y=l.current();if(!y)return g.apply(this,m);let h=performance.now(),T=y.startTime,d=this.namespace?.collection||"unknown",f=k=>(s(u,u,d,h,T),k),w=k=>{throw s(u,u,d,h,T,k),k};try{let k=g.apply(this,m);return k&&typeof k.then=="function"?k.then(f,w):f(k)}catch(k){w(k)}}};c(e,"find"),c(o,"aggregate")}catch(t){r&&console.warn("[Senzor] MongoDB instrumentation warning:",t.message)}};var B=()=>{try{let r=S("pg"),t=r.Client.prototype.query;r.Client.prototype.query=function(...n){let e=l.current();if(!e)return t.apply(this,n);let o=performance.now()-e.startTime,s=performance.now(),a=typeof n[0]=="string"?n[0]:n[0].text,c=t.apply(this,n);return c&&typeof c.then=="function"?c.then(i=>{let u=performance.now()-s;return l.addSpan({name:"Postgres Query",type:"db",startTime:o,duration:u,meta:{query:a}}),i}):c}}catch{}};var A=M(S("module"));var W=Symbol.for("senzor.require.patched"),I=Symbol.for("senzor.require.hooks");function dt(){let r=A.default;return r[I]||Object.defineProperty(r,I,{value:new Map,enumerable:!1}),r[I]}function lt(r,t){let n=A.default[I];if(!n)return;let e=n.get(r);if(e?.length)for(let o of e)try{o(t)}catch(s){console.error(`[Senzor] instrumentation failed for ${r}`,s)}}function ht(){let r=A.default;if(r[W])return;let t=r._load;r._load=function(e,o,s){let a=t.apply(this,arguments);return lt(e,a),a},Object.defineProperty(r,W,{value:!0,enumerable:!1})}function mt(r,t){try{let n=S.resolve(r),e=S.cache?.[n];e?.exports&&t(e.exports)}catch{}}function ft(r,t){try{let n=S(r);n&&t(n)}catch{}}function yt(r,t){let n=0,e=5,o=setInterval(()=>{n++;try{let s=S(r);s&&(t(s),clearInterval(o))}catch{}n>=e&&clearInterval(o)},200)}var C=(r,t)=>{let n=dt();n.has(r)||n.set(r,[]),n.get(r).push(t),ht(),mt(r,t),ft(r,t),yt(r,t)};var j=Symbol.for("senzor.bullmq.patched");function J(r,t,n){if(!r?.Worker?.prototype)return;let e=r.Worker.prototype,o=e.processJob;typeof o!="function"||o[j]||(e.processJob=async function(s){let a=s.timestamp?Date.now()-s.timestamp:0,c=(s.attemptsMade||0)+1,i=s.opts?.attempts??1,u=c>=i,g=s.name==="__default__"?s.queueName:`${s.queueName}:${s.name}`;return t.startTask(g,"queue",{queueDelay:a,attempts:c,isDeadLetter:!1,metadata:{jobId:s.id,queueName:s.queueName,maxAttempts:i}},async()=>{try{let m=await o.call(this,s);return t.endTask("success"),m}catch(m){try{let y=l.current();y&&y.contextType==="task"&&u&&(y.data.isDeadLetter=!0)}catch{}throw t.captureError(m,{queueName:s.queueName,jobId:s.id,isDeadLetter:u}),t.endTask("failed"),m}})},Object.defineProperty(e.processJob,j,{value:!0}),n&&console.log("[Senzor] BullMQ instrumented"))}var q=(r,t)=>{C("bullmq",n=>{J(n,r,t),n?.default&&J(n.default,r,t)})};var Z=Symbol.for("senzor.cron.patched");function gt(r){return typeof r=="object"&&r!==null?r:r?{timezone:r}:{}}function V(r,t,n){let e=r.schedule;if(typeof e!="function"||e[Z])return;let o=e,s=function(a,c,i){if(typeof c!="function")return o.call(this,a,c,i);try{let u=gt(i),g=u?.name??`cron: ${a}`,m=t.wrapTask(g,"cron",{expression:a,metadata:u},c);return o.call(this,a,m,i)}catch(u){return n&&console.error("[Senzor] cron wrap failed",u),o.call(this,a,c,i)}};Object.defineProperty(s,Z,{value:!0,enumerable:!1});try{r.schedule=s}catch{n&&console.warn("[Senzor] unable to patch cron schedule (readonly export)")}n&&console.log("[Senzor] node-cron instrumented")}var X=(r,t)=>{C("node-cron",n=>{n&&(V(n,r,t),n.default&&V(n.default,r,t))})};var N={name:"@senzops/apm-node",version:"1.1.15",description:"Universal APM SDK for Senzor",main:"dist/index.js",types:"dist/index.d.ts",scripts:{build:"tsup src/index.ts --format cjs,esm,iife --dts --clean --minify",prepublishOnly:"npm run build"},dependencies:{},devDependencies:{"@types/node":"^20.0.0",tsup:"^8.0.0",typescript:"^5.0.0"},engines:{node:">=18.0.0"},keywords:["apm","monitoring","senzor","node","javascript","api","observability"],author:"Senzops",license:"MIT"};var U={name:N.name,version:N.version};var D=class{constructor(){this.transport=null;this.options=null;this.isInstrumented=!1}init(t){if(!t.apiKey){console.warn("[Senzor] API Key missing. SDK disabled.");return}this.options=t;let n=t.endpoint||"https://api.senzor.dev/api/ingest/apm",e=t.debug||!1;if(this.transport=new v({...t,endpoint:n}),!this.isInstrumented){this.setupGlobalErrorHandlers();try{L(n,e)}catch{}try{_(n,e)}catch{}try{K(e)}catch{}try{B()}catch{}try{q(this,e)}catch{}try{X(this,e)}catch{}this.isInstrumented=!0,e&&console.log("[Senzor] Auto-instrumentation & Error Tracking enabled")}}setupGlobalErrorHandlers(){if(process.__senzorGlobalHandlersInstalled)return;process.__senzorGlobalHandlersInstalled=!0;let t=()=>{try{return{pid:process.pid,ppid:process.ppid,platform:process.platform,uptimeSec:Math.floor(process.uptime()),env:process.env.NODE_ENV||"unknown"}}catch{return{}}},n=()=>{try{let o=process.memoryUsage();return{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}catch{return{}}},e=(o,s={})=>{try{let a;if(o instanceof Error)a=o;else if(typeof o=="string")a=new Error(o);else try{a=new Error(JSON.stringify(o))}catch{a=new Error("Non-serializable rejection reason")}let c={...s,runtime:{name:"node",version:process.version},process:t(),memory:n(),sdk:{name:U.name,version:U.version}};this.captureError(a,c)}catch(a){try{this.options?.debug&&console.error("[Senzor] Error handler failure:",a)}catch{}}};process.on("uncaughtExceptionMonitor",o=>{e(o,{type:"uncaughtExceptionMonitor",severity:"fatal"})}),process.on("uncaughtException",o=>{e(o,{type:"uncaughtException",severity:"fatal"})}),process.on("unhandledRejection",o=>{e(o,{type:"unhandledRejection",severity:"error"})}),process.on("warning",o=>{e(o,{type:"processWarning",severity:"warning"})}),process.on("multipleResolves",(o,s,a)=>{e(a||new Error("Multiple promise resolves"),{type:"multipleResolves",resolveType:o,severity:"warning"})}),process.on("rejectionHandled",o=>{if(this.options?.debug)try{console.warn("[Senzor] rejectionHandled event detected")}catch{}}),process.on("SIGTERM",()=>{e(new Error("Process received SIGTERM"),{type:"processSignal",signal:"SIGTERM"})}),process.on("SIGINT",()=>{e(new Error("Process received SIGINT"),{type:"processSignal",signal:"SIGINT"})})}startTrace(t,n){if(!this.transport)return n();let e,o;if(t.headers){let a=c=>{if(t.headers[c])return t.headers[c];if(t.headers[c.toLowerCase()])return t.headers[c.toLowerCase()]};e=a("x-senzor-trace-id"),o=a("x-senzor-parent-span-id"),Array.isArray(e)&&(e=e[0]),Array.isArray(o)&&(o=o[0])}let s={id:(0,b.randomUUID)(),contextType:"apm",startTime:performance.now(),data:{...t,parentTraceId:e,parentSpanId:o},spans:[]};return l.run(s,n)}endTrace(t,n={}){let e=l.current();if(!e||e.contextType!=="apm"||!this.transport)return;let o=performance.now()-e.startTime,s={traceId:e.id,parentTraceId:e.data.parentTraceId,parentSpanId:e.data.parentSpanId,...e.data,...n,status:t,duration:o,spans:e.spans,timestamp:new Date().toISOString()};this.transport.addTrace(s)}startTask(t,n,e,o){if(!this.transport)return o();let s=l.current(),a=s?.contextType==="apm"?s.id:void 0,c=process.memoryUsage?process.memoryUsage().heapUsed:0,i=process.cpuUsage?process.cpuUsage():void 0,u={id:(0,b.randomUUID)(),contextType:"task",startTime:performance.now(),startMemory:c,startCpu:i,data:{taskName:t,taskType:n,triggerTraceId:a,...e},spans:[]};return l.run(u,o)}endTask(t,n={}){let e=l.current();if(!e||e.contextType!=="task"||!this.transport)return;let o;if(process.memoryUsage&&e.startMemory!==void 0&&process.cpuUsage&&e.startCpu){let a=process.memoryUsage().heapUsed,c=process.cpuUsage(e.startCpu);o={memoryDeltaBytes:a-e.startMemory,cpuUserUs:c.user,cpuSystemUs:c.system}}let s={runId:e.id,taskName:e.data.taskName,taskType:e.data.taskType,triggerTraceId:e.data.triggerTraceId,queueDelay:e.data.queueDelay,attempts:e.data.attempts,isDeadLetter:e.data.isDeadLetter,metadata:{...e.data.metadata,...n},resourceMetrics:o,status:t,duration:performance.now()-e.startTime,spans:e.spans,timestamp:new Date().toISOString()};this.transport.addTask(s)}wrapTask(t,n,e={},o){return(async(...s)=>this.startTask(t,n,e,async()=>{try{let a=await o(...s);return this.endTask("success"),a}catch(a){throw this.captureError(a,{taskName:t}),this.endTask("failed"),a}}))}captureError(t,n={}){if(!this.transport)return;let e;t instanceof Error?e=t:e=new Error(String(t));let o=l.current(),s={errorClass:e.name||"Error",message:e.message,stackTrace:e.stack,context:n,timestamp:new Date().toISOString()};o?.contextType==="task"?this.transport.addError({...s,runId:o.id},"task"):this.transport.addError({...s,traceId:o?.id},"apm")}track(t){this.transport?.addTrace({traceId:(0,b.randomUUID)(),...t,spans:[],timestamp:new Date().toISOString()})}startSpan(t,n="custom"){let e=l.current();if(!e)return{end:()=>{}};let o=performance.now()-e.startTime,s=performance.now(),a=(0,b.randomUUID)();return{end:(c,i)=>{l.addSpan({spanId:a,name:t,type:n,startTime:o,duration:performance.now()-s,status:i,meta:c})}}}async flush(){this.transport&&await this.transport.flush()}},p=new D;var Y=()=>(r,t,n)=>{p.startTrace({method:r.method,path:r.originalUrl||r.url,ip:r.ip||r.socket?.remoteAddress,userAgent:r.headers["user-agent"],headers:r.headers},()=>{t.once("finish",()=>{try{let e="UNKNOWN";r.route&&r.route.path?e=(r.baseUrl||"")+r.route.path:t.statusCode===404?e="Not Found":e=r.path||"Wildcard",p.endTrace(t.statusCode,{route:e})}catch{}}),n()})},tt=()=>(r,t,n,e)=>{p.captureError(r),e(r)};var x=r=>!r||r==="/"?"/":r.replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,":uuid").replace(/[0-9a-fA-F]{24}/g,":objectId").replace(/\/(\d+)(?=\/|$)/g,"/:id").split("?")[0],Q=(r,t)=>r.route&&r.route.path?(r.baseUrl||"")+r.route.path:r.context&&r.context.matchedRoute?r.context.matchedRoute.path:r.routerPath?r.routerPath:x(t);var et=r=>t=>{let n=t.node.req,e=n.originalUrl||n.url||"/";return p.startTrace({method:n.method||"GET",path:e,ip:n.headers["x-forwarded-for"]||n.socket?.remoteAddress,userAgent:n.headers["user-agent"],headers:n.headers},async()=>{try{let o=await r(t),s=200;return t.node.res.statusCode&&(s=t.node.res.statusCode),o&&o.statusCode&&(s=o.statusCode),p.endTrace(s,{route:Q(t,e)}),o}catch(o){p.captureError(o);let s=o.statusCode||o.status||500;throw p.endTrace(s,{route:Q(t,e)}),o}})};var rt=r=>async(t,n)=>{let e=t.url?new URL(t.url):{pathname:"/"},o=t.method||"GET",s={},a,c;return typeof t.headers.get=="function"?(a=t.headers.get("user-agent"),c=t.headers.get("x-forwarded-for"),t.headers.forEach((i,u)=>{s[u]=i})):(s=t.headers,a=s["user-agent"],c=s["x-forwarded-for"]),p.startTrace({method:o,path:e.pathname,userAgent:a,ip:c,headers:s},async()=>{try{let i=await r(t,n),u=i?.status||200;return p.endTrace(u,{route:x(e.pathname)}),i}catch(i){throw p.captureError(i),p.endTrace(500,{route:x(e.pathname)}),i}})},nt=r=>async(t,n)=>{let e=t.url?t.url.split("?")[0]:"/";return p.startTrace({method:t.method||"GET",path:e,userAgent:t.headers["user-agent"],ip:t.headers["x-forwarded-for"]||t.socket?.remoteAddress,headers:t.headers},async()=>{let o=()=>{p.endTrace(n.statusCode||200,{route:x(e)})};n.once("finish",o),n.once("close",o);try{return await r(t,n)}catch(s){throw p.captureError(s),s}})};var ot=(r,t,n)=>{t&&t.apiKey&&p.init(t),r.addHook("onRequest",(e,o,s)=>{p.startTrace({method:e.method,path:e.raw.url||e.url,ip:e.ip,userAgent:e.headers["user-agent"],headers:e.headers},()=>s())}),r.addHook("onError",(e,o,s,a)=>{p.captureError(s),a()}),r.addHook("onResponse",(e,o,s)=>{let a=e.routeOptions?.url||e.routerPath||"UNKNOWN";p.endTrace(o.statusCode,{route:a}),s()}),n()};var kt={init:r=>p.init(r),flush:()=>p.flush(),track:p.track.bind(p),startSpan:p.startSpan.bind(p),captureException:p.captureError.bind(p),wrapTask:p.wrapTask.bind(p),startTask:p.startTask.bind(p),requestHandler:Y,errorHandler:tt,wrapNextRoute:rt,wrapNextPages:nt,wrapH3:et,fastifyPlugin:ot},ue=kt;})();
|
|
1
|
+
"use strict";(()=>{var pe=Object.create;var D=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var de=Object.getPrototypeOf,he=Object.prototype.hasOwnProperty;var w=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var me=(r,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of le(e))!he.call(r,o)&&o!==n&&D(r,o,{get:()=>e[o],enumerable:!(t=ue(e,o))||t.enumerable});return r};var H=(r,e,n)=>(n=r!=null?pe(de(r)):{},me(e||!r||!r.__esModule?D(n,"default",{value:r,enumerable:!0}):n,r));var x=class{constructor(e){this.config=e;this.traceQueue=[];this.apmErrorQueue=[];this.apmLogQueue=[];this.taskQueue=[];this.taskErrorQueue=[];this.taskLogQueue=[];this.timer=null;let n=e.endpoint||"https://api.senzor.dev";this.apmEndpoint=n.includes("/api/ingest")?n:`${n}/api/ingest/apm`,this.taskEndpoint=n.includes("/api/ingest")?n.replace("/apm","/task"):`${n}/api/ingest/task`,typeof setInterval<"u"&&(this.timer=setInterval(()=>this.flush(),e.flushInterval||1e4),this.timer&&typeof this.timer.unref=="function"&&this.timer.unref())}addTrace(e){this.traceQueue.push(e),this.checkFlush()}addTask(e){this.taskQueue.push(e),this.checkFlush()}addError(e,n="apm"){n==="task"?this.taskErrorQueue.push(e):this.apmErrorQueue.push(e),this.checkFlush()}addLog(e,n="apm"){n==="task"?this.taskLogQueue.push(e):this.apmLogQueue.push(e),this.checkFlush()}checkFlush(){let e=this.traceQueue.length+this.apmErrorQueue.length+this.apmLogQueue.length,n=this.taskQueue.length+this.taskErrorQueue.length+this.taskLogQueue.length;(e>=(this.config.batchSize||100)||n>=(this.config.batchSize||100))&&this.flush()}async flush(){let e={traces:[...this.traceQueue],errors:[...this.apmErrorQueue],logs:[...this.apmLogQueue]},n={runs:[...this.taskQueue],errors:[...this.taskErrorQueue],logs:[...this.taskLogQueue]};this.traceQueue=[],this.apmErrorQueue=[],this.apmLogQueue=[],this.taskQueue=[],this.taskErrorQueue=[],this.taskLogQueue=[];let t={"Content-Type":"application/json","x-service-api-key":this.config.apiKey};try{let o=[];(e.traces.length>0||e.errors.length>0||e.logs.length>0)&&o.push(fetch(this.apmEndpoint,{method:"POST",headers:t,body:JSON.stringify(e),keepalive:!0})),(n.runs.length>0||n.errors.length>0||n.logs.length>0)&&o.push(fetch(this.taskEndpoint,{method:"POST",headers:t,body:JSON.stringify(n),keepalive:!0})),await Promise.allSettled(o),this.config.debug&&console.log(`[Senzor] Flushed: APM(${e.traces.length} traces, ${e.logs.length} logs), Task(${n.runs.length} runs, ${n.logs.length} logs)`)}catch(o){this.config.debug&&console.error("[Senzor] Transport Flush Error:",o)}}};var $=w("async_hooks"),O=new $.AsyncLocalStorage,m={run:(r,e)=>O.run(r,e),current:()=>O.getStore(),addSpan:r=>{let e=O.getStore();e&&e.spans.push(r)}};var A=w("crypto");var F=H(w("http")),L=H(w("https")),E=w("url");var _=w("crypto");var fe=/^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/,G=r=>{if(!r)return null;let e=Array.isArray(r)?r[0]:r;if(typeof e!="string")return null;let n=e.trim().toLowerCase().match(fe);if(!n)return null;let t=n[1],o=n[2],s=n[3];if(t==="00000000000000000000000000000000"||o==="0000000000000000")return null;let a=(parseInt(s,16)&1)===1;return{traceId:t,parentSpanId:o,sampled:a}},R=(r,e,n=!0)=>`00-${r}-${e}-${n?"01":"00"}`;var I=(r,e,n)=>{if(!r[e])return;let t=r[e];r[e]=n(t)},j=()=>(0,_.randomUUID)().replace(/-/g,"").slice(0,16),K=(r,e=!1)=>{if(!globalThis.fetch)return;let n="";try{n=new E.URL(r).hostname}catch{}let t=globalThis.fetch;globalThis.fetch=async(o,s)=>{let a="";if(typeof o=="string"?a=o:o instanceof E.URL?a=o.toString():o&&o.url&&(a=o.url),n&&a.includes(n))return t(o,s);let c=m.current();if(!c)return t(o,s);let i=(s?.method||"GET").toUpperCase(),p=performance.now()-c.startTime,d=performance.now(),u=j(),y="unknown";try{y=new E.URL(a).hostname}catch{}let f={...s};f.headers||(f.headers={});let T=(h,g)=>{f.headers instanceof Headers?f.headers.set(h,g):Array.isArray(f.headers)?f.headers.push([h,g]):f.headers[h]=g};T("traceparent",R(c.id,u)),T("x-senzor-trace-id",c.id),T("x-senzor-parent-span-id",u);try{let h=await t(o,f),g=performance.now()-d;return m.addSpan({spanId:u,name:`${i} ${y}`,type:"http",startTime:p,duration:g,status:h.status,meta:{url:a,method:i,library:"fetch"}}),h}catch(h){let g=performance.now()-d;throw m.addSpan({spanId:u,name:`${i} ${y}`,type:"http",startTime:p,duration:g,status:500,meta:{error:h.message,url:a,library:"fetch"}}),h}}},W=(r,e=!1)=>{let n="";try{n=new E.URL(r).hostname}catch{}let t=o=>function(...s){let a={},c="",i=0;if(typeof s[0]=="string"||s[0]instanceof E.URL?(c=s[0].toString(),i=1):i=0,(!s[i]||typeof s[i]!="object")&&(s[i]={}),a=s[i],!c){let S=a.protocol||(a.port===443?"https:":"http:"),k=a.hostname||a.host||"localhost",M=a.path||"/";c=`${S}//${k}${M}`}if(n&&(c.includes(n)||a.hostname&&a.hostname.includes(n)))return o.apply(this,s);let p=m.current();if(!p)return o.apply(this,s);let d=(a.method||"GET").toUpperCase(),u=performance.now()-p.startTime,y=performance.now(),f=j(),T="unknown";try{T=new E.URL(c).hostname}catch{T=a.hostname||"unknown"}a.headers||(a.headers={}),a.headers.traceparent=R(p.id,f),a.headers["x-senzor-trace-id"]=p.id,a.headers["x-senzor-parent-span-id"]=f,e&&console.log(`[Senzor] Injecting W3C traceparent headers to ${c}`);let h=o.apply(this,s),g=(S,k)=>{let M=performance.now()-y;m.addSpan({spanId:f,name:`${d} ${T}`,type:"http",startTime:u,duration:M,status:k?500:S?.statusCode||0,meta:{url:c,method:d,library:"http"}})};return h.on("response",S=>{S.once("end",()=>g(S)),S.once("close",()=>g(S)),S.once("error",k=>g(S,k))}),h.on("error",S=>g(null,S)),h};I(F.default,"request",t),I(F.default,"get",t),I(L.default,"request",t),I(L.default,"get",t)};var B=(r=!1)=>{try{let e=w("mongodb"),n=e.Collection,t=e.FindCursor||w("mongodb/lib/cursor/find_cursor").FindCursor,o=e.AggregationCursor||w("mongodb/lib/cursor/aggregation_cursor").AggregationCursor;r&&console.log("[Senzor] Instrumenting MongoDB (Collection + Cursors)...");let s=(i,p,d,u,y,f)=>{let T=performance.now()-u;m.addSpan({name:`MongoDB ${i}`,type:"db",startTime:performance.now()-y-T,duration:T,status:f?500:0,meta:{collection:d,operation:p,error:f?f.message:void 0}}),r&&console.log(`[Senzor] Captured Mongo: ${i} (${T.toFixed(2)}ms)`)};["insertOne","insertMany","updateOne","updateMany","deleteOne","deleteMany","countDocuments"].forEach(i=>{if(!n.prototype[i])return;let p=n.prototype[i];n.prototype[i]=function(...d){let u=m.current();if(!u)return p.apply(this,d);let y=performance.now(),f=u.startTime,T=this.collectionName;try{let h=p.apply(this,d);return h&&typeof h.then=="function"?h.then(g=>(s(i,i,T,y,f),g),g=>{throw s(i,i,T,y,f,g),g}):h}catch(h){throw s(i,i,T,y,f,h),h}}});let c=(i,p)=>{if(!i||!i.prototype.toArray)return;let d=i.prototype.toArray;i.prototype.toArray=function(...u){let y=m.current();if(!y)return d.apply(this,u);let f=performance.now(),T=y.startTime,h=this.namespace?.collection||"unknown",g=k=>(s(p,p,h,f,T),k),S=k=>{throw s(p,p,h,f,T,k),k};try{let k=d.apply(this,u);return k&&typeof k.then=="function"?k.then(g,S):g(k)}catch(k){S(k)}}};c(t,"find"),c(o,"aggregate")}catch(e){r&&console.warn("[Senzor] MongoDB instrumentation warning:",e.message)}};var J=()=>{try{let r=w("pg"),e=r.Client.prototype.query;r.Client.prototype.query=function(...n){let t=m.current();if(!t)return e.apply(this,n);let o=performance.now()-t.startTime,s=performance.now(),a=typeof n[0]=="string"?n[0]:n[0].text,c=e.apply(this,n);return c&&typeof c.then=="function"?c.then(i=>{let p=performance.now()-s;return m.addSpan({name:"Postgres Query",type:"db",startTime:o,duration:p,meta:{query:a}}),i}):c}}catch{}};var v=H(w("module"));var q=Symbol.for("senzor.require.patched"),z=Symbol.for("senzor.require.hooks");function ye(){let r=v.default;return r[z]||Object.defineProperty(r,z,{value:new Map,enumerable:!1}),r[z]}function ge(r,e){let n=v.default[z];if(!n)return;let t=n.get(r);if(t?.length)for(let o of t)try{o(e)}catch(s){console.error(`[Senzor] instrumentation failed for ${r}`,s)}}function Te(){let r=v.default;if(r[q])return;let e=r._load;r._load=function(t,o,s){let a=e.apply(this,arguments);return ge(t,a),a},Object.defineProperty(r,q,{value:!0,enumerable:!1})}function ke(r,e){try{let n=w.resolve(r),t=w.cache?.[n];t?.exports&&e(t.exports)}catch{}}function Se(r,e){try{let n=w(r);n&&e(n)}catch{}}function we(r,e){let n=0,t=5,o=setInterval(()=>{n++;try{let s=w(r);s&&(e(s),clearInterval(o))}catch{}n>=t&&clearInterval(o)},200)}var C=(r,e)=>{let n=ye();n.has(r)||n.set(r,[]),n.get(r).push(e),Te(),ke(r,e),Se(r,e),we(r,e)};var Z=Symbol.for("senzor.bullmq.patched");function V(r,e,n){if(!r?.Worker?.prototype)return;let t=r.Worker.prototype,o=t.processJob;typeof o!="function"||o[Z]||(t.processJob=async function(s){let a=s.timestamp?Date.now()-s.timestamp:0,c=(s.attemptsMade||0)+1,i=s.opts?.attempts??1,p=c>=i,d=s.name==="__default__"?s.queueName:`${s.queueName}:${s.name}`;return e.startTask(d,"queue",{queueDelay:a,attempts:c,isDeadLetter:!1,metadata:{jobId:s.id,queueName:s.queueName,maxAttempts:i}},async()=>{try{let u=await o.call(this,s);return e.endTask("success"),u}catch(u){try{let y=m.current();y&&y.contextType==="task"&&p&&(y.data.isDeadLetter=!0)}catch{}throw e.captureError(u,{queueName:s.queueName,jobId:s.id,isDeadLetter:p}),e.endTask("failed"),u}})},Object.defineProperty(t.processJob,Z,{value:!0}),n&&console.log("[Senzor] BullMQ instrumented"))}var X=(r,e)=>{C("bullmq",n=>{V(n,r,e),n?.default&&V(n.default,r,e)})};var Y=Symbol.for("senzor.cron.patched");function Ee(r){return typeof r=="object"&&r!==null?r:r?{timezone:r}:{}}function ee(r,e,n){let t=r.schedule;if(typeof t!="function"||t[Y])return;let o=t,s=function(a,c,i){if(typeof c!="function")return o.call(this,a,c,i);try{let p=Ee(i),d=p?.name??`cron: ${a}`,u=e.wrapTask(d,"cron",{expression:a,metadata:p},c);return o.call(this,a,u,i)}catch(p){return n&&console.error("[Senzor] cron wrap failed",p),o.call(this,a,c,i)}};Object.defineProperty(s,Y,{value:!0,enumerable:!1});try{r.schedule=s}catch{n&&console.warn("[Senzor] unable to patch cron schedule (readonly export)")}n&&console.log("[Senzor] node-cron instrumented")}var te=(r,e)=>{C("node-cron",n=>{n&&(ee(n,r,e),n.default&&ee(n.default,r,e))})};var P={name:"@senzops/apm-node",version:"1.1.17",description:"Universal APM SDK for Senzor",main:"dist/index.js",types:"dist/index.d.ts",scripts:{build:"tsup src/index.ts --format cjs,esm,iife --dts --clean --minify",prepublishOnly:"npm run build"},dependencies:{},devDependencies:{"@types/node":"^20.0.0",tsup:"^8.0.0",typescript:"^5.0.0"},engines:{node:">=18.0.0"},keywords:["apm","monitoring","senzor","node","javascript","api","observability"],author:"Senzops",license:"MIT"};var N={name:P.name,version:P.version};var re=()=>(0,A.randomUUID)().replace(/-/g,""),xe=r=>{let e=new Set;return JSON.stringify(r,(n,t)=>{if(typeof t=="object"&&t!==null){if(e.has(t))return"[Circular]";e.add(t)}return t})},Q=class{constructor(){this.transport=null;this.options=null;this.isInstrumented=!1}init(e){if(!e.apiKey){console.warn("[Senzor] API Key missing. SDK disabled.");return}this.options=e;let n=e.endpoint||"https://api.senzor.dev/api/ingest/apm",t=e.debug||!1;if(this.transport=new x({...e,endpoint:n}),!this.isInstrumented){this.setupGlobalErrorHandlers(),this.setupLogInterception();try{W(n,t)}catch{}try{K(n,t)}catch{}try{B(t)}catch{}try{J()}catch{}try{X(this,t)}catch{}try{te(this,t)}catch{}this.isInstrumented=!0,t&&console.log("[Senzor] Auto-instrumentation enabled")}}setupLogInterception(){if(this.options?.autoLogs===!1)return;let e=["log","info","warn","error","debug"],n={log:console.log,info:console.info,warn:console.warn,error:console.error,debug:console.debug},t=!1;e.forEach(o=>{console[o]=(...s)=>{if(n[o].apply(console,s),!(t||!this.transport)){t=!0;try{let a="",c={};s.forEach(u=>{if(typeof u=="string")a+=(a?" ":"")+u;else if(u instanceof Error)a+=(a?" ":"")+u.message,c.errorStack=u.stack,c.errorName=u.name;else if(typeof u=="object"&&u!==null)try{let y=JSON.parse(xe(u));c={...c,...y}}catch{c.unparseableObject=!0}else a+=(a?" ":"")+String(u)}),!a&&Object.keys(c).length>0&&(a="Object Log");let i=m.current(),p=i?.contextType==="task"?"task":"apm",d={message:a||"Empty log",level:o==="log"?"info":o,attributes:c,timestamp:new Date().toISOString()};i&&(p==="task"?d.runId=i.id:d.traceId=i.id),this.transport.addLog(d,p)}catch{}finally{t=!1}}}})}setupGlobalErrorHandlers(){if(process.__senzorGlobalHandlersInstalled)return;process.__senzorGlobalHandlersInstalled=!0;let e=()=>{try{return{pid:process.pid,ppid:process.ppid,platform:process.platform,uptimeSec:Math.floor(process.uptime()),env:process.env.NODE_ENV||"unknown"}}catch{return{}}},n=()=>{try{let o=process.memoryUsage();return{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}catch{return{}}},t=(o,s={})=>{try{let a;if(o instanceof Error)a=o;else if(typeof o=="string")a=new Error(o);else try{a=new Error(JSON.stringify(o))}catch{a=new Error("Non-serializable rejection reason")}let c={...s,runtime:{name:"node",version:process.version},process:e(),memory:n(),sdk:{name:N.name,version:N.version}};this.captureError(a,c)}catch(a){try{this.options?.debug&&console.error("[Senzor] Error handler failure:",a)}catch{}}};process.on("uncaughtExceptionMonitor",o=>t(o,{type:"uncaughtExceptionMonitor",severity:"fatal"})),process.on("uncaughtException",o=>t(o,{type:"uncaughtException",severity:"fatal"})),process.on("unhandledRejection",o=>t(o,{type:"unhandledRejection",severity:"error"})),process.on("warning",o=>t(o,{type:"processWarning",severity:"warning"})),process.on("multipleResolves",(o,s,a)=>t(a||new Error("Multiple promise resolves"),{type:"multipleResolves",resolveType:o,severity:"warning"})),process.on("rejectionHandled",o=>{if(this.options?.debug)try{console.warn("[Senzor] rejectionHandled event detected")}catch{}}),process.on("SIGTERM",()=>t(new Error("Process received SIGTERM"),{type:"processSignal",signal:"SIGTERM"})),process.on("SIGINT",()=>t(new Error("Process received SIGINT"),{type:"processSignal",signal:"SIGINT"}))}startTrace(e,n){if(!this.transport)return n();let t,o;if(e.headers){let c=d=>{if(e.headers[d])return e.headers[d];if(e.headers[d.toLowerCase()])return e.headers[d.toLowerCase()]},i=c("traceparent"),p=G(i);if(p)t=p.traceId,o=p.parentSpanId;else{let d=c("x-senzor-trace-id"),u=c("x-senzor-parent-span-id");t=Array.isArray(d)?d[0]:d,o=Array.isArray(u)?u[0]:u}}let a={id:t||re(),contextType:"apm",startTime:performance.now(),data:{...e,parentTraceId:t,parentSpanId:o},spans:[]};return m.run(a,n)}endTrace(e,n={}){let t=m.current();if(!t||t.contextType!=="apm"||!this.transport)return;let o=performance.now()-t.startTime,s={traceId:t.id,parentTraceId:t.data.parentTraceId,parentSpanId:t.data.parentSpanId,...t.data,...n,status:e,duration:o,spans:t.spans,timestamp:new Date().toISOString()};this.transport.addTrace(s)}startTask(e,n,t,o){if(!this.transport)return o();let s=m.current(),a=s?.contextType==="apm"?s.id:void 0,c=process.memoryUsage?process.memoryUsage().heapUsed:0,i=process.cpuUsage?process.cpuUsage():void 0,p={id:(0,A.randomUUID)(),contextType:"task",startTime:performance.now(),startMemory:c,startCpu:i,data:{taskName:e,taskType:n,triggerTraceId:a,...t},spans:[]};return m.run(p,o)}endTask(e,n={}){let t=m.current();if(!t||t.contextType!=="task"||!this.transport)return;let o;if(process.memoryUsage&&t.startMemory!==void 0&&process.cpuUsage&&t.startCpu){let a=process.memoryUsage().heapUsed,c=process.cpuUsage(t.startCpu);o={memoryDeltaBytes:a-t.startMemory,cpuUserUs:c.user,cpuSystemUs:c.system}}let s={runId:t.id,taskName:t.data.taskName,taskType:t.data.taskType,triggerTraceId:t.data.triggerTraceId,queueDelay:t.data.queueDelay,attempts:t.data.attempts,isDeadLetter:t.data.isDeadLetter,metadata:{...t.data.metadata,...n},resourceMetrics:o,status:e,duration:performance.now()-t.startTime,spans:t.spans,timestamp:new Date().toISOString()};this.transport.addTask(s)}wrapTask(e,n,t={},o){return(async(...s)=>this.startTask(e,n,t,async()=>{try{let a=await o(...s);return this.endTask("success"),a}catch(a){throw this.captureError(a,{taskName:e}),this.endTask("failed"),a}}))}captureError(e,n={}){if(!this.transport)return;let t;e instanceof Error?t=e:t=new Error(String(e));let o=m.current(),s={errorClass:t.name||"Error",message:t.message,stackTrace:t.stack,context:n,timestamp:new Date().toISOString()};o?.contextType==="task"?this.transport.addError({...s,runId:o.id},"task"):this.transport.addError({...s,traceId:o?.id},"apm")}track(e){this.transport?.addTrace({traceId:re(),...e,spans:[],timestamp:new Date().toISOString()})}startSpan(e,n="custom"){let t=m.current();if(!t)return{end:()=>{}};let o=performance.now()-t.startTime,s=performance.now(),a=(0,A.randomUUID)().replace(/-/g,"").slice(0,16);return{end:(c,i)=>{m.addSpan({spanId:a,name:e,type:n,startTime:o,duration:performance.now()-s,status:i,meta:c})}}}async flush(){this.transport&&await this.transport.flush()}},l=new Q;var ne=()=>(r,e,n)=>{l.startTrace({method:r.method,path:r.originalUrl||r.url,ip:r.ip||r.socket?.remoteAddress,userAgent:r.headers["user-agent"],headers:r.headers},()=>{e.once("finish",()=>{try{let t="UNKNOWN";r.route&&r.route.path?t=(r.baseUrl||"")+r.route.path:e.statusCode===404?t="Not Found":t=r.path||"Wildcard",l.endTrace(e.statusCode,{route:t})}catch{}}),n()})},oe=()=>(r,e,n,t)=>{l.captureError(r),t(r)};var b=r=>!r||r==="/"?"/":r.replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,":uuid").replace(/[0-9a-fA-F]{24}/g,":objectId").replace(/\/(\d+)(?=\/|$)/g,"/:id").split("?")[0],U=(r,e)=>r.route&&r.route.path?(r.baseUrl||"")+r.route.path:r.context&&r.context.matchedRoute?r.context.matchedRoute.path:r.routerPath?r.routerPath:b(e);var se=r=>e=>{let n=e.node.req,t=n.originalUrl||n.url||"/";return l.startTrace({method:n.method||"GET",path:t,ip:n.headers["x-forwarded-for"]||n.socket?.remoteAddress,userAgent:n.headers["user-agent"],headers:n.headers},async()=>{try{let o=await r(e),s=200;return e.node.res.statusCode&&(s=e.node.res.statusCode),o&&o.statusCode&&(s=o.statusCode),l.endTrace(s,{route:U(e,t)}),o}catch(o){l.captureError(o);let s=o.statusCode||o.status||500;throw l.endTrace(s,{route:U(e,t)}),o}})};var ae=r=>async(e,n)=>{let t=e.url?new URL(e.url):{pathname:"/"},o=e.method||"GET",s={},a,c;return typeof e.headers.get=="function"?(a=e.headers.get("user-agent"),c=e.headers.get("x-forwarded-for"),e.headers.forEach((i,p)=>{s[p]=i})):(s=e.headers,a=s["user-agent"],c=s["x-forwarded-for"]),l.startTrace({method:o,path:t.pathname,userAgent:a,ip:c,headers:s},async()=>{try{let i=await r(e,n),p=i?.status||200;return l.endTrace(p,{route:b(t.pathname)}),i}catch(i){throw l.captureError(i),l.endTrace(500,{route:b(t.pathname)}),i}})},ie=r=>async(e,n)=>{let t=e.url?e.url.split("?")[0]:"/";return l.startTrace({method:e.method||"GET",path:t,userAgent:e.headers["user-agent"],ip:e.headers["x-forwarded-for"]||e.socket?.remoteAddress,headers:e.headers},async()=>{let o=()=>{l.endTrace(n.statusCode||200,{route:b(t)})};n.once("finish",o),n.once("close",o);try{return await r(e,n)}catch(s){throw l.captureError(s),s}})};var ce=(r,e,n)=>{e&&e.apiKey&&l.init(e),r.addHook("onRequest",(t,o,s)=>{l.startTrace({method:t.method,path:t.raw.url||t.url,ip:t.ip,userAgent:t.headers["user-agent"],headers:t.headers},()=>s())}),r.addHook("onError",(t,o,s,a)=>{l.captureError(s),a()}),r.addHook("onResponse",(t,o,s)=>{let a=t.routeOptions?.url||t.routerPath||"UNKNOWN";l.endTrace(o.statusCode,{route:a}),s()}),n()};var Ie={init:r=>l.init(r),flush:()=>l.flush(),track:l.track.bind(l),startSpan:l.startSpan.bind(l),captureException:l.captureError.bind(l),wrapTask:l.wrapTask.bind(l),startTask:l.startTask.bind(l),requestHandler:ne,errorHandler:oe,wrapNextRoute:ae,wrapNextPages:ie,wrapH3:se,fastifyPlugin:ce},kt=Ie;})();
|
|
2
2
|
//# sourceMappingURL=index.global.js.map
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/transport.ts","../src/core/context.ts","../src/core/client.ts","../src/instrumentation/http.ts","../src/instrumentation/mongo.ts","../src/instrumentation/pg.ts","../src/instrumentation/hook.ts","../src/instrumentation/bullmq.ts","../src/instrumentation/cron.ts","../package.json","../src/utils/sdkMeta.ts","../src/middleware/express.ts","../src/core/normalizer.ts","../src/wrappers/h3.ts","../src/wrappers/next.ts","../src/wrappers/fastify.ts","../src/index.ts"],"sourcesContent":["import { SenzorOptions, Trace, TaskRun, SenzorError } from './types';\r\n\r\nexport class Transport {\r\n private traceQueue: Trace[] = [];\r\n private apmErrorQueue: SenzorError[] = [];\r\n\r\n private taskQueue: TaskRun[] = [];\r\n private taskErrorQueue: SenzorError[] = [];\r\n\r\n private timer: NodeJS.Timeout | null = null;\r\n private apmEndpoint: string;\r\n private taskEndpoint: string;\r\n\r\n constructor(private config: SenzorOptions) {\r\n const baseEndpoint = config.endpoint || 'https://api.senzor.dev';\r\n // Support legacy full URLs or base URLs\r\n this.apmEndpoint = baseEndpoint.includes('/api/ingest') ? baseEndpoint : `${baseEndpoint}/api/ingest/apm`;\r\n this.taskEndpoint = baseEndpoint.includes('/api/ingest') ? baseEndpoint.replace('/apm', '/task') : `${baseEndpoint}/api/ingest/task`;\r\n\r\n if (typeof setInterval !== 'undefined') {\r\n this.timer = setInterval(() => this.flush(), config.flushInterval || 10000);\r\n if (this.timer && typeof this.timer.unref === 'function') {\r\n this.timer.unref();\r\n }\r\n }\r\n }\r\n\r\n public addTrace(trace: any) {\r\n this.traceQueue.push(trace);\r\n this.checkFlush();\r\n }\r\n\r\n public addTask(task: TaskRun) {\r\n this.taskQueue.push(task);\r\n this.checkFlush();\r\n }\r\n\r\n public addError(error: SenzorError, type: 'apm' | 'task' = 'apm') {\r\n if (type === 'task') this.taskErrorQueue.push(error);\r\n else this.apmErrorQueue.push(error);\r\n this.checkFlush();\r\n }\r\n\r\n private checkFlush() {\r\n const totalApm = this.traceQueue.length + this.apmErrorQueue.length;\r\n const totalTask = this.taskQueue.length + this.taskErrorQueue.length;\r\n if (totalApm >= (this.config.batchSize || 100) || totalTask >= (this.config.batchSize || 100)) {\r\n this.flush();\r\n }\r\n }\r\n\r\n public async flush() {\r\n const apmPayload = { traces: [...this.traceQueue], errors: [...this.apmErrorQueue] };\r\n const taskPayload = { runs: [...this.taskQueue], errors: [...this.taskErrorQueue] };\r\n\r\n this.traceQueue = [];\r\n this.apmErrorQueue = [];\r\n this.taskQueue = [];\r\n this.taskErrorQueue = [];\r\n\r\n const headers = { 'Content-Type': 'application/json', 'x-service-api-key': this.config.apiKey };\r\n\r\n try {\r\n const promises = [];\r\n\r\n if (apmPayload.traces.length > 0 || apmPayload.errors.length > 0) {\r\n promises.push(fetch(this.apmEndpoint, { method: 'POST', headers, body: JSON.stringify(apmPayload), keepalive: true }));\r\n }\r\n\r\n if (taskPayload.runs.length > 0 || taskPayload.errors.length > 0) {\r\n promises.push(fetch(this.taskEndpoint, { method: 'POST', headers, body: JSON.stringify(taskPayload), keepalive: true }));\r\n }\r\n\r\n await Promise.allSettled(promises);\r\n\r\n if (this.config.debug) {\r\n console.log(`[Senzor] Flushed: ${apmPayload.traces.length} traces, ${taskPayload.runs.length} tasks`);\r\n }\r\n } catch (err) {\r\n if (this.config.debug) console.error('[Senzor] Transport Flush Error:', err);\r\n }\r\n }\r\n}","import { AsyncLocalStorage } from 'async_hooks';\r\nimport { ActiveTrace } from './types';\r\n\r\nexport const storage = new AsyncLocalStorage<ActiveTrace>();\r\n\r\nexport const Context = {\r\n run: <T>(trace: ActiveTrace, fn: () => T): T => {\r\n return storage.run(trace, fn);\r\n },\r\n\r\n current: (): ActiveTrace | undefined => {\r\n return storage.getStore();\r\n },\r\n\r\n addSpan: (span: any) => {\r\n const store = storage.getStore();\r\n if (store) {\r\n store.spans.push(span);\r\n }\r\n }\r\n};","import { Transport } from './transport';\r\nimport { Context } from './context';\r\nimport { SenzorOptions, ActiveTrace, TaskRun } from './types';\r\nimport { randomUUID } from 'crypto';\r\nimport { instrumentHttp, instrumentFetch } from '../instrumentation/http';\r\nimport { instrumentMongo } from '../instrumentation/mongo';\r\nimport { instrumentPg } from '../instrumentation/pg';\r\nimport { instrumentBullMQ } from '../instrumentation/bullmq';\r\nimport { instrumentNodeCron } from '../instrumentation/cron';\r\nimport { SDK_META } from '../utils/sdkMeta';\r\n\r\nexport class SenzorClient {\r\n private transport: Transport | null = null;\r\n private options: SenzorOptions | null = null;\r\n private isInstrumented = false;\r\n\r\n public init(options: SenzorOptions) {\r\n if (!options.apiKey) {\r\n console.warn('[Senzor] API Key missing. SDK disabled.');\r\n return;\r\n }\r\n this.options = options;\r\n const endpoint = options.endpoint || 'https://api.senzor.dev/api/ingest/apm';\r\n const debug = options.debug || false;\r\n\r\n this.transport = new Transport({ ...options, endpoint });\r\n\r\n if (!this.isInstrumented) {\r\n this.setupGlobalErrorHandlers();\r\n\r\n try { instrumentHttp(endpoint, debug); } catch (e) { }\r\n try { instrumentFetch(endpoint, debug); } catch (e) { }\r\n try { instrumentMongo(debug); } catch (e) { }\r\n try { instrumentPg(); } catch (e) { }\r\n\r\n // Task Integrations (NEW)\r\n try { instrumentBullMQ(this, debug); } catch (e) { }\r\n try { instrumentNodeCron(this, debug); } catch (e) { }\r\n\r\n this.isInstrumented = true;\r\n if (debug) console.log('[Senzor] Auto-instrumentation & Error Tracking enabled');\r\n }\r\n }\r\n\r\n private setupGlobalErrorHandlers() {\r\n if ((process as any).__senzorGlobalHandlersInstalled) {\r\n return;\r\n }\r\n\r\n (process as any).__senzorGlobalHandlersInstalled = true;\r\n\r\n const getProcessContext = () => {\r\n try {\r\n return {\r\n pid: process.pid,\r\n ppid: process.ppid,\r\n platform: process.platform,\r\n uptimeSec: Math.floor(process.uptime()),\r\n env: process.env.NODE_ENV || 'unknown'\r\n };\r\n } catch {\r\n return {};\r\n }\r\n };\r\n\r\n const getMemoryContext = () => {\r\n try {\r\n const mem = process.memoryUsage();\r\n return {\r\n rss: mem.rss,\r\n heapTotal: mem.heapTotal,\r\n heapUsed: mem.heapUsed,\r\n external: mem.external,\r\n arrayBuffers: mem.arrayBuffers\r\n };\r\n } catch {\r\n return {};\r\n }\r\n };\r\n\r\n const safeCapture = (error: unknown, meta: any = {}) => {\r\n try {\r\n let parsedError: Error;\r\n if (error instanceof Error) {\r\n parsedError = error;\r\n } else if (typeof error === 'string') {\r\n parsedError = new Error(error);\r\n } else {\r\n try {\r\n parsedError = new Error(JSON.stringify(error));\r\n } catch {\r\n parsedError = new Error('Non-serializable rejection reason');\r\n }\r\n }\r\n const enrichedMeta = {\r\n ...meta,\r\n runtime: {\r\n name: 'node',\r\n version: process.version\r\n },\r\n process: getProcessContext(),\r\n memory: getMemoryContext(),\r\n sdk: {\r\n name: SDK_META.name,\r\n version: SDK_META.version\r\n }\r\n };\r\n\r\n this.captureError(parsedError, enrichedMeta);\r\n } catch (internalFailure) {\r\n // NEVER allow SDK to crash host app\r\n try {\r\n if (this.options?.debug) {\r\n console.error('[Senzor] Error handler failure:', internalFailure);\r\n }\r\n } catch { }\r\n }\r\n };\r\n\r\n process.on('uncaughtExceptionMonitor', (error) => {\r\n safeCapture(error, {\r\n type: 'uncaughtExceptionMonitor',\r\n severity: 'fatal'\r\n });\r\n });\r\n\r\n process.on('uncaughtException', (error) => {\r\n safeCapture(error, {\r\n type: 'uncaughtException',\r\n severity: 'fatal'\r\n });\r\n });\r\n\r\n process.on('unhandledRejection', (reason) => {\r\n safeCapture(reason, {\r\n type: 'unhandledRejection',\r\n severity: 'error'\r\n });\r\n });\r\n\r\n process.on('warning', (warning) => {\r\n safeCapture(warning, {\r\n type: 'processWarning',\r\n severity: 'warning'\r\n });\r\n });\r\n\r\n process.on('multipleResolves', (type, promise, reason) => {\r\n safeCapture(reason || new Error('Multiple promise resolves'), {\r\n type: 'multipleResolves',\r\n resolveType: type,\r\n severity: 'warning'\r\n });\r\n });\r\n\r\n process.on('rejectionHandled', (promise) => {\r\n if (this.options?.debug) {\r\n try {\r\n console.warn('[Senzor] rejectionHandled event detected');\r\n } catch { }\r\n }\r\n });\r\n\r\n process.on('SIGTERM', () => {\r\n safeCapture(\r\n new Error('Process received SIGTERM'),\r\n {\r\n type: 'processSignal',\r\n signal: 'SIGTERM'\r\n }\r\n );\r\n });\r\n\r\n process.on('SIGINT', () => {\r\n safeCapture(\r\n new Error('Process received SIGINT'),\r\n {\r\n type: 'processSignal',\r\n signal: 'SIGINT'\r\n }\r\n );\r\n });\r\n }\r\n\r\n public startTrace<T>(data: Partial<ActiveTrace['data']> & { headers?: any }, next: () => T): T {\r\n if (!this.transport) return next();\r\n\r\n let parentTraceId = undefined;\r\n let parentSpanId = undefined;\r\n\r\n if (data.headers) {\r\n const getHeader = (key: string) => {\r\n if (data.headers[key]) return data.headers[key];\r\n if (data.headers[key.toLowerCase()]) return data.headers[key.toLowerCase()];\r\n return undefined;\r\n };\r\n\r\n parentTraceId = getHeader('x-senzor-trace-id');\r\n parentSpanId = getHeader('x-senzor-parent-span-id');\r\n\r\n if (Array.isArray(parentTraceId)) parentTraceId = parentTraceId[0];\r\n if (Array.isArray(parentSpanId)) parentSpanId = parentSpanId[0];\r\n }\r\n\r\n const trace: ActiveTrace = {\r\n id: randomUUID(),\r\n contextType: 'apm', // Ensure we distinguish APM traces from Background Tasks\r\n startTime: performance.now(),\r\n data: {\r\n ...data,\r\n parentTraceId,\r\n parentSpanId\r\n },\r\n spans: []\r\n };\r\n\r\n return Context.run(trace, next);\r\n }\r\n\r\n public endTrace(status: number, extraData: any = {}) {\r\n const trace = Context.current();\r\n if (!trace || trace.contextType !== 'apm' || !this.transport) return;\r\n const duration = performance.now() - trace.startTime;\r\n\r\n const payload = {\r\n traceId: trace.id,\r\n parentTraceId: trace.data.parentTraceId,\r\n parentSpanId: trace.data.parentSpanId,\r\n ...trace.data,\r\n ...extraData,\r\n status, duration, spans: trace.spans, timestamp: new Date().toISOString()\r\n };\r\n this.transport.addTrace(payload);\r\n }\r\n\r\n // --- TASK MONITORING METHODS ---\r\n public startTask<T>(name: string, type: 'cron' | 'queue' | 'pipeline' | 'custom', options: any, next: () => T): T {\r\n if (!this.transport) return next();\r\n\r\n const currentContext = Context.current();\r\n const triggerTraceId = currentContext?.contextType === 'apm' ? currentContext.id : undefined;\r\n\r\n // Snapshot system resources before execution\r\n const startMemory = process.memoryUsage ? process.memoryUsage().heapUsed : 0;\r\n const startCpu = process.cpuUsage ? process.cpuUsage() : undefined;\r\n\r\n const task: ActiveTrace = {\r\n id: randomUUID(),\r\n contextType: 'task',\r\n startTime: performance.now(),\r\n startMemory,\r\n startCpu,\r\n data: { taskName: name, taskType: type, triggerTraceId, ...options },\r\n spans: []\r\n };\r\n return Context.run(task, next);\r\n }\r\n\r\n public endTask(status: 'success' | 'failed', extraMetadata: any = {}) {\r\n const task = Context.current();\r\n if (!task || task.contextType !== 'task' || !this.transport) return;\r\n\r\n // Calculate resource deltas\r\n let resourceMetrics;\r\n if (process.memoryUsage && task.startMemory !== undefined && process.cpuUsage && task.startCpu) {\r\n const endMemory = process.memoryUsage().heapUsed;\r\n const cpuDelta = process.cpuUsage(task.startCpu);\r\n\r\n resourceMetrics = {\r\n memoryDeltaBytes: endMemory - task.startMemory, // Can be negative if GC ran!\r\n cpuUserUs: cpuDelta.user,\r\n cpuSystemUs: cpuDelta.system\r\n };\r\n }\r\n\r\n const payload: TaskRun = {\r\n runId: task.id,\r\n taskName: task.data.taskName,\r\n taskType: task.data.taskType,\r\n triggerTraceId: task.data.triggerTraceId,\r\n queueDelay: task.data.queueDelay,\r\n attempts: task.data.attempts,\r\n isDeadLetter: task.data.isDeadLetter, // Extracted from options/metadata if provided\r\n metadata: { ...task.data.metadata, ...extraMetadata },\r\n resourceMetrics,\r\n status,\r\n duration: performance.now() - task.startTime,\r\n spans: task.spans,\r\n timestamp: new Date().toISOString()\r\n };\r\n\r\n this.transport.addTask(payload);\r\n }\r\n\r\n public wrapTask<T extends (...args: any[]) => any>(name: string, type: 'cron' | 'queue' | 'pipeline' | 'custom', options: any = {}, fn: T): T {\r\n return (async (...args: any[]) => {\r\n return this.startTask(name, type, options, async () => {\r\n try {\r\n const result = await fn(...args);\r\n this.endTask('success');\r\n return result;\r\n } catch (error) {\r\n this.captureError(error, { taskName: name });\r\n this.endTask('failed');\r\n throw error;\r\n }\r\n });\r\n }) as unknown as T;\r\n }\r\n\r\n // --- MODIFIED: Context-Aware Error Capture ---\r\n public captureError(error: unknown, context: any = {}) {\r\n if (!this.transport) return;\r\n\r\n let parsedError: Error;\r\n if (error instanceof Error) {\r\n parsedError = error;\r\n } else {\r\n parsedError = new Error(String(error));\r\n }\r\n\r\n const currentTrace = Context.current();\r\n\r\n const errPayload = {\r\n errorClass: parsedError.name || 'Error',\r\n message: parsedError.message,\r\n stackTrace: parsedError.stack,\r\n context,\r\n timestamp: new Date().toISOString()\r\n };\r\n\r\n if (currentTrace?.contextType === 'task') {\r\n this.transport.addError({ ...errPayload, runId: currentTrace.id }, 'task');\r\n } else {\r\n this.transport.addError({ ...errPayload, traceId: currentTrace?.id }, 'apm');\r\n }\r\n }\r\n\r\n public track(data: any) {\r\n this.transport?.addTrace({ traceId: randomUUID(), ...data, spans: [], timestamp: new Date().toISOString() });\r\n }\r\n\r\n public startSpan(name: string, type: 'db' | 'http' | 'function' | 'custom' = 'custom') {\r\n const trace = Context.current();\r\n if (!trace) return { end: () => { } };\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n const spanId = randomUUID();\r\n return { end: (meta?: any, status?: number) => { Context.addSpan({ spanId, name, type, startTime, duration: performance.now() - spanStartAbs, status, meta }); } };\r\n }\r\n\r\n public async flush() { if (this.transport) await this.transport.flush(); }\r\n}\r\n\r\nexport const client = new SenzorClient();","import http from 'http';\r\nimport https from 'https';\r\nimport { URL } from 'url';\r\nimport { Context } from '../core/context';\r\nimport { randomUUID } from 'crypto';\r\n\r\nconst shimmer = (module: any, methodName: string, wrapper: (original: Function) => Function) => {\r\n if (!module[methodName]) return;\r\n const original = module[methodName];\r\n module[methodName] = wrapper(original);\r\n};\r\n\r\n// --- FETCH INSTRUMENTATION ---\r\nexport const instrumentFetch = (ingestUrl: string, debug = false) => {\r\n if (!globalThis.fetch) return;\r\n\r\n let ingestHost = '';\r\n try { ingestHost = new URL(ingestUrl).hostname; } catch (e) { }\r\n\r\n const originalFetch = globalThis.fetch;\r\n\r\n // @ts-ignore\r\n globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {\r\n let urlStr = '';\r\n if (typeof input === 'string') urlStr = input;\r\n else if (input instanceof URL) urlStr = input.toString();\r\n else if (input && (input as any).url) urlStr = (input as any).url;\r\n\r\n if (ingestHost && urlStr.includes(ingestHost)) {\r\n return originalFetch(input, init);\r\n }\r\n\r\n const trace = Context.current();\r\n if (!trace) {\r\n return originalFetch(input, init);\r\n }\r\n\r\n const method = (init?.method || 'GET').toUpperCase();\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n const spanId = randomUUID();\r\n\r\n let hostname = 'unknown';\r\n try { hostname = new URL(urlStr).hostname; } catch (e) { }\r\n\r\n // Inject Headers\r\n const newInit = { ...init } as RequestInit;\r\n if (!newInit.headers) newInit.headers = {};\r\n\r\n // Helper to set header on various types\r\n const setHeader = (key: string, value: string) => {\r\n if (newInit.headers instanceof Headers) {\r\n newInit.headers.set(key, value);\r\n } else if (Array.isArray(newInit.headers)) {\r\n newInit.headers.push([key, value]);\r\n } else {\r\n (newInit.headers as any)[key] = value;\r\n }\r\n };\r\n\r\n setHeader('x-senzor-trace-id', trace.id);\r\n setHeader('x-senzor-parent-span-id', spanId);\r\n\r\n try {\r\n const response = await originalFetch(input, newInit);\r\n\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({\r\n spanId,\r\n name: `${method} ${hostname}`,\r\n type: 'http',\r\n startTime,\r\n duration,\r\n status: response.status,\r\n meta: { url: urlStr, method, library: 'fetch' }\r\n });\r\n\r\n return response;\r\n } catch (err: any) {\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({\r\n spanId,\r\n name: `${method} ${hostname}`,\r\n type: 'http',\r\n startTime,\r\n duration,\r\n status: 500,\r\n meta: { error: err.message, url: urlStr, library: 'fetch' }\r\n });\r\n throw err;\r\n }\r\n };\r\n};\r\n\r\n// --- HTTP/HTTPS INSTRUMENTATION ---\r\nexport const instrumentHttp = (ingestUrl: string, debug = false) => {\r\n let ingestHost = '';\r\n try { ingestHost = new URL(ingestUrl).hostname; } catch (e) { }\r\n\r\n const requestWrapper = (original: Function) => {\r\n return function (this: any, ...args: any[]) {\r\n let options: any = {};\r\n let urlStr = '';\r\n let optionsIndex = 0;\r\n\r\n // Parsing Logic: http.request(url, options, cb) OR http.request(options, cb)\r\n if (typeof args[0] === 'string' || args[0] instanceof URL) {\r\n urlStr = args[0].toString();\r\n optionsIndex = 1;\r\n } else {\r\n optionsIndex = 0;\r\n }\r\n\r\n // Ensure options object exists at correct index\r\n if (!args[optionsIndex] || typeof args[optionsIndex] !== 'object') {\r\n args[optionsIndex] = {};\r\n }\r\n options = args[optionsIndex];\r\n\r\n // Construct URL if missing\r\n if (!urlStr) {\r\n const protocol = options.protocol || (options.port === 443 ? 'https:' : 'http:');\r\n const host = options.hostname || options.host || 'localhost';\r\n const path = options.path || '/';\r\n urlStr = `${protocol}//${host}${path}`;\r\n }\r\n\r\n // Guard\r\n if (ingestHost && (urlStr.includes(ingestHost) || (options.hostname && options.hostname.includes(ingestHost)))) {\r\n return original.apply(this, args);\r\n }\r\n\r\n const trace = Context.current();\r\n if (!trace) return original.apply(this, args);\r\n\r\n const method = (options.method || 'GET').toUpperCase();\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n const spanId = randomUUID();\r\n\r\n let hostname = 'unknown';\r\n try { hostname = new URL(urlStr).hostname; } catch (e) { hostname = options.hostname || 'unknown'; }\r\n\r\n // Inject Headers (Mutate the options object reference directly)\r\n if (!options.headers) options.headers = {};\r\n options.headers['x-senzor-trace-id'] = trace.id;\r\n options.headers['x-senzor-parent-span-id'] = spanId;\r\n\r\n // Debug\r\n if (debug) console.log(`[Senzor] Injecting headers to ${urlStr}`);\r\n\r\n // Call Original\r\n const req = original.apply(this, args);\r\n\r\n const captureSpan = (res: any, error?: Error) => {\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({\r\n spanId,\r\n name: `${method} ${hostname}`,\r\n type: 'http',\r\n startTime,\r\n duration,\r\n status: error ? 500 : res?.statusCode || 0,\r\n meta: { url: urlStr, method, library: 'http' }\r\n });\r\n };\r\n\r\n req.on('response', (res: any) => {\r\n res.once('end', () => captureSpan(res));\r\n res.once('close', () => captureSpan(res));\r\n res.once('error', (err: Error) => captureSpan(res, err));\r\n });\r\n\r\n req.on('error', (err: Error) => captureSpan(null, err));\r\n\r\n return req;\r\n };\r\n };\r\n\r\n shimmer(http, 'request', requestWrapper);\r\n shimmer(http, 'get', requestWrapper);\r\n shimmer(https, 'request', requestWrapper);\r\n shimmer(https, 'get', requestWrapper);\r\n};","import { Context } from '../core/context';\r\n\r\nexport const instrumentMongo = (debug = false) => {\r\n try {\r\n const mongodb = require('mongodb');\r\n const Collection = mongodb.Collection;\r\n\r\n // Attempt to get Cursor classes\r\n // Note: The location of these classes varies by driver version, \r\n // checking common locations\r\n const FindCursor = mongodb.FindCursor || require('mongodb/lib/cursor/find_cursor').FindCursor;\r\n const AggregationCursor = mongodb.AggregationCursor || require('mongodb/lib/cursor/aggregation_cursor').AggregationCursor;\r\n\r\n if (debug) console.log('[Senzor] Instrumenting MongoDB (Collection + Cursors)...');\r\n\r\n // --- Helper to Record Span ---\r\n const recordSpan = (name: string, operation: string, collection: string, startAbs: number, traceStart: number, err?: Error) => {\r\n const duration = performance.now() - startAbs;\r\n Context.addSpan({\r\n name: `MongoDB ${name}`,\r\n type: 'db',\r\n startTime: performance.now() - traceStart - duration, // Adjust start time to when op actually started\r\n duration,\r\n status: err ? 500 : 0,\r\n meta: { collection, operation, error: err ? err.message : undefined }\r\n });\r\n if (debug) console.log(`[Senzor] Captured Mongo: ${name} (${duration.toFixed(2)}ms)`);\r\n };\r\n\r\n // --- 1. Instrument Immediate Operations (Insert/Update/Delete) ---\r\n const immediateMethods = ['insertOne', 'insertMany', 'updateOne', 'updateMany', 'deleteOne', 'deleteMany', 'countDocuments'];\r\n\r\n immediateMethods.forEach((method) => {\r\n if (!Collection.prototype[method]) return;\r\n const original = Collection.prototype[method];\r\n\r\n Collection.prototype[method] = function (...args: any[]) {\r\n const trace = Context.current();\r\n if (!trace) return original.apply(this, args);\r\n\r\n const spanStartAbs = performance.now();\r\n const traceStart = trace.startTime;\r\n const collName = this.collectionName;\r\n\r\n try {\r\n const result = original.apply(this, args);\r\n if (result && typeof result.then === 'function') {\r\n return result.then(\r\n (res: any) => { recordSpan(method, method, collName, spanStartAbs, traceStart); return res; },\r\n (err: any) => { recordSpan(method, method, collName, spanStartAbs, traceStart, err); throw err; }\r\n );\r\n }\r\n return result;\r\n } catch (err: any) {\r\n recordSpan(method, method, collName, spanStartAbs, traceStart, err);\r\n throw err;\r\n }\r\n };\r\n });\r\n\r\n // --- 2. Instrument Cursor Execution (find -> toArray) ---\r\n const patchCursor = (CursorClass: any, label: string) => {\r\n if (!CursorClass || !CursorClass.prototype.toArray) return;\r\n\r\n const originalToArray = CursorClass.prototype.toArray;\r\n\r\n CursorClass.prototype.toArray = function (...args: any[]) {\r\n const trace = Context.current();\r\n // Cursors are often created in context but executed later. \r\n // We check context at execution time.\r\n if (!trace) return originalToArray.apply(this, args);\r\n\r\n const spanStartAbs = performance.now();\r\n const traceStart = trace.startTime;\r\n // Attempt to get collection name from cursor internal state\r\n const collName = this.namespace?.collection || 'unknown';\r\n\r\n const onSuccess = (res: any) => {\r\n recordSpan(label, label, collName, spanStartAbs, traceStart);\r\n return res;\r\n };\r\n const onError = (err: any) => {\r\n recordSpan(label, label, collName, spanStartAbs, traceStart, err);\r\n throw err;\r\n };\r\n\r\n try {\r\n const result = originalToArray.apply(this, args);\r\n if (result && typeof result.then === 'function') {\r\n return result.then(onSuccess, onError);\r\n }\r\n return onSuccess(result);\r\n } catch (e) {\r\n onError(e);\r\n }\r\n };\r\n };\r\n\r\n patchCursor(FindCursor, 'find');\r\n patchCursor(AggregationCursor, 'aggregate');\r\n\r\n } catch (e: any) {\r\n if (debug) console.warn('[Senzor] MongoDB instrumentation warning:', e.message);\r\n }\r\n};","import { Context } from '../core/context';\r\n\r\n// Simple shim for 'pg' library\r\nexport const instrumentPg = () => {\r\n try {\r\n // Try to require pg (it might not be installed by user)\r\n const pg = require('pg');\r\n const originalQuery = pg.Client.prototype.query;\r\n\r\n pg.Client.prototype.query = function (...args: any[]) {\r\n const trace = Context.current();\r\n if (!trace) return originalQuery.apply(this, args);\r\n\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n\r\n // Extract SQL (first arg usually string or config object)\r\n const sql = typeof args[0] === 'string' ? args[0] : args[0].text;\r\n\r\n // Wrap callback if present, or handle Promise\r\n const result = originalQuery.apply(this, args);\r\n\r\n if (result && typeof result.then === 'function') {\r\n return result.then((res: any) => {\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({\r\n name: 'Postgres Query',\r\n type: 'db',\r\n startTime,\r\n duration,\r\n meta: { query: sql }\r\n });\r\n return res;\r\n });\r\n }\r\n return result;\r\n };\r\n } catch (e) {\r\n // User doesn't use pg, ignore\r\n }\r\n};","import Module from 'module';\r\n\r\nconst SENZOR_PATCHED =\r\n Symbol.for('senzor.require.patched');\r\n\r\nconst SENZOR_HOOKS =\r\n Symbol.for('senzor.require.hooks');\r\n\r\ntype HookFn =\r\n (exports: unknown) => void;\r\n\r\ntype HookMap =\r\n Map<string, HookFn[]>;\r\n\r\nfunction getHookRegistry(): HookMap {\r\n\r\n const mod =\r\n Module as unknown as Record<\r\n symbol,\r\n HookMap\r\n >;\r\n\r\n if (!mod[SENZOR_HOOKS]) {\r\n\r\n Object.defineProperty(\r\n mod,\r\n SENZOR_HOOKS,\r\n {\r\n value: new Map(),\r\n enumerable: false\r\n }\r\n );\r\n\r\n }\r\n\r\n return mod[SENZOR_HOOKS];\r\n\r\n}\r\n\r\nfunction runHooks(\r\n moduleName: string,\r\n exports: unknown\r\n) {\r\n\r\n const registry =\r\n (Module as unknown as Record<\r\n symbol,\r\n HookMap\r\n >)[SENZOR_HOOKS];\r\n\r\n if (!registry) return;\r\n\r\n const hooks =\r\n registry.get(moduleName);\r\n\r\n if (!hooks?.length) return;\r\n\r\n for (const hook of hooks) {\r\n\r\n try {\r\n hook(exports);\r\n }\r\n catch (err) {\r\n\r\n console.error(\r\n `[Senzor] instrumentation failed for ${moduleName}`,\r\n err\r\n );\r\n\r\n }\r\n\r\n }\r\n\r\n}\r\n\r\nfunction patchLoaderOnce() {\r\n\r\n const mod =\r\n Module as unknown as any;\r\n\r\n if (mod[SENZOR_PATCHED]) {\r\n return;\r\n }\r\n\r\n const previousLoad =\r\n mod._load;\r\n\r\n mod._load =\r\n function patchedLoad(\r\n request: string,\r\n parent: unknown,\r\n isMain: boolean\r\n ) {\r\n\r\n const exports =\r\n previousLoad.apply(\r\n this,\r\n arguments\r\n );\r\n\r\n runHooks(\r\n request,\r\n exports\r\n );\r\n\r\n return exports;\r\n\r\n };\r\n\r\n Object.defineProperty(\r\n mod,\r\n SENZOR_PATCHED,\r\n {\r\n value: true,\r\n enumerable: false\r\n }\r\n );\r\n\r\n}\r\n\r\nfunction patchCached(\r\n moduleName: string,\r\n hook: HookFn\r\n) {\r\n\r\n try {\r\n\r\n const resolved =\r\n require.resolve(\r\n moduleName\r\n );\r\n\r\n const cached =\r\n require.cache?.[\r\n resolved\r\n ];\r\n\r\n if (cached?.exports) {\r\n\r\n hook(\r\n cached.exports\r\n );\r\n\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n}\r\n\r\nfunction tryRequire(\r\n moduleName: string,\r\n hook: HookFn\r\n) {\r\n\r\n try {\r\n\r\n const mod =\r\n require(moduleName);\r\n\r\n if (mod) {\r\n hook(mod);\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n}\r\n\r\nfunction retryPatch(\r\n moduleName: string,\r\n hook: HookFn\r\n) {\r\n\r\n let attempts = 0;\r\n\r\n const max = 5;\r\n\r\n const timer =\r\n setInterval(() => {\r\n\r\n attempts++;\r\n\r\n try {\r\n\r\n const mod =\r\n require(moduleName);\r\n\r\n if (mod) {\r\n\r\n hook(mod);\r\n\r\n clearInterval(timer);\r\n\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n if (attempts >= max) {\r\n clearInterval(timer);\r\n }\r\n\r\n }, 200);\r\n\r\n}\r\n\r\nexport const hookRequire =\r\n (\r\n moduleName: string,\r\n onRequire: HookFn\r\n ) => {\r\n\r\n const registry =\r\n getHookRegistry();\r\n\r\n if (!registry.has(moduleName)) {\r\n\r\n registry.set(\r\n moduleName,\r\n []\r\n );\r\n\r\n }\r\n\r\n registry\r\n .get(moduleName)!\r\n .push(onRequire);\r\n\r\n patchLoaderOnce();\r\n\r\n patchCached(\r\n moduleName,\r\n onRequire\r\n );\r\n\r\n tryRequire(\r\n moduleName,\r\n onRequire\r\n );\r\n\r\n retryPatch(\r\n moduleName,\r\n onRequire\r\n );\r\n\r\n };","import type { SenzorClient } from '../core/client';\r\nimport { hookRequire } from './hook';\r\nimport { Context } from '../core/context';\r\n\r\nconst PATCHED =\r\n Symbol.for(\r\n 'senzor.bullmq.patched'\r\n );\r\n\r\nfunction patchWorker(\r\n target: any,\r\n client: SenzorClient,\r\n debug: boolean\r\n) {\r\n\r\n if (\r\n !target?.Worker?.prototype\r\n ) {\r\n return;\r\n }\r\n\r\n const proto =\r\n target.Worker.prototype;\r\n\r\n const original =\r\n proto.processJob;\r\n\r\n if (\r\n typeof original !==\r\n 'function' ||\r\n original[PATCHED]\r\n ) {\r\n return;\r\n }\r\n\r\n proto.processJob =\r\n async function (\r\n job: any\r\n ) {\r\n\r\n const queueDelay =\r\n job.timestamp\r\n ? Date.now() -\r\n job.timestamp\r\n : 0;\r\n\r\n const currentAttempt =\r\n (job.attemptsMade || 0)\r\n + 1;\r\n\r\n const maxAttempts =\r\n job.opts?.attempts\r\n ?? 1;\r\n\r\n const isFinal =\r\n currentAttempt >=\r\n maxAttempts;\r\n\r\n const taskName =\r\n job.name ===\r\n '__default__'\r\n ? job.queueName\r\n : `${job.queueName}:${job.name}`;\r\n\r\n return client.startTask(\r\n\r\n taskName,\r\n\r\n 'queue',\r\n\r\n {\r\n queueDelay,\r\n attempts:\r\n currentAttempt,\r\n isDeadLetter: false,\r\n metadata: {\r\n jobId: job.id,\r\n queueName:\r\n job.queueName,\r\n maxAttempts\r\n }\r\n },\r\n\r\n async () => {\r\n\r\n try {\r\n\r\n const result =\r\n await original.call(\r\n this,\r\n job\r\n );\r\n\r\n client.endTask(\r\n 'success'\r\n );\r\n\r\n return result;\r\n\r\n }\r\n catch (error) {\r\n\r\n try {\r\n\r\n const ctx =\r\n Context.current();\r\n\r\n if (\r\n ctx &&\r\n ctx.contextType === 'task' &&\r\n isFinal\r\n ) {\r\n\r\n ctx.data\r\n .isDeadLetter =\r\n true;\r\n\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n client.captureError(\r\n error,\r\n {\r\n queueName:\r\n job.queueName,\r\n jobId: job.id,\r\n isDeadLetter:\r\n isFinal\r\n }\r\n );\r\n\r\n client.endTask(\r\n 'failed'\r\n );\r\n\r\n throw error;\r\n\r\n }\r\n\r\n }\r\n\r\n );\r\n\r\n };\r\n\r\n Object.defineProperty(\r\n proto.processJob,\r\n PATCHED,\r\n {\r\n value: true\r\n }\r\n );\r\n\r\n if (debug) {\r\n\r\n console.log(\r\n '[Senzor] BullMQ instrumented'\r\n );\r\n\r\n }\r\n\r\n}\r\n\r\nexport const instrumentBullMQ =\r\n (\r\n client: SenzorClient,\r\n debug: boolean\r\n ) => {\r\n\r\n hookRequire(\r\n 'bullmq',\r\n (exports: any) => {\r\n\r\n patchWorker(\r\n exports,\r\n client,\r\n debug\r\n );\r\n\r\n if (exports?.default) {\r\n\r\n patchWorker(\r\n exports.default,\r\n client,\r\n debug\r\n );\r\n\r\n }\r\n\r\n }\r\n );\r\n\r\n };","import type { SenzorClient } from '../core/client';\r\nimport { hookRequire } from './hook';\r\n\r\nconst PATCHED =\r\n Symbol.for('senzor.cron.patched');\r\n\r\ntype CronHandler =\r\n (...args: unknown[]) => unknown;\r\n\r\ntype CronSchedule =\r\n (\r\n expression: string,\r\n handler: CronHandler,\r\n options?: unknown\r\n ) => unknown;\r\n\r\nfunction normalizeOptions(\r\n options: unknown\r\n): Record<string, unknown> {\r\n\r\n if (\r\n typeof options === 'object' &&\r\n options !== null\r\n ) {\r\n return options as Record<\r\n string,\r\n unknown\r\n >;\r\n }\r\n\r\n // backward compatibility with:\r\n // cron.schedule(expr, fn, \"UTC\")\r\n if (options) {\r\n return { timezone: options };\r\n }\r\n\r\n return {};\r\n\r\n}\r\n\r\nfunction patchTarget(\r\n target: Record<string, unknown>,\r\n client: SenzorClient,\r\n debug: boolean\r\n): void {\r\n\r\n const schedule =\r\n target.schedule as\r\n CronSchedule | undefined;\r\n\r\n if (\r\n typeof schedule !== 'function' ||\r\n (schedule as any)[PATCHED]\r\n ) {\r\n return;\r\n }\r\n\r\n const original =\r\n schedule;\r\n\r\n const wrapped: CronSchedule =\r\n function (\r\n this: unknown,\r\n expression,\r\n handler,\r\n options\r\n ) {\r\n\r\n if (\r\n typeof handler !==\r\n 'function'\r\n ) {\r\n\r\n return original.call(\r\n this,\r\n expression,\r\n handler,\r\n options\r\n );\r\n\r\n }\r\n\r\n try {\r\n\r\n const opts =\r\n normalizeOptions(\r\n options\r\n );\r\n\r\n const taskName =\r\n (opts as any)?.name ??\r\n `cron: ${expression}`;\r\n\r\n const wrappedHandler =\r\n client.wrapTask(\r\n taskName,\r\n 'cron',\r\n {\r\n expression,\r\n metadata: opts\r\n },\r\n handler\r\n );\r\n\r\n return original.call(\r\n this,\r\n expression,\r\n wrappedHandler,\r\n options\r\n );\r\n\r\n }\r\n catch (err) {\r\n\r\n if (debug) {\r\n\r\n console.error(\r\n '[Senzor] cron wrap failed',\r\n err\r\n );\r\n\r\n }\r\n\r\n return original.call(\r\n this,\r\n expression,\r\n handler,\r\n options\r\n );\r\n\r\n }\r\n\r\n };\r\n\r\n Object.defineProperty(\r\n wrapped,\r\n PATCHED,\r\n {\r\n value: true,\r\n enumerable: false\r\n }\r\n );\r\n\r\n // Some ESM namespace exports are frozen\r\n try {\r\n\r\n target.schedule =\r\n wrapped;\r\n\r\n }\r\n catch {\r\n\r\n if (debug) {\r\n\r\n console.warn(\r\n '[Senzor] unable to patch cron schedule (readonly export)'\r\n );\r\n\r\n }\r\n\r\n }\r\n\r\n if (debug) {\r\n\r\n console.log(\r\n '[Senzor] node-cron instrumented'\r\n );\r\n\r\n }\r\n\r\n}\r\n\r\nexport const instrumentNodeCron =\r\n (\r\n client: SenzorClient,\r\n debug: boolean\r\n ): void => {\r\n\r\n hookRequire(\r\n 'node-cron',\r\n (exports: any) => {\r\n\r\n if (!exports) return;\r\n\r\n patchTarget(\r\n exports,\r\n client,\r\n debug\r\n );\r\n\r\n if (exports.default) {\r\n\r\n patchTarget(\r\n exports.default,\r\n client,\r\n debug\r\n );\r\n\r\n }\r\n\r\n }\r\n );\r\n\r\n };","{\r\n \"name\": \"@senzops/apm-node\",\r\n \"version\": \"1.1.15\",\r\n \"description\": \"Universal APM SDK for Senzor\",\r\n \"main\": \"dist/index.js\",\r\n \"types\": \"dist/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"tsup src/index.ts --format cjs,esm,iife --dts --clean --minify\",\r\n \"prepublishOnly\": \"npm run build\"\r\n },\r\n \"dependencies\": {},\r\n \"devDependencies\": {\r\n \"@types/node\": \"^20.0.0\",\r\n \"tsup\": \"^8.0.0\",\r\n \"typescript\": \"^5.0.0\"\r\n },\r\n \"engines\": {\r\n \"node\": \">=18.0.0\"\r\n },\r\n \"keywords\": [\r\n \"apm\",\r\n \"monitoring\",\r\n \"senzor\",\r\n \"node\",\r\n \"javascript\",\r\n \"api\",\r\n \"observability\"\r\n ],\r\n \"author\": \"Senzops\",\r\n \"license\": \"MIT\"\r\n}\r\n","import pkg from '../../package.json';\r\n\r\nexport const SDK_META = {\r\n name: pkg.name,\r\n version: pkg.version\r\n};","import { client } from '../core/client';\r\n\r\n// 1. Request Handler (Place before routes)\r\nexport const expressMiddleware = () => {\r\n return (req: any, res: any, next: () => void) => {\r\n client.startTrace({\r\n method: req.method,\r\n path: req.originalUrl || req.url,\r\n ip: req.ip || req.socket?.remoteAddress,\r\n userAgent: req.headers['user-agent'],\r\n headers: req.headers\r\n }, () => {\r\n\r\n // Auto-detect status code on finish\r\n res.once('finish', () => {\r\n try {\r\n let route = 'UNKNOWN';\r\n // Express populates req.route only if a route matched\r\n if (req.route && req.route.path) {\r\n route = (req.baseUrl || '') + req.route.path;\r\n } else if (res.statusCode === 404) {\r\n route = 'Not Found';\r\n } else {\r\n route = req.path || 'Wildcard';\r\n }\r\n\r\n client.endTrace(res.statusCode, { route });\r\n } catch (e) { /* Fail open */ }\r\n });\r\n\r\n next();\r\n });\r\n };\r\n};\r\n\r\n// 2. Error Handler (Place after routes)\r\n// This is required in Express to capture the actual Error Object (Stack Trace)\r\nexport const expressErrorHandler = () => {\r\n return (err: any, req: any, res: any, next: (err?: any) => void) => {\r\n\r\n // 1. Capture the exception context\r\n client.captureError(err);\r\n\r\n // 2. Pass it to the next error handler (don't swallow it)\r\n next(err);\r\n };\r\n};","/**\r\n * Heuristic URL Normalizer\r\n * Converts raw paths with IDs into generic patterns to prevent high cardinality.\r\n * Example: /users/123/orders/abc-def -> /users/:id/orders/:uuid\r\n */\r\nexport const normalizePath = (path: string): string => {\r\n if (!path || path === '/') return '/';\r\n\r\n return path\r\n // Replace UUIDs (long alphanumeric strings)\r\n .replace(\r\n /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,\r\n ':uuid'\r\n )\r\n // Replace MongoDB ObjectIds (24 hex chars)\r\n .replace(/[0-9a-fA-F]{24}/g, ':objectId')\r\n // Replace pure numeric IDs (e.g., /123)\r\n .replace(/\\/(\\d+)(?=\\/|$)/g, '/:id')\r\n // Remove query strings\r\n .split('?')[0];\r\n};\r\n\r\n/**\r\n * Tries to extract route from Framework internals, falls back to heuristic\r\n */\r\nexport const getRoute = (req: any, fallbackPath: string): string => {\r\n // Express / Connect\r\n if (req.route && req.route.path) {\r\n return (req.baseUrl || '') + req.route.path;\r\n }\r\n\r\n // H3 / Nitro (Nuxt)\r\n if (req.context && req.context.matchedRoute) {\r\n return req.context.matchedRoute.path;\r\n }\r\n\r\n // Fastify\r\n if (req.routerPath) {\r\n return req.routerPath;\r\n }\r\n\r\n // Fallback: Heuristic Normalization\r\n return normalizePath(fallbackPath);\r\n};","import { client } from '../core/client';\r\nimport { getRoute } from '../core/normalizer';\r\n\r\ntype EventHandler = (event: any) => any;\r\n\r\nexport const wrapH3 = (handler: EventHandler) => {\r\n return (event: any) => {\r\n const req = event.node.req;\r\n const path = req.originalUrl || req.url || '/';\r\n\r\n return client.startTrace({\r\n method: req.method || 'GET',\r\n path: path,\r\n ip: req.headers['x-forwarded-for'] || req.socket?.remoteAddress,\r\n userAgent: req.headers['user-agent'],\r\n headers: req.headers // Pass headers\r\n }, async () => {\r\n try {\r\n const response = await handler(event);\r\n let status = 200;\r\n if (event.node.res.statusCode) status = event.node.res.statusCode;\r\n if (response && response.statusCode) status = response.statusCode;\r\n\r\n client.endTrace(status, { route: getRoute(event, path) });\r\n return response;\r\n } catch (err: any) {\r\n client.captureError(err);\r\n const status = err.statusCode || err.status || 500;\r\n client.endTrace(status, { route: getRoute(event, path) });\r\n throw err;\r\n }\r\n });\r\n };\r\n};","import { client } from '../core/client';\r\nimport { normalizePath } from '../core/normalizer';\r\n\r\n// --- App Router Wrapper ---\r\nexport const wrapNextRoute = (handler: Function) => {\r\n return async (req: Request | any, context?: any) => {\r\n\r\n // Extract info from Web Standard Request\r\n const url = req.url ? new URL(req.url) : { pathname: '/' };\r\n const method = req.method || 'GET';\r\n\r\n // Header Extraction\r\n let headers: Record<string, string> = {};\r\n let ua: string | undefined;\r\n let ip: string | undefined;\r\n\r\n if (typeof req.headers.get === 'function') {\r\n // It's a Web Request Object\r\n ua = req.headers.get('user-agent');\r\n ip = req.headers.get('x-forwarded-for');\r\n\r\n // Convert to plain object for trace context extraction\r\n req.headers.forEach((value: string, key: string) => {\r\n headers[key] = value;\r\n });\r\n } else {\r\n // It's a Node Request Object (rare in App router but possible)\r\n headers = req.headers;\r\n ua = headers['user-agent'];\r\n ip = headers['x-forwarded-for'] as string;\r\n }\r\n\r\n return client.startTrace({\r\n method,\r\n path: url.pathname,\r\n userAgent: ua,\r\n ip: ip,\r\n headers: headers // Pass extracted headers\r\n }, async () => {\r\n try {\r\n const response = await handler(req, context);\r\n const status = response?.status || 200;\r\n\r\n client.endTrace(status, { route: normalizePath(url.pathname) });\r\n return response;\r\n } catch (err: any) {\r\n client.captureError(err);\r\n client.endTrace(500, { route: normalizePath(url.pathname) });\r\n throw err;\r\n }\r\n });\r\n };\r\n};\r\n\r\n// --- Pages Router Wrapper ---\r\nexport const wrapNextPages = (handler: Function) => {\r\n return async (req: any, res: any) => {\r\n const path = req.url ? req.url.split('?')[0] : '/';\r\n\r\n return client.startTrace({\r\n method: req.method || 'GET',\r\n path: path,\r\n userAgent: req.headers['user-agent'],\r\n ip: req.headers['x-forwarded-for'] || req.socket?.remoteAddress,\r\n headers: req.headers // Standard Node headers work fine\r\n }, async () => {\r\n\r\n const done = () => {\r\n client.endTrace(res.statusCode || 200, { route: normalizePath(path) });\r\n };\r\n\r\n res.once('finish', done);\r\n res.once('close', done);\r\n\r\n try {\r\n return await handler(req, res);\r\n } catch (e: any) {\r\n client.captureError(e);\r\n throw e;\r\n }\r\n });\r\n };\r\n};","import { client } from '../core/client';\r\nimport { SenzorOptions } from '../core/types';\r\n\r\nexport const senzorPlugin = (fastify: any, options: SenzorOptions, done: Function) => {\r\n if (options && options.apiKey) {\r\n client.init(options);\r\n }\r\n\r\n fastify.addHook('onRequest', (request: any, reply: any, next: Function) => {\r\n client.startTrace({\r\n method: request.method,\r\n path: request.raw.url || request.url,\r\n ip: request.ip,\r\n userAgent: request.headers['user-agent'],\r\n headers: request.headers // Pass headers\r\n }, () => next());\r\n });\r\n\r\n fastify.addHook('onError', (request: any, reply: any, error: any, next: Function) => {\r\n client.captureError(error);\r\n next();\r\n });\r\n\r\n fastify.addHook('onResponse', (request: any, reply: any, next: Function) => {\r\n const route = request.routeOptions?.url || request.routerPath || 'UNKNOWN';\r\n client.endTrace(reply.statusCode, { route });\r\n next();\r\n });\r\n\r\n done();\r\n};","import { client } from './core/client';\r\nimport { expressMiddleware, expressErrorHandler } from './middleware/express';\r\nimport { wrapH3 } from './wrappers/h3';\r\nimport { wrapNextRoute, wrapNextPages } from './wrappers/next';\r\nimport { senzorPlugin } from './wrappers/fastify';\r\nimport { SenzorOptions } from './core/types';\r\n\r\nconst Senzor = {\r\n init: (options: SenzorOptions) => client.init(options),\r\n flush: () => client.flush(),\r\n track: client.track.bind(client),\r\n startSpan: client.startSpan.bind(client),\r\n captureException: client.captureError.bind(client),\r\n\r\n // Task Monitoring (NEW)\r\n wrapTask: client.wrapTask.bind(client),\r\n startTask: client.startTask.bind(client),\r\n\r\n // Express\r\n requestHandler: expressMiddleware,\r\n errorHandler: expressErrorHandler,\r\n\r\n // Next\r\n wrapNextRoute,\r\n wrapNextPages,\r\n\r\n // H3\r\n wrapH3,\r\n\r\n // Fastify\r\n fastifyPlugin: senzorPlugin\r\n};\r\n\r\nexport default Senzor;\r\nexport { Senzor };"],"mappings":"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","names":["Transport","config","baseEndpoint","trace","task","error","type","totalApm","totalTask","apmPayload","taskPayload","headers","promises","err","import_async_hooks","storage","Context","trace","fn","span","store","import_crypto","import_http","import_https","import_url","import_crypto","shimmer","module","methodName","wrapper","original","instrumentFetch","ingestUrl","debug","ingestHost","originalFetch","input","init","urlStr","trace","Context","method","startTime","spanStartAbs","spanId","hostname","newInit","setHeader","key","value","response","duration","err","instrumentHttp","requestWrapper","args","options","optionsIndex","protocol","host","path","req","captureSpan","res","error","http","https","instrumentMongo","debug","mongodb","Collection","FindCursor","AggregationCursor","recordSpan","name","operation","collection","startAbs","traceStart","err","duration","Context","method","original","args","trace","spanStartAbs","collName","result","res","patchCursor","CursorClass","label","originalToArray","onSuccess","onError","e","instrumentPg","pg","originalQuery","args","trace","Context","startTime","spanStartAbs","sql","result","res","duration","import_module","SENZOR_PATCHED","SENZOR_HOOKS","getHookRegistry","mod","Module","runHooks","moduleName","exports","registry","hooks","hook","err","patchLoaderOnce","previousLoad","request","parent","isMain","patchCached","resolved","__require","cached","tryRequire","retryPatch","attempts","max","timer","hookRequire","onRequire","PATCHED","patchWorker","target","client","debug","proto","original","job","queueDelay","currentAttempt","maxAttempts","isFinal","taskName","result","error","ctx","Context","instrumentBullMQ","hookRequire","exports","PATCHED","normalizeOptions","options","patchTarget","target","client","debug","schedule","original","wrapped","expression","handler","opts","taskName","wrappedHandler","err","instrumentNodeCron","hookRequire","exports","package_default","SDK_META","package_default","SenzorClient","options","endpoint","debug","Transport","instrumentHttp","instrumentFetch","instrumentMongo","instrumentPg","instrumentBullMQ","instrumentNodeCron","getProcessContext","getMemoryContext","mem","safeCapture","error","meta","parsedError","enrichedMeta","SDK_META","internalFailure","reason","warning","type","promise","data","next","parentTraceId","parentSpanId","getHeader","key","trace","Context","status","extraData","duration","payload","name","currentContext","triggerTraceId","startMemory","startCpu","task","extraMetadata","resourceMetrics","endMemory","cpuDelta","fn","args","result","context","currentTrace","errPayload","startTime","spanStartAbs","spanId","client","expressMiddleware","req","res","next","client","route","expressErrorHandler","err","normalizePath","path","getRoute","req","fallbackPath","wrapH3","handler","event","req","path","client","response","status","getRoute","err","wrapNextRoute","handler","req","context","url","method","headers","ua","ip","value","key","client","response","status","normalizePath","err","wrapNextPages","res","path","done","e","senzorPlugin","fastify","options","done","client","request","reply","next","error","route","Senzor","options","client","expressMiddleware","expressErrorHandler","wrapNextRoute","wrapNextPages","wrapH3","senzorPlugin","index_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/transport.ts","../src/core/context.ts","../src/core/client.ts","../src/instrumentation/http.ts","../src/utils/traceContext.ts","../src/instrumentation/mongo.ts","../src/instrumentation/pg.ts","../src/instrumentation/hook.ts","../src/instrumentation/bullmq.ts","../src/instrumentation/cron.ts","../package.json","../src/utils/sdkMeta.ts","../src/middleware/express.ts","../src/core/normalizer.ts","../src/wrappers/h3.ts","../src/wrappers/next.ts","../src/wrappers/fastify.ts","../src/index.ts"],"sourcesContent":["import { SenzorOptions, Trace, TaskRun, SenzorError, SenzorLog } from './types';\r\n\r\nexport class Transport {\r\n private traceQueue: Trace[] = [];\r\n private apmErrorQueue: SenzorError[] = [];\r\n private apmLogQueue: SenzorLog[] = []; // APM Logs\r\n\r\n private taskQueue: TaskRun[] = [];\r\n private taskErrorQueue: SenzorError[] = [];\r\n private taskLogQueue: SenzorLog[] = []; // Task Logs\r\n\r\n private timer: NodeJS.Timeout | null = null;\r\n private apmEndpoint: string;\r\n private taskEndpoint: string;\r\n\r\n constructor(private config: SenzorOptions) {\r\n const baseEndpoint = config.endpoint || 'https://api.senzor.dev';\r\n // Support legacy full URLs or base URLs\r\n this.apmEndpoint = baseEndpoint.includes('/api/ingest') ? baseEndpoint : `${baseEndpoint}/api/ingest/apm`;\r\n this.taskEndpoint = baseEndpoint.includes('/api/ingest') ? baseEndpoint.replace('/apm', '/task') : `${baseEndpoint}/api/ingest/task`;\r\n\r\n if (typeof setInterval !== 'undefined') {\r\n this.timer = setInterval(() => this.flush(), config.flushInterval || 10000);\r\n if (this.timer && typeof this.timer.unref === 'function') {\r\n this.timer.unref();\r\n }\r\n }\r\n }\r\n\r\n public addTrace(trace: any) {\r\n this.traceQueue.push(trace);\r\n this.checkFlush();\r\n }\r\n\r\n public addTask(task: TaskRun) {\r\n this.taskQueue.push(task);\r\n this.checkFlush();\r\n }\r\n\r\n public addError(error: SenzorError, type: 'apm' | 'task' = 'apm') {\r\n if (type === 'task') this.taskErrorQueue.push(error);\r\n else this.apmErrorQueue.push(error);\r\n this.checkFlush();\r\n }\r\n\r\n // Add captured log to the correct batch queue\r\n public addLog(log: SenzorLog, type: 'apm' | 'task' = 'apm') {\r\n if (type === 'task') this.taskLogQueue.push(log);\r\n else this.apmLogQueue.push(log);\r\n this.checkFlush();\r\n }\r\n\r\n private checkFlush() {\r\n const totalApm = this.traceQueue.length + this.apmErrorQueue.length + this.apmLogQueue.length;\r\n const totalTask = this.taskQueue.length + this.taskErrorQueue.length + this.taskLogQueue.length;\r\n if (totalApm >= (this.config.batchSize || 100) || totalTask >= (this.config.batchSize || 100)) {\r\n this.flush();\r\n }\r\n }\r\n\r\n public async flush() {\r\n const apmPayload = {\r\n traces: [...this.traceQueue],\r\n errors: [...this.apmErrorQueue],\r\n logs: [...this.apmLogQueue]\r\n };\r\n const taskPayload = {\r\n runs: [...this.taskQueue],\r\n errors: [...this.taskErrorQueue],\r\n logs: [...this.taskLogQueue]\r\n };\r\n\r\n // Reset Queues instantly\r\n this.traceQueue = [];\r\n this.apmErrorQueue = [];\r\n this.apmLogQueue = [];\r\n this.taskQueue = [];\r\n this.taskErrorQueue = [];\r\n this.taskLogQueue = [];\r\n\r\n const headers = { 'Content-Type': 'application/json', 'x-service-api-key': this.config.apiKey };\r\n\r\n try {\r\n const promises = [];\r\n\r\n // Piggyback logs onto APM/Task batch ingestion to bypass extra network round-trips\r\n if (apmPayload.traces.length > 0 || apmPayload.errors.length > 0 || apmPayload.logs.length > 0) {\r\n promises.push(fetch(this.apmEndpoint, { method: 'POST', headers, body: JSON.stringify(apmPayload), keepalive: true }));\r\n }\r\n\r\n if (taskPayload.runs.length > 0 || taskPayload.errors.length > 0 || taskPayload.logs.length > 0) {\r\n promises.push(fetch(this.taskEndpoint, { method: 'POST', headers, body: JSON.stringify(taskPayload), keepalive: true }));\r\n }\r\n\r\n await Promise.allSettled(promises);\r\n\r\n if (this.config.debug) {\r\n console.log(`[Senzor] Flushed: APM(${apmPayload.traces.length} traces, ${apmPayload.logs.length} logs), Task(${taskPayload.runs.length} runs, ${taskPayload.logs.length} logs)`);\r\n }\r\n } catch (err) {\r\n if (this.config.debug) console.error('[Senzor] Transport Flush Error:', err);\r\n }\r\n }\r\n}","import { AsyncLocalStorage } from 'async_hooks';\r\nimport { ActiveTrace } from './types';\r\n\r\nexport const storage = new AsyncLocalStorage<ActiveTrace>();\r\n\r\nexport const Context = {\r\n run: <T>(trace: ActiveTrace, fn: () => T): T => {\r\n return storage.run(trace, fn);\r\n },\r\n\r\n current: (): ActiveTrace | undefined => {\r\n return storage.getStore();\r\n },\r\n\r\n addSpan: (span: any) => {\r\n const store = storage.getStore();\r\n if (store) {\r\n store.spans.push(span);\r\n }\r\n }\r\n};","import { Transport } from './transport';\r\nimport { Context } from './context';\r\nimport { SenzorOptions, ActiveTrace, TaskRun, SenzorLog } from './types';\r\nimport { randomUUID } from 'crypto';\r\nimport { instrumentHttp, instrumentFetch } from '../instrumentation/http';\r\nimport { instrumentMongo } from '../instrumentation/mongo';\r\nimport { instrumentPg } from '../instrumentation/pg';\r\nimport { instrumentBullMQ } from '../instrumentation/bullmq';\r\nimport { instrumentNodeCron } from '../instrumentation/cron';\r\nimport { SDK_META } from '../utils/sdkMeta';\r\nimport { parseTraceparent } from '../utils/traceContext';\r\n\r\nconst generateW3CTraceId = () => randomUUID().replace(/-/g, '');\r\n\r\n// Memory-safe JSON stringifier to handle cyclical objects \r\n// (like Express 'req' objects) passed into console.log\r\nconst safeStringify = (obj: any): string => {\r\n const cache = new Set();\r\n return JSON.stringify(obj, (key, value) => {\r\n if (typeof value === 'object' && value !== null) {\r\n if (cache.has(value)) return '[Circular]';\r\n cache.add(value);\r\n }\r\n return value;\r\n });\r\n};\r\n\r\nexport class SenzorClient {\r\n private transport: Transport | null = null;\r\n private options: SenzorOptions | null = null;\r\n private isInstrumented = false;\r\n\r\n public init(options: SenzorOptions) {\r\n if (!options.apiKey) {\r\n console.warn('[Senzor] API Key missing. SDK disabled.');\r\n return;\r\n }\r\n this.options = options;\r\n const endpoint = options.endpoint || 'https://api.senzor.dev/api/ingest/apm';\r\n const debug = options.debug || false;\r\n\r\n this.transport = new Transport({ ...options, endpoint });\r\n\r\n if (!this.isInstrumented) {\r\n this.setupGlobalErrorHandlers();\r\n this.setupLogInterception(); // Fire up Auto Log Instrumentation\r\n\r\n try { instrumentHttp(endpoint, debug); } catch (e) { }\r\n try { instrumentFetch(endpoint, debug); } catch (e) { }\r\n try { instrumentMongo(debug); } catch (e) { }\r\n try { instrumentPg(); } catch (e) { }\r\n\r\n // Task Integrations \r\n try { instrumentBullMQ(this, debug); } catch (e) { }\r\n try { instrumentNodeCron(this, debug); } catch (e) { }\r\n\r\n this.isInstrumented = true;\r\n if (debug) console.log('[Senzor] Auto-instrumentation enabled');\r\n }\r\n }\r\n\r\n // --- Enterprise Auto-Log Interception ---\r\n private setupLogInterception() {\r\n if (this.options?.autoLogs === false) return; // Opt-out check\r\n\r\n const levels = ['log', 'info', 'warn', 'error', 'debug'] as const;\r\n const originalConsole = {\r\n log: console.log,\r\n info: console.info,\r\n warn: console.warn,\r\n error: console.error,\r\n debug: console.debug\r\n };\r\n\r\n let isIntercepting = false; // Lock to prevent SDK internal logs from looping infinitely\r\n\r\n levels.forEach(level => {\r\n console[level] = (...args: any[]) => {\r\n // Always execute original console so user's terminal isn't broken\r\n originalConsole[level].apply(console, args);\r\n\r\n if (isIntercepting || !this.transport) return;\r\n isIntercepting = true;\r\n\r\n try {\r\n let message = '';\r\n let attributes: Record<string, any> = {};\r\n\r\n args.forEach(arg => {\r\n if (typeof arg === 'string') {\r\n message += (message ? ' ' : '') + arg;\r\n } else if (arg instanceof Error) {\r\n message += (message ? ' ' : '') + arg.message;\r\n attributes.errorStack = arg.stack;\r\n attributes.errorName = arg.name;\r\n } else if (typeof arg === 'object' && arg !== null) {\r\n try {\r\n // New Relic Style Destructuring: Merge all object keys into `attributes`\r\n const parsed = JSON.parse(safeStringify(arg));\r\n attributes = { ...attributes, ...parsed };\r\n } catch (e) {\r\n attributes.unparseableObject = true;\r\n }\r\n } else {\r\n message += (message ? ' ' : '') + String(arg);\r\n }\r\n });\r\n\r\n // Fallback if the user purely logged an object without text e.g., console.log({ user: 123 })\r\n if (!message && Object.keys(attributes).length > 0) {\r\n message = 'Object Log';\r\n }\r\n\r\n // Attach to Active Context seamlessly (Works for BOTH APM and Tasks!)\r\n const currentTrace = Context.current();\r\n const logType = currentTrace?.contextType === 'task' ? 'task' : 'apm';\r\n\r\n const logPayload: SenzorLog = {\r\n message: message || 'Empty log',\r\n level: level === 'log' ? 'info' : level, // Map generic log -> info\r\n attributes,\r\n timestamp: new Date().toISOString()\r\n };\r\n\r\n // Attach the specific contextual ID\r\n if (currentTrace) {\r\n if (logType === 'task') logPayload.runId = currentTrace.id;\r\n else logPayload.traceId = currentTrace.id;\r\n }\r\n\r\n this.transport.addLog(logPayload, logType);\r\n } catch (e) {\r\n // Absolute failure isolation. Never crash host app during logging.\r\n } finally {\r\n isIntercepting = false; // Release lock\r\n }\r\n };\r\n });\r\n }\r\n\r\n private setupGlobalErrorHandlers() {\r\n if ((process as any).__senzorGlobalHandlersInstalled) {\r\n return;\r\n }\r\n\r\n (process as any).__senzorGlobalHandlersInstalled = true;\r\n\r\n const getProcessContext = () => {\r\n try {\r\n return {\r\n pid: process.pid,\r\n ppid: process.ppid,\r\n platform: process.platform,\r\n uptimeSec: Math.floor(process.uptime()),\r\n env: process.env.NODE_ENV || 'unknown'\r\n };\r\n } catch {\r\n return {};\r\n }\r\n };\r\n\r\n const getMemoryContext = () => {\r\n try {\r\n const mem = process.memoryUsage();\r\n return {\r\n rss: mem.rss,\r\n heapTotal: mem.heapTotal,\r\n heapUsed: mem.heapUsed,\r\n external: mem.external,\r\n arrayBuffers: mem.arrayBuffers\r\n };\r\n } catch {\r\n return {};\r\n }\r\n };\r\n\r\n const safeCapture = (error: unknown, meta: any = {}) => {\r\n try {\r\n let parsedError: Error;\r\n if (error instanceof Error) {\r\n parsedError = error;\r\n } else if (typeof error === 'string') {\r\n parsedError = new Error(error);\r\n } else {\r\n try {\r\n parsedError = new Error(JSON.stringify(error));\r\n } catch {\r\n parsedError = new Error('Non-serializable rejection reason');\r\n }\r\n }\r\n const enrichedMeta = {\r\n ...meta,\r\n runtime: { name: 'node', version: process.version },\r\n process: getProcessContext(),\r\n memory: getMemoryContext(),\r\n sdk: { name: SDK_META.name, version: SDK_META.version }\r\n };\r\n\r\n this.captureError(parsedError, enrichedMeta);\r\n } catch (internalFailure) {\r\n try {\r\n if (this.options?.debug) {\r\n console.error('[Senzor] Error handler failure:', internalFailure);\r\n }\r\n } catch { }\r\n }\r\n };\r\n\r\n process.on('uncaughtExceptionMonitor', (error) => safeCapture(error, { type: 'uncaughtExceptionMonitor', severity: 'fatal' }));\r\n process.on('uncaughtException', (error) => safeCapture(error, { type: 'uncaughtException', severity: 'fatal' }));\r\n process.on('unhandledRejection', (reason) => safeCapture(reason, { type: 'unhandledRejection', severity: 'error' }));\r\n process.on('warning', (warning) => safeCapture(warning, { type: 'processWarning', severity: 'warning' }));\r\n process.on('multipleResolves', (type, promise, reason) => safeCapture(reason || new Error('Multiple promise resolves'), { type: 'multipleResolves', resolveType: type, severity: 'warning' }));\r\n process.on('rejectionHandled', (promise) => { if (this.options?.debug) { try { console.warn('[Senzor] rejectionHandled event detected'); } catch { } } });\r\n process.on('SIGTERM', () => safeCapture(new Error('Process received SIGTERM'), { type: 'processSignal', signal: 'SIGTERM' }));\r\n process.on('SIGINT', () => safeCapture(new Error('Process received SIGINT'), { type: 'processSignal', signal: 'SIGINT' }));\r\n }\r\n\r\n public startTrace<T>(data: Partial<ActiveTrace['data']> & { headers?: any }, next: () => T): T {\r\n if (!this.transport) return next();\r\n\r\n let inheritedTraceId: string | undefined = undefined;\r\n let inheritedParentSpanId: string | undefined = undefined;\r\n\r\n if (data.headers) {\r\n const getHeader = (key: string) => {\r\n if (data.headers[key]) return data.headers[key];\r\n if (data.headers[key.toLowerCase()]) return data.headers[key.toLowerCase()];\r\n return undefined;\r\n };\r\n\r\n const traceparent = getHeader('traceparent');\r\n const parsedContext = parseTraceparent(traceparent);\r\n\r\n if (parsedContext) {\r\n inheritedTraceId = parsedContext.traceId;\r\n inheritedParentSpanId = parsedContext.parentSpanId;\r\n } else {\r\n const rawTrace = getHeader('x-senzor-trace-id');\r\n const rawSpan = getHeader('x-senzor-parent-span-id');\r\n inheritedTraceId = Array.isArray(rawTrace) ? rawTrace[0] : rawTrace;\r\n inheritedParentSpanId = Array.isArray(rawSpan) ? rawSpan[0] : rawSpan;\r\n }\r\n }\r\n\r\n const activeTraceId = inheritedTraceId || generateW3CTraceId();\r\n\r\n const trace: ActiveTrace = {\r\n id: activeTraceId,\r\n contextType: 'apm',\r\n startTime: performance.now(),\r\n data: { ...data, parentTraceId: inheritedTraceId, parentSpanId: inheritedParentSpanId },\r\n spans: []\r\n };\r\n\r\n return Context.run(trace, next);\r\n }\r\n\r\n public endTrace(status: number, extraData: any = {}) {\r\n const trace = Context.current();\r\n if (!trace || trace.contextType !== 'apm' || !this.transport) return;\r\n const duration = performance.now() - trace.startTime;\r\n\r\n const payload = {\r\n traceId: trace.id,\r\n parentTraceId: trace.data.parentTraceId,\r\n parentSpanId: trace.data.parentSpanId,\r\n ...trace.data,\r\n ...extraData,\r\n status, duration, spans: trace.spans, timestamp: new Date().toISOString()\r\n };\r\n this.transport.addTrace(payload);\r\n }\r\n\r\n // --- TASK MONITORING METHODS ---\r\n public startTask<T>(name: string, type: 'cron' | 'queue' | 'pipeline' | 'custom', options: any, next: () => T): T {\r\n if (!this.transport) return next();\r\n\r\n const currentContext = Context.current();\r\n const triggerTraceId = currentContext?.contextType === 'apm' ? currentContext.id : undefined;\r\n\r\n const startMemory = process.memoryUsage ? process.memoryUsage().heapUsed : 0;\r\n const startCpu = process.cpuUsage ? process.cpuUsage() : undefined;\r\n\r\n const task: ActiveTrace = {\r\n id: randomUUID(),\r\n contextType: 'task',\r\n startTime: performance.now(),\r\n startMemory,\r\n startCpu,\r\n data: { taskName: name, taskType: type, triggerTraceId, ...options },\r\n spans: []\r\n };\r\n return Context.run(task, next);\r\n }\r\n\r\n public endTask(status: 'success' | 'failed', extraMetadata: any = {}) {\r\n const task = Context.current();\r\n if (!task || task.contextType !== 'task' || !this.transport) return;\r\n\r\n let resourceMetrics;\r\n if (process.memoryUsage && task.startMemory !== undefined && process.cpuUsage && task.startCpu) {\r\n const endMemory = process.memoryUsage().heapUsed;\r\n const cpuDelta = process.cpuUsage(task.startCpu);\r\n\r\n resourceMetrics = {\r\n memoryDeltaBytes: endMemory - task.startMemory,\r\n cpuUserUs: cpuDelta.user,\r\n cpuSystemUs: cpuDelta.system\r\n };\r\n }\r\n\r\n const payload: TaskRun = {\r\n runId: task.id,\r\n taskName: task.data.taskName,\r\n taskType: task.data.taskType,\r\n triggerTraceId: task.data.triggerTraceId,\r\n queueDelay: task.data.queueDelay,\r\n attempts: task.data.attempts,\r\n isDeadLetter: task.data.isDeadLetter,\r\n metadata: { ...task.data.metadata, ...extraMetadata },\r\n resourceMetrics,\r\n status,\r\n duration: performance.now() - task.startTime,\r\n spans: task.spans,\r\n timestamp: new Date().toISOString()\r\n };\r\n\r\n this.transport.addTask(payload);\r\n }\r\n\r\n public wrapTask<T extends (...args: any[]) => any>(name: string, type: 'cron' | 'queue' | 'pipeline' | 'custom', options: any = {}, fn: T): T {\r\n return (async (...args: any[]) => {\r\n return this.startTask(name, type, options, async () => {\r\n try {\r\n const result = await fn(...args);\r\n this.endTask('success');\r\n return result;\r\n } catch (error) {\r\n this.captureError(error, { taskName: name });\r\n this.endTask('failed');\r\n throw error;\r\n }\r\n });\r\n }) as unknown as T;\r\n }\r\n\r\n public captureError(error: unknown, context: any = {}) {\r\n if (!this.transport) return;\r\n\r\n let parsedError: Error;\r\n if (error instanceof Error) {\r\n parsedError = error;\r\n } else {\r\n parsedError = new Error(String(error));\r\n }\r\n\r\n const currentTrace = Context.current();\r\n\r\n const errPayload = {\r\n errorClass: parsedError.name || 'Error',\r\n message: parsedError.message,\r\n stackTrace: parsedError.stack,\r\n context,\r\n timestamp: new Date().toISOString()\r\n };\r\n\r\n if (currentTrace?.contextType === 'task') {\r\n this.transport.addError({ ...errPayload, runId: currentTrace.id }, 'task');\r\n } else {\r\n this.transport.addError({ ...errPayload, traceId: currentTrace?.id }, 'apm');\r\n }\r\n }\r\n\r\n public track(data: any) {\r\n this.transport?.addTrace({ traceId: generateW3CTraceId(), ...data, spans: [], timestamp: new Date().toISOString() });\r\n }\r\n\r\n public startSpan(name: string, type: 'db' | 'http' | 'function' | 'custom' = 'custom') {\r\n const trace = Context.current();\r\n if (!trace) return { end: () => { } };\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n const spanId = randomUUID().replace(/-/g, '').slice(0, 16);\r\n return { end: (meta?: any, status?: number) => { Context.addSpan({ spanId, name, type, startTime, duration: performance.now() - spanStartAbs, status, meta }); } };\r\n }\r\n\r\n public async flush() { if (this.transport) await this.transport.flush(); }\r\n}\r\n\r\nexport const client = new SenzorClient();","import http from 'http';\r\nimport https from 'https';\r\nimport { URL } from 'url';\r\nimport { Context } from '../core/context';\r\nimport { randomUUID } from 'crypto';\r\nimport { generateTraceparent } from '../utils/traceContext';\r\n\r\nconst shimmer = (module: any, methodName: string, wrapper: (original: Function) => Function) => {\r\n if (!module[methodName]) return;\r\n const original = module[methodName];\r\n module[methodName] = wrapper(original);\r\n};\r\n\r\n// 16-char hex for W3C standard spans\r\nconst generateSpanId = () => randomUUID().replace(/-/g, '').slice(0, 16);\r\n\r\n// --- FETCH INSTRUMENTATION ---\r\nexport const instrumentFetch = (ingestUrl: string, debug = false) => {\r\n if (!globalThis.fetch) return;\r\n\r\n let ingestHost = '';\r\n try { ingestHost = new URL(ingestUrl).hostname; } catch (e) { }\r\n\r\n const originalFetch = globalThis.fetch;\r\n\r\n // @ts-ignore\r\n globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {\r\n let urlStr = '';\r\n if (typeof input === 'string') urlStr = input;\r\n else if (input instanceof URL) urlStr = input.toString();\r\n else if (input && (input as any).url) urlStr = (input as any).url;\r\n\r\n if (ingestHost && urlStr.includes(ingestHost)) {\r\n return originalFetch(input, init);\r\n }\r\n\r\n const trace = Context.current();\r\n if (!trace) {\r\n return originalFetch(input, init);\r\n }\r\n\r\n const method = (init?.method || 'GET').toUpperCase();\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n const spanId = generateSpanId();\r\n\r\n let hostname = 'unknown';\r\n try { hostname = new URL(urlStr).hostname; } catch (e) { }\r\n\r\n const newInit = { ...init } as RequestInit;\r\n if (!newInit.headers) newInit.headers = {};\r\n\r\n const setHeader = (key: string, value: string) => {\r\n if (newInit.headers instanceof Headers) {\r\n newInit.headers.set(key, value);\r\n } else if (Array.isArray(newInit.headers)) {\r\n newInit.headers.push([key, value]);\r\n } else {\r\n (newInit.headers as any)[key] = value;\r\n }\r\n };\r\n\r\n // W3C Trace Context Injection\r\n setHeader('traceparent', generateTraceparent(trace.id, spanId));\r\n\r\n // Legacy fallback for older Senzor services\r\n setHeader('x-senzor-trace-id', trace.id);\r\n setHeader('x-senzor-parent-span-id', spanId);\r\n\r\n try {\r\n const response = await originalFetch(input, newInit);\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({ spanId, name: `${method} ${hostname}`, type: 'http', startTime, duration, status: response.status, meta: { url: urlStr, method, library: 'fetch' } });\r\n return response;\r\n } catch (err: any) {\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({ spanId, name: `${method} ${hostname}`, type: 'http', startTime, duration, status: 500, meta: { error: err.message, url: urlStr, library: 'fetch' } });\r\n throw err;\r\n }\r\n };\r\n};\r\n\r\n// --- HTTP/HTTPS INSTRUMENTATION ---\r\nexport const instrumentHttp = (ingestUrl: string, debug = false) => {\r\n let ingestHost = '';\r\n try { ingestHost = new URL(ingestUrl).hostname; } catch (e) { }\r\n\r\n const requestWrapper = (original: Function) => {\r\n return function (this: any, ...args: any[]) {\r\n let options: any = {};\r\n let urlStr = '';\r\n let optionsIndex = 0;\r\n\r\n if (typeof args[0] === 'string' || args[0] instanceof URL) {\r\n urlStr = args[0].toString();\r\n optionsIndex = 1;\r\n } else {\r\n optionsIndex = 0;\r\n }\r\n\r\n if (!args[optionsIndex] || typeof args[optionsIndex] !== 'object') {\r\n args[optionsIndex] = {};\r\n }\r\n options = args[optionsIndex];\r\n\r\n if (!urlStr) {\r\n const protocol = options.protocol || (options.port === 443 ? 'https:' : 'http:');\r\n const host = options.hostname || options.host || 'localhost';\r\n const path = options.path || '/';\r\n urlStr = `${protocol}//${host}${path}`;\r\n }\r\n\r\n if (ingestHost && (urlStr.includes(ingestHost) || (options.hostname && options.hostname.includes(ingestHost)))) {\r\n return original.apply(this, args);\r\n }\r\n\r\n const trace = Context.current();\r\n if (!trace) return original.apply(this, args);\r\n\r\n const method = (options.method || 'GET').toUpperCase();\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n const spanId = generateSpanId();\r\n\r\n let hostname = 'unknown';\r\n try { hostname = new URL(urlStr).hostname; } catch (e) { hostname = options.hostname || 'unknown'; }\r\n\r\n if (!options.headers) options.headers = {};\r\n\r\n // W3C Trace Context Injection\r\n options.headers['traceparent'] = generateTraceparent(trace.id, spanId);\r\n\r\n // Legacy fallback\r\n options.headers['x-senzor-trace-id'] = trace.id;\r\n options.headers['x-senzor-parent-span-id'] = spanId;\r\n\r\n if (debug) console.log(`[Senzor] Injecting W3C traceparent headers to ${urlStr}`);\r\n\r\n const req = original.apply(this, args);\r\n\r\n const captureSpan = (res: any, error?: Error) => {\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({ spanId, name: `${method} ${hostname}`, type: 'http', startTime, duration, status: error ? 500 : res?.statusCode || 0, meta: { url: urlStr, method, library: 'http' } });\r\n };\r\n\r\n req.on('response', (res: any) => {\r\n res.once('end', () => captureSpan(res));\r\n res.once('close', () => captureSpan(res));\r\n res.once('error', (err: Error) => captureSpan(res, err));\r\n });\r\n\r\n req.on('error', (err: Error) => captureSpan(null, err));\r\n\r\n return req;\r\n };\r\n };\r\n\r\n shimmer(http, 'request', requestWrapper);\r\n shimmer(http, 'get', requestWrapper);\r\n shimmer(https, 'request', requestWrapper);\r\n shimmer(https, 'get', requestWrapper);\r\n};","/**\r\n * W3C Trace Context Implementation\r\n * Standard: https://www.w3.org/TR/trace-context/\r\n * Format: 00-{traceId}-{spanId}-{traceFlags}\r\n */\r\n\r\nexport interface TraceContext {\r\n traceId: string;\r\n parentSpanId: string;\r\n sampled: boolean;\r\n}\r\n\r\nconst TRACEPARENT_REGEX = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;\r\n\r\nexport const parseTraceparent = (header?: string | string[]): TraceContext | null => {\r\n if (!header) return null;\r\n\r\n const traceparent = Array.isArray(header) ? header[0] : header;\r\n if (typeof traceparent !== 'string') return null;\r\n\r\n const match = traceparent.trim().toLowerCase().match(TRACEPARENT_REGEX);\r\n if (!match) return null;\r\n\r\n const traceId = match[1];\r\n const parentSpanId = match[2];\r\n const flags = match[3];\r\n\r\n // Invalid IDs according to W3C specification\r\n if (traceId === '00000000000000000000000000000000') return null;\r\n if (parentSpanId === '0000000000000000') return null;\r\n\r\n // The least significant bit of flags indicates if the trace is sampled\r\n const sampled = (parseInt(flags, 16) & 0x01) === 0x01;\r\n\r\n return { traceId, parentSpanId, sampled };\r\n};\r\n\r\n/**\r\n * Generates a valid W3C traceparent header string for OUTGOING requests.\r\n */\r\nexport const generateTraceparent = (traceId: string, spanId: string, sampled: boolean = true): string => {\r\n const flags = sampled ? '01' : '00';\r\n return `00-${traceId}-${spanId}-${flags}`;\r\n};","import { Context } from '../core/context';\r\n\r\nexport const instrumentMongo = (debug = false) => {\r\n try {\r\n const mongodb = require('mongodb');\r\n const Collection = mongodb.Collection;\r\n\r\n // Attempt to get Cursor classes\r\n // Note: The location of these classes varies by driver version, \r\n // checking common locations\r\n const FindCursor = mongodb.FindCursor || require('mongodb/lib/cursor/find_cursor').FindCursor;\r\n const AggregationCursor = mongodb.AggregationCursor || require('mongodb/lib/cursor/aggregation_cursor').AggregationCursor;\r\n\r\n if (debug) console.log('[Senzor] Instrumenting MongoDB (Collection + Cursors)...');\r\n\r\n // --- Helper to Record Span ---\r\n const recordSpan = (name: string, operation: string, collection: string, startAbs: number, traceStart: number, err?: Error) => {\r\n const duration = performance.now() - startAbs;\r\n Context.addSpan({\r\n name: `MongoDB ${name}`,\r\n type: 'db',\r\n startTime: performance.now() - traceStart - duration, // Adjust start time to when op actually started\r\n duration,\r\n status: err ? 500 : 0,\r\n meta: { collection, operation, error: err ? err.message : undefined }\r\n });\r\n if (debug) console.log(`[Senzor] Captured Mongo: ${name} (${duration.toFixed(2)}ms)`);\r\n };\r\n\r\n // --- 1. Instrument Immediate Operations (Insert/Update/Delete) ---\r\n const immediateMethods = ['insertOne', 'insertMany', 'updateOne', 'updateMany', 'deleteOne', 'deleteMany', 'countDocuments'];\r\n\r\n immediateMethods.forEach((method) => {\r\n if (!Collection.prototype[method]) return;\r\n const original = Collection.prototype[method];\r\n\r\n Collection.prototype[method] = function (...args: any[]) {\r\n const trace = Context.current();\r\n if (!trace) return original.apply(this, args);\r\n\r\n const spanStartAbs = performance.now();\r\n const traceStart = trace.startTime;\r\n const collName = this.collectionName;\r\n\r\n try {\r\n const result = original.apply(this, args);\r\n if (result && typeof result.then === 'function') {\r\n return result.then(\r\n (res: any) => { recordSpan(method, method, collName, spanStartAbs, traceStart); return res; },\r\n (err: any) => { recordSpan(method, method, collName, spanStartAbs, traceStart, err); throw err; }\r\n );\r\n }\r\n return result;\r\n } catch (err: any) {\r\n recordSpan(method, method, collName, spanStartAbs, traceStart, err);\r\n throw err;\r\n }\r\n };\r\n });\r\n\r\n // --- 2. Instrument Cursor Execution (find -> toArray) ---\r\n const patchCursor = (CursorClass: any, label: string) => {\r\n if (!CursorClass || !CursorClass.prototype.toArray) return;\r\n\r\n const originalToArray = CursorClass.prototype.toArray;\r\n\r\n CursorClass.prototype.toArray = function (...args: any[]) {\r\n const trace = Context.current();\r\n // Cursors are often created in context but executed later. \r\n // We check context at execution time.\r\n if (!trace) return originalToArray.apply(this, args);\r\n\r\n const spanStartAbs = performance.now();\r\n const traceStart = trace.startTime;\r\n // Attempt to get collection name from cursor internal state\r\n const collName = this.namespace?.collection || 'unknown';\r\n\r\n const onSuccess = (res: any) => {\r\n recordSpan(label, label, collName, spanStartAbs, traceStart);\r\n return res;\r\n };\r\n const onError = (err: any) => {\r\n recordSpan(label, label, collName, spanStartAbs, traceStart, err);\r\n throw err;\r\n };\r\n\r\n try {\r\n const result = originalToArray.apply(this, args);\r\n if (result && typeof result.then === 'function') {\r\n return result.then(onSuccess, onError);\r\n }\r\n return onSuccess(result);\r\n } catch (e) {\r\n onError(e);\r\n }\r\n };\r\n };\r\n\r\n patchCursor(FindCursor, 'find');\r\n patchCursor(AggregationCursor, 'aggregate');\r\n\r\n } catch (e: any) {\r\n if (debug) console.warn('[Senzor] MongoDB instrumentation warning:', e.message);\r\n }\r\n};","import { Context } from '../core/context';\r\n\r\n// Simple shim for 'pg' library\r\nexport const instrumentPg = () => {\r\n try {\r\n // Try to require pg (it might not be installed by user)\r\n const pg = require('pg');\r\n const originalQuery = pg.Client.prototype.query;\r\n\r\n pg.Client.prototype.query = function (...args: any[]) {\r\n const trace = Context.current();\r\n if (!trace) return originalQuery.apply(this, args);\r\n\r\n const startTime = performance.now() - trace.startTime;\r\n const spanStartAbs = performance.now();\r\n\r\n // Extract SQL (first arg usually string or config object)\r\n const sql = typeof args[0] === 'string' ? args[0] : args[0].text;\r\n\r\n // Wrap callback if present, or handle Promise\r\n const result = originalQuery.apply(this, args);\r\n\r\n if (result && typeof result.then === 'function') {\r\n return result.then((res: any) => {\r\n const duration = performance.now() - spanStartAbs;\r\n Context.addSpan({\r\n name: 'Postgres Query',\r\n type: 'db',\r\n startTime,\r\n duration,\r\n meta: { query: sql }\r\n });\r\n return res;\r\n });\r\n }\r\n return result;\r\n };\r\n } catch (e) {\r\n // User doesn't use pg, ignore\r\n }\r\n};","import Module from 'module';\r\n\r\nconst SENZOR_PATCHED =\r\n Symbol.for('senzor.require.patched');\r\n\r\nconst SENZOR_HOOKS =\r\n Symbol.for('senzor.require.hooks');\r\n\r\ntype HookFn =\r\n (exports: unknown) => void;\r\n\r\ntype HookMap =\r\n Map<string, HookFn[]>;\r\n\r\nfunction getHookRegistry(): HookMap {\r\n\r\n const mod =\r\n Module as unknown as Record<\r\n symbol,\r\n HookMap\r\n >;\r\n\r\n if (!mod[SENZOR_HOOKS]) {\r\n\r\n Object.defineProperty(\r\n mod,\r\n SENZOR_HOOKS,\r\n {\r\n value: new Map(),\r\n enumerable: false\r\n }\r\n );\r\n\r\n }\r\n\r\n return mod[SENZOR_HOOKS];\r\n\r\n}\r\n\r\nfunction runHooks(\r\n moduleName: string,\r\n exports: unknown\r\n) {\r\n\r\n const registry =\r\n (Module as unknown as Record<\r\n symbol,\r\n HookMap\r\n >)[SENZOR_HOOKS];\r\n\r\n if (!registry) return;\r\n\r\n const hooks =\r\n registry.get(moduleName);\r\n\r\n if (!hooks?.length) return;\r\n\r\n for (const hook of hooks) {\r\n\r\n try {\r\n hook(exports);\r\n }\r\n catch (err) {\r\n\r\n console.error(\r\n `[Senzor] instrumentation failed for ${moduleName}`,\r\n err\r\n );\r\n\r\n }\r\n\r\n }\r\n\r\n}\r\n\r\nfunction patchLoaderOnce() {\r\n\r\n const mod =\r\n Module as unknown as any;\r\n\r\n if (mod[SENZOR_PATCHED]) {\r\n return;\r\n }\r\n\r\n const previousLoad =\r\n mod._load;\r\n\r\n mod._load =\r\n function patchedLoad(\r\n request: string,\r\n parent: unknown,\r\n isMain: boolean\r\n ) {\r\n\r\n const exports =\r\n previousLoad.apply(\r\n this,\r\n arguments\r\n );\r\n\r\n runHooks(\r\n request,\r\n exports\r\n );\r\n\r\n return exports;\r\n\r\n };\r\n\r\n Object.defineProperty(\r\n mod,\r\n SENZOR_PATCHED,\r\n {\r\n value: true,\r\n enumerable: false\r\n }\r\n );\r\n\r\n}\r\n\r\nfunction patchCached(\r\n moduleName: string,\r\n hook: HookFn\r\n) {\r\n\r\n try {\r\n\r\n const resolved =\r\n require.resolve(\r\n moduleName\r\n );\r\n\r\n const cached =\r\n require.cache?.[\r\n resolved\r\n ];\r\n\r\n if (cached?.exports) {\r\n\r\n hook(\r\n cached.exports\r\n );\r\n\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n}\r\n\r\nfunction tryRequire(\r\n moduleName: string,\r\n hook: HookFn\r\n) {\r\n\r\n try {\r\n\r\n const mod =\r\n require(moduleName);\r\n\r\n if (mod) {\r\n hook(mod);\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n}\r\n\r\nfunction retryPatch(\r\n moduleName: string,\r\n hook: HookFn\r\n) {\r\n\r\n let attempts = 0;\r\n\r\n const max = 5;\r\n\r\n const timer =\r\n setInterval(() => {\r\n\r\n attempts++;\r\n\r\n try {\r\n\r\n const mod =\r\n require(moduleName);\r\n\r\n if (mod) {\r\n\r\n hook(mod);\r\n\r\n clearInterval(timer);\r\n\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n if (attempts >= max) {\r\n clearInterval(timer);\r\n }\r\n\r\n }, 200);\r\n\r\n}\r\n\r\nexport const hookRequire =\r\n (\r\n moduleName: string,\r\n onRequire: HookFn\r\n ) => {\r\n\r\n const registry =\r\n getHookRegistry();\r\n\r\n if (!registry.has(moduleName)) {\r\n\r\n registry.set(\r\n moduleName,\r\n []\r\n );\r\n\r\n }\r\n\r\n registry\r\n .get(moduleName)!\r\n .push(onRequire);\r\n\r\n patchLoaderOnce();\r\n\r\n patchCached(\r\n moduleName,\r\n onRequire\r\n );\r\n\r\n tryRequire(\r\n moduleName,\r\n onRequire\r\n );\r\n\r\n retryPatch(\r\n moduleName,\r\n onRequire\r\n );\r\n\r\n };","import type { SenzorClient } from '../core/client';\r\nimport { hookRequire } from './hook';\r\nimport { Context } from '../core/context';\r\n\r\nconst PATCHED =\r\n Symbol.for(\r\n 'senzor.bullmq.patched'\r\n );\r\n\r\nfunction patchWorker(\r\n target: any,\r\n client: SenzorClient,\r\n debug: boolean\r\n) {\r\n\r\n if (\r\n !target?.Worker?.prototype\r\n ) {\r\n return;\r\n }\r\n\r\n const proto =\r\n target.Worker.prototype;\r\n\r\n const original =\r\n proto.processJob;\r\n\r\n if (\r\n typeof original !==\r\n 'function' ||\r\n original[PATCHED]\r\n ) {\r\n return;\r\n }\r\n\r\n proto.processJob =\r\n async function (\r\n job: any\r\n ) {\r\n\r\n const queueDelay =\r\n job.timestamp\r\n ? Date.now() -\r\n job.timestamp\r\n : 0;\r\n\r\n const currentAttempt =\r\n (job.attemptsMade || 0)\r\n + 1;\r\n\r\n const maxAttempts =\r\n job.opts?.attempts\r\n ?? 1;\r\n\r\n const isFinal =\r\n currentAttempt >=\r\n maxAttempts;\r\n\r\n const taskName =\r\n job.name ===\r\n '__default__'\r\n ? job.queueName\r\n : `${job.queueName}:${job.name}`;\r\n\r\n return client.startTask(\r\n\r\n taskName,\r\n\r\n 'queue',\r\n\r\n {\r\n queueDelay,\r\n attempts:\r\n currentAttempt,\r\n isDeadLetter: false,\r\n metadata: {\r\n jobId: job.id,\r\n queueName:\r\n job.queueName,\r\n maxAttempts\r\n }\r\n },\r\n\r\n async () => {\r\n\r\n try {\r\n\r\n const result =\r\n await original.call(\r\n this,\r\n job\r\n );\r\n\r\n client.endTask(\r\n 'success'\r\n );\r\n\r\n return result;\r\n\r\n }\r\n catch (error) {\r\n\r\n try {\r\n\r\n const ctx =\r\n Context.current();\r\n\r\n if (\r\n ctx &&\r\n ctx.contextType === 'task' &&\r\n isFinal\r\n ) {\r\n\r\n ctx.data\r\n .isDeadLetter =\r\n true;\r\n\r\n }\r\n\r\n }\r\n catch { }\r\n\r\n client.captureError(\r\n error,\r\n {\r\n queueName:\r\n job.queueName,\r\n jobId: job.id,\r\n isDeadLetter:\r\n isFinal\r\n }\r\n );\r\n\r\n client.endTask(\r\n 'failed'\r\n );\r\n\r\n throw error;\r\n\r\n }\r\n\r\n }\r\n\r\n );\r\n\r\n };\r\n\r\n Object.defineProperty(\r\n proto.processJob,\r\n PATCHED,\r\n {\r\n value: true\r\n }\r\n );\r\n\r\n if (debug) {\r\n\r\n console.log(\r\n '[Senzor] BullMQ instrumented'\r\n );\r\n\r\n }\r\n\r\n}\r\n\r\nexport const instrumentBullMQ =\r\n (\r\n client: SenzorClient,\r\n debug: boolean\r\n ) => {\r\n\r\n hookRequire(\r\n 'bullmq',\r\n (exports: any) => {\r\n\r\n patchWorker(\r\n exports,\r\n client,\r\n debug\r\n );\r\n\r\n if (exports?.default) {\r\n\r\n patchWorker(\r\n exports.default,\r\n client,\r\n debug\r\n );\r\n\r\n }\r\n\r\n }\r\n );\r\n\r\n };","import type { SenzorClient } from '../core/client';\r\nimport { hookRequire } from './hook';\r\n\r\nconst PATCHED =\r\n Symbol.for('senzor.cron.patched');\r\n\r\ntype CronHandler =\r\n (...args: unknown[]) => unknown;\r\n\r\ntype CronSchedule =\r\n (\r\n expression: string,\r\n handler: CronHandler,\r\n options?: unknown\r\n ) => unknown;\r\n\r\nfunction normalizeOptions(\r\n options: unknown\r\n): Record<string, unknown> {\r\n\r\n if (\r\n typeof options === 'object' &&\r\n options !== null\r\n ) {\r\n return options as Record<\r\n string,\r\n unknown\r\n >;\r\n }\r\n\r\n // backward compatibility with:\r\n // cron.schedule(expr, fn, \"UTC\")\r\n if (options) {\r\n return { timezone: options };\r\n }\r\n\r\n return {};\r\n\r\n}\r\n\r\nfunction patchTarget(\r\n target: Record<string, unknown>,\r\n client: SenzorClient,\r\n debug: boolean\r\n): void {\r\n\r\n const schedule =\r\n target.schedule as\r\n CronSchedule | undefined;\r\n\r\n if (\r\n typeof schedule !== 'function' ||\r\n (schedule as any)[PATCHED]\r\n ) {\r\n return;\r\n }\r\n\r\n const original =\r\n schedule;\r\n\r\n const wrapped: CronSchedule =\r\n function (\r\n this: unknown,\r\n expression,\r\n handler,\r\n options\r\n ) {\r\n\r\n if (\r\n typeof handler !==\r\n 'function'\r\n ) {\r\n\r\n return original.call(\r\n this,\r\n expression,\r\n handler,\r\n options\r\n );\r\n\r\n }\r\n\r\n try {\r\n\r\n const opts =\r\n normalizeOptions(\r\n options\r\n );\r\n\r\n const taskName =\r\n (opts as any)?.name ??\r\n `cron: ${expression}`;\r\n\r\n const wrappedHandler =\r\n client.wrapTask(\r\n taskName,\r\n 'cron',\r\n {\r\n expression,\r\n metadata: opts\r\n },\r\n handler\r\n );\r\n\r\n return original.call(\r\n this,\r\n expression,\r\n wrappedHandler,\r\n options\r\n );\r\n\r\n }\r\n catch (err) {\r\n\r\n if (debug) {\r\n\r\n console.error(\r\n '[Senzor] cron wrap failed',\r\n err\r\n );\r\n\r\n }\r\n\r\n return original.call(\r\n this,\r\n expression,\r\n handler,\r\n options\r\n );\r\n\r\n }\r\n\r\n };\r\n\r\n Object.defineProperty(\r\n wrapped,\r\n PATCHED,\r\n {\r\n value: true,\r\n enumerable: false\r\n }\r\n );\r\n\r\n // Some ESM namespace exports are frozen\r\n try {\r\n\r\n target.schedule =\r\n wrapped;\r\n\r\n }\r\n catch {\r\n\r\n if (debug) {\r\n\r\n console.warn(\r\n '[Senzor] unable to patch cron schedule (readonly export)'\r\n );\r\n\r\n }\r\n\r\n }\r\n\r\n if (debug) {\r\n\r\n console.log(\r\n '[Senzor] node-cron instrumented'\r\n );\r\n\r\n }\r\n\r\n}\r\n\r\nexport const instrumentNodeCron =\r\n (\r\n client: SenzorClient,\r\n debug: boolean\r\n ): void => {\r\n\r\n hookRequire(\r\n 'node-cron',\r\n (exports: any) => {\r\n\r\n if (!exports) return;\r\n\r\n patchTarget(\r\n exports,\r\n client,\r\n debug\r\n );\r\n\r\n if (exports.default) {\r\n\r\n patchTarget(\r\n exports.default,\r\n client,\r\n debug\r\n );\r\n\r\n }\r\n\r\n }\r\n );\r\n\r\n };","{\r\n \"name\": \"@senzops/apm-node\",\r\n \"version\": \"1.1.17\",\r\n \"description\": \"Universal APM SDK for Senzor\",\r\n \"main\": \"dist/index.js\",\r\n \"types\": \"dist/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"tsup src/index.ts --format cjs,esm,iife --dts --clean --minify\",\r\n \"prepublishOnly\": \"npm run build\"\r\n },\r\n \"dependencies\": {},\r\n \"devDependencies\": {\r\n \"@types/node\": \"^20.0.0\",\r\n \"tsup\": \"^8.0.0\",\r\n \"typescript\": \"^5.0.0\"\r\n },\r\n \"engines\": {\r\n \"node\": \">=18.0.0\"\r\n },\r\n \"keywords\": [\r\n \"apm\",\r\n \"monitoring\",\r\n \"senzor\",\r\n \"node\",\r\n \"javascript\",\r\n \"api\",\r\n \"observability\"\r\n ],\r\n \"author\": \"Senzops\",\r\n \"license\": \"MIT\"\r\n}\r\n","import pkg from '../../package.json';\r\n\r\nexport const SDK_META = {\r\n name: pkg.name,\r\n version: pkg.version\r\n};","import { client } from '../core/client';\r\n\r\n// 1. Request Handler (Place before routes)\r\nexport const expressMiddleware = () => {\r\n return (req: any, res: any, next: () => void) => {\r\n client.startTrace({\r\n method: req.method,\r\n path: req.originalUrl || req.url,\r\n ip: req.ip || req.socket?.remoteAddress,\r\n userAgent: req.headers['user-agent'],\r\n headers: req.headers\r\n }, () => {\r\n\r\n // Auto-detect status code on finish\r\n res.once('finish', () => {\r\n try {\r\n let route = 'UNKNOWN';\r\n // Express populates req.route only if a route matched\r\n if (req.route && req.route.path) {\r\n route = (req.baseUrl || '') + req.route.path;\r\n } else if (res.statusCode === 404) {\r\n route = 'Not Found';\r\n } else {\r\n route = req.path || 'Wildcard';\r\n }\r\n\r\n client.endTrace(res.statusCode, { route });\r\n } catch (e) { /* Fail open */ }\r\n });\r\n\r\n next();\r\n });\r\n };\r\n};\r\n\r\n// 2. Error Handler (Place after routes)\r\n// This is required in Express to capture the actual Error Object (Stack Trace)\r\nexport const expressErrorHandler = () => {\r\n return (err: any, req: any, res: any, next: (err?: any) => void) => {\r\n\r\n // 1. Capture the exception context\r\n client.captureError(err);\r\n\r\n // 2. Pass it to the next error handler (don't swallow it)\r\n next(err);\r\n };\r\n};","/**\r\n * Heuristic URL Normalizer\r\n * Converts raw paths with IDs into generic patterns to prevent high cardinality.\r\n * Example: /users/123/orders/abc-def -> /users/:id/orders/:uuid\r\n */\r\nexport const normalizePath = (path: string): string => {\r\n if (!path || path === '/') return '/';\r\n\r\n return path\r\n // Replace UUIDs (long alphanumeric strings)\r\n .replace(\r\n /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g,\r\n ':uuid'\r\n )\r\n // Replace MongoDB ObjectIds (24 hex chars)\r\n .replace(/[0-9a-fA-F]{24}/g, ':objectId')\r\n // Replace pure numeric IDs (e.g., /123)\r\n .replace(/\\/(\\d+)(?=\\/|$)/g, '/:id')\r\n // Remove query strings\r\n .split('?')[0];\r\n};\r\n\r\n/**\r\n * Tries to extract route from Framework internals, falls back to heuristic\r\n */\r\nexport const getRoute = (req: any, fallbackPath: string): string => {\r\n // Express / Connect\r\n if (req.route && req.route.path) {\r\n return (req.baseUrl || '') + req.route.path;\r\n }\r\n\r\n // H3 / Nitro (Nuxt)\r\n if (req.context && req.context.matchedRoute) {\r\n return req.context.matchedRoute.path;\r\n }\r\n\r\n // Fastify\r\n if (req.routerPath) {\r\n return req.routerPath;\r\n }\r\n\r\n // Fallback: Heuristic Normalization\r\n return normalizePath(fallbackPath);\r\n};","import { client } from '../core/client';\r\nimport { getRoute } from '../core/normalizer';\r\n\r\ntype EventHandler = (event: any) => any;\r\n\r\nexport const wrapH3 = (handler: EventHandler) => {\r\n return (event: any) => {\r\n const req = event.node.req;\r\n const path = req.originalUrl || req.url || '/';\r\n\r\n return client.startTrace({\r\n method: req.method || 'GET',\r\n path: path,\r\n ip: req.headers['x-forwarded-for'] || req.socket?.remoteAddress,\r\n userAgent: req.headers['user-agent'],\r\n headers: req.headers // Pass headers\r\n }, async () => {\r\n try {\r\n const response = await handler(event);\r\n let status = 200;\r\n if (event.node.res.statusCode) status = event.node.res.statusCode;\r\n if (response && response.statusCode) status = response.statusCode;\r\n\r\n client.endTrace(status, { route: getRoute(event, path) });\r\n return response;\r\n } catch (err: any) {\r\n client.captureError(err);\r\n const status = err.statusCode || err.status || 500;\r\n client.endTrace(status, { route: getRoute(event, path) });\r\n throw err;\r\n }\r\n });\r\n };\r\n};","import { client } from '../core/client';\r\nimport { normalizePath } from '../core/normalizer';\r\n\r\n// --- App Router Wrapper ---\r\nexport const wrapNextRoute = (handler: Function) => {\r\n return async (req: Request | any, context?: any) => {\r\n\r\n // Extract info from Web Standard Request\r\n const url = req.url ? new URL(req.url) : { pathname: '/' };\r\n const method = req.method || 'GET';\r\n\r\n // Header Extraction\r\n let headers: Record<string, string> = {};\r\n let ua: string | undefined;\r\n let ip: string | undefined;\r\n\r\n if (typeof req.headers.get === 'function') {\r\n // It's a Web Request Object\r\n ua = req.headers.get('user-agent');\r\n ip = req.headers.get('x-forwarded-for');\r\n\r\n // Convert to plain object for trace context extraction\r\n req.headers.forEach((value: string, key: string) => {\r\n headers[key] = value;\r\n });\r\n } else {\r\n // It's a Node Request Object (rare in App router but possible)\r\n headers = req.headers;\r\n ua = headers['user-agent'];\r\n ip = headers['x-forwarded-for'] as string;\r\n }\r\n\r\n return client.startTrace({\r\n method,\r\n path: url.pathname,\r\n userAgent: ua,\r\n ip: ip,\r\n headers: headers // Pass extracted headers\r\n }, async () => {\r\n try {\r\n const response = await handler(req, context);\r\n const status = response?.status || 200;\r\n\r\n client.endTrace(status, { route: normalizePath(url.pathname) });\r\n return response;\r\n } catch (err: any) {\r\n client.captureError(err);\r\n client.endTrace(500, { route: normalizePath(url.pathname) });\r\n throw err;\r\n }\r\n });\r\n };\r\n};\r\n\r\n// --- Pages Router Wrapper ---\r\nexport const wrapNextPages = (handler: Function) => {\r\n return async (req: any, res: any) => {\r\n const path = req.url ? req.url.split('?')[0] : '/';\r\n\r\n return client.startTrace({\r\n method: req.method || 'GET',\r\n path: path,\r\n userAgent: req.headers['user-agent'],\r\n ip: req.headers['x-forwarded-for'] || req.socket?.remoteAddress,\r\n headers: req.headers // Standard Node headers work fine\r\n }, async () => {\r\n\r\n const done = () => {\r\n client.endTrace(res.statusCode || 200, { route: normalizePath(path) });\r\n };\r\n\r\n res.once('finish', done);\r\n res.once('close', done);\r\n\r\n try {\r\n return await handler(req, res);\r\n } catch (e: any) {\r\n client.captureError(e);\r\n throw e;\r\n }\r\n });\r\n };\r\n};","import { client } from '../core/client';\r\nimport { SenzorOptions } from '../core/types';\r\n\r\nexport const senzorPlugin = (fastify: any, options: SenzorOptions, done: Function) => {\r\n if (options && options.apiKey) {\r\n client.init(options);\r\n }\r\n\r\n fastify.addHook('onRequest', (request: any, reply: any, next: Function) => {\r\n client.startTrace({\r\n method: request.method,\r\n path: request.raw.url || request.url,\r\n ip: request.ip,\r\n userAgent: request.headers['user-agent'],\r\n headers: request.headers // Pass headers\r\n }, () => next());\r\n });\r\n\r\n fastify.addHook('onError', (request: any, reply: any, error: any, next: Function) => {\r\n client.captureError(error);\r\n next();\r\n });\r\n\r\n fastify.addHook('onResponse', (request: any, reply: any, next: Function) => {\r\n const route = request.routeOptions?.url || request.routerPath || 'UNKNOWN';\r\n client.endTrace(reply.statusCode, { route });\r\n next();\r\n });\r\n\r\n done();\r\n};","import { client } from './core/client';\r\nimport { expressMiddleware, expressErrorHandler } from './middleware/express';\r\nimport { wrapH3 } from './wrappers/h3';\r\nimport { wrapNextRoute, wrapNextPages } from './wrappers/next';\r\nimport { senzorPlugin } from './wrappers/fastify';\r\nimport { SenzorOptions } from './core/types';\r\n\r\nconst Senzor = {\r\n init: (options: SenzorOptions) => client.init(options),\r\n flush: () => client.flush(),\r\n track: client.track.bind(client),\r\n startSpan: client.startSpan.bind(client),\r\n captureException: client.captureError.bind(client),\r\n\r\n // Task Monitoring (NEW)\r\n wrapTask: client.wrapTask.bind(client),\r\n startTask: client.startTask.bind(client),\r\n\r\n // Express\r\n requestHandler: expressMiddleware,\r\n errorHandler: expressErrorHandler,\r\n\r\n // Next\r\n wrapNextRoute,\r\n wrapNextPages,\r\n\r\n // H3\r\n wrapH3,\r\n\r\n // Fastify\r\n fastifyPlugin: senzorPlugin\r\n};\r\n\r\nexport default Senzor;\r\nexport { Senzor };"],"mappings":"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","names":["Transport","config","baseEndpoint","trace","task","error","type","log","totalApm","totalTask","apmPayload","taskPayload","headers","promises","err","import_async_hooks","storage","Context","trace","fn","span","store","import_crypto","import_http","import_https","import_url","import_crypto","TRACEPARENT_REGEX","parseTraceparent","header","traceparent","match","traceId","parentSpanId","flags","sampled","generateTraceparent","spanId","shimmer","module","methodName","wrapper","original","generateSpanId","instrumentFetch","ingestUrl","debug","ingestHost","originalFetch","input","init","urlStr","trace","Context","method","startTime","spanStartAbs","spanId","hostname","newInit","setHeader","key","value","generateTraceparent","response","duration","err","instrumentHttp","requestWrapper","args","options","optionsIndex","protocol","host","path","req","captureSpan","res","error","http","https","instrumentMongo","debug","mongodb","Collection","FindCursor","AggregationCursor","recordSpan","name","operation","collection","startAbs","traceStart","err","duration","Context","method","original","args","trace","spanStartAbs","collName","result","res","patchCursor","CursorClass","label","originalToArray","onSuccess","onError","e","instrumentPg","pg","originalQuery","args","trace","Context","startTime","spanStartAbs","sql","result","res","duration","import_module","SENZOR_PATCHED","SENZOR_HOOKS","getHookRegistry","mod","Module","runHooks","moduleName","exports","registry","hooks","hook","err","patchLoaderOnce","previousLoad","request","parent","isMain","patchCached","resolved","__require","cached","tryRequire","retryPatch","attempts","max","timer","hookRequire","onRequire","PATCHED","patchWorker","target","client","debug","proto","original","job","queueDelay","currentAttempt","maxAttempts","isFinal","taskName","result","error","ctx","Context","instrumentBullMQ","hookRequire","exports","PATCHED","normalizeOptions","options","patchTarget","target","client","debug","schedule","original","wrapped","expression","handler","opts","taskName","wrappedHandler","err","instrumentNodeCron","hookRequire","exports","package_default","SDK_META","package_default","generateW3CTraceId","safeStringify","obj","cache","key","value","SenzorClient","options","endpoint","debug","Transport","instrumentHttp","instrumentFetch","instrumentMongo","instrumentPg","instrumentBullMQ","instrumentNodeCron","levels","originalConsole","isIntercepting","level","args","message","attributes","arg","parsed","currentTrace","Context","logType","logPayload","getProcessContext","getMemoryContext","mem","safeCapture","error","meta","parsedError","enrichedMeta","SDK_META","internalFailure","reason","warning","type","promise","data","next","inheritedTraceId","inheritedParentSpanId","getHeader","traceparent","parsedContext","parseTraceparent","rawTrace","rawSpan","trace","status","extraData","duration","payload","name","currentContext","triggerTraceId","startMemory","startCpu","task","extraMetadata","resourceMetrics","endMemory","cpuDelta","fn","result","context","errPayload","startTime","spanStartAbs","spanId","client","expressMiddleware","req","res","next","client","route","expressErrorHandler","err","normalizePath","path","getRoute","req","fallbackPath","wrapH3","handler","event","req","path","client","response","status","getRoute","err","wrapNextRoute","handler","req","context","url","method","headers","ua","ip","value","key","client","response","status","normalizePath","err","wrapNextPages","res","path","done","e","senzorPlugin","fastify","options","done","client","request","reply","next","error","route","Senzor","options","client","expressMiddleware","expressErrorHandler","wrapNextRoute","wrapNextPages","wrapH3","senzorPlugin","index_default"]}
|