@senzops/apm-node 1.1.18 → 1.2.0
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 +4 -0
- package/README.md +386 -48
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -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/dist/register.d.mts +2 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.js +2 -0
- package/dist/register.js.map +1 -0
- package/dist/register.mjs +2 -0
- package/dist/register.mjs.map +1 -0
- package/package.json +15 -4
- package/src/core/client.ts +159 -105
- package/src/core/context.ts +48 -21
- package/src/core/sanitizer.ts +203 -0
- package/src/core/transport.ts +273 -104
- package/src/core/types.ts +38 -24
- package/src/index.ts +5 -4
- package/src/instrumentation/http.ts +530 -162
- package/src/instrumentation/mongo.ts +202 -105
- package/src/instrumentation/mongoose.ts +156 -0
- package/src/instrumentation/mysql.ts +169 -0
- package/src/instrumentation/patch.ts +56 -0
- package/src/instrumentation/pg.ts +131 -41
- package/src/instrumentation/redis.ts +109 -0
- package/src/instrumentation/span.ts +73 -0
- package/src/instrumentation/undici.ts +189 -0
- package/src/register.ts +42 -0
- package/src/utils/ids.ts +7 -0
- package/src/utils/internal.ts +1 -0
- package/tsup.config.ts +21 -11
- package/wiki.md +844 -120
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var L=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var w="x-senzor-sdk-internal";var $=class{constructor(e){this.config=e;this.traceQueue=[];this.apmErrorQueue=[];this.apmLogQueue=[];this.taskQueue=[];this.taskErrorQueue=[];this.taskLogQueue=[];this.timer=null;this.isFlushing=!1;this.flushAgain=!1;this.droppedItems=0;let r=e.endpoint||"https://api.senzor.dev";this.apmEndpoint=r.includes("/api/ingest")?r:`${r}/api/ingest/apm`,this.taskEndpoint=r.includes("/api/ingest")?r.replace("/apm","/task"):`${r}/api/ingest/task`,typeof setInterval<"u"&&(this.timer=setInterval(()=>{this.flush()},e.flushInterval||1e4),this.timer&&typeof this.timer.unref=="function"&&this.timer.unref()),this.installShutdownFlush()}addTrace(e){this.enqueue(this.traceQueue,e),this.checkFlush()}addTask(e){this.enqueue(this.taskQueue,e),this.checkFlush()}addError(e,r="apm"){this.enqueue(r==="task"?this.taskErrorQueue:this.apmErrorQueue,e),this.checkFlush()}addLog(e,r="apm"){this.enqueue(r==="task"?this.taskLogQueue:this.apmLogQueue,e),this.checkFlush()}enqueue(e,r){e.push(r);let n=this.config.maxQueueSize??1e4;for(;e.length>n;)e.shift(),this.droppedItems++}prependWithLimit(e,r){if(!r.length)return;e.unshift(...r);let n=this.config.maxQueueSize??1e4;for(;e.length>n;)e.pop(),this.droppedItems++}checkFlush(){let e=this.traceQueue.length+this.apmErrorQueue.length+this.apmLogQueue.length,r=this.taskQueue.length+this.taskErrorQueue.length+this.taskLogQueue.length;(e>=(this.config.batchSize||100)||r>=(this.config.batchSize||100))&&this.flush()}takeApmPayload(){let e={traces:this.traceQueue,errors:this.apmErrorQueue,logs:this.apmLogQueue};return this.traceQueue=[],this.apmErrorQueue=[],this.apmLogQueue=[],e}takeTaskPayload(){let e={runs:this.taskQueue,errors:this.taskErrorQueue,logs:this.taskLogQueue};return this.taskQueue=[],this.taskErrorQueue=[],this.taskLogQueue=[],e}restoreApmPayload(e){this.prependWithLimit(this.apmLogQueue,e.logs),this.prependWithLimit(this.apmErrorQueue,e.errors),this.prependWithLimit(this.traceQueue,e.traces)}restoreTaskPayload(e){this.prependWithLimit(this.taskLogQueue,e.logs),this.prependWithLimit(this.taskErrorQueue,e.errors),this.prependWithLimit(this.taskQueue,e.runs)}hasApmPayload(e){return e.traces.length>0||e.errors.length>0||e.logs.length>0}hasTaskPayload(e){return e.runs.length>0||e.errors.length>0||e.logs.length>0}async postJson(e,r){let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.flushTimeoutMs??5e3);typeof o.unref=="function"&&o.unref();try{let a=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","x-service-api-key":this.config.apiKey,[w]:"true"},body:JSON.stringify(r),keepalive:!0,signal:n.signal});if(!a.ok)throw new Error(`Senzor ingest failed with status ${a.status}`)}finally{clearTimeout(o)}}async flush(){if(this.isFlushing){this.flushAgain=!0;return}this.isFlushing=!0;try{do{this.flushAgain=!1;let e=this.takeApmPayload(),r=this.takeTaskPayload(),n=[];if(this.hasApmPayload(e)&&n.push(this.postJson(this.apmEndpoint,e).catch(s=>{throw this.restoreApmPayload(e),s})),this.hasTaskPayload(r)&&n.push(this.postJson(this.taskEndpoint,r).catch(s=>{throw this.restoreTaskPayload(r),s})),!n.length)continue;let a=(await Promise.allSettled(n)).filter(s=>s.status==="rejected");this.config.debug&&console.log(`[Senzor] Flushed: APM(${e.traces.length} traces, ${e.logs.length} logs), Task(${r.runs.length} runs, ${r.logs.length} logs), failures=${a.length}, dropped=${this.droppedItems}`)}while(this.flushAgain)}catch(e){this.config.debug&&console.error("[Senzor] Transport Flush Error:",e)}finally{this.isFlushing=!1}}installShutdownFlush(){let e=Symbol.for("senzor.transport.shutdownFlushInstalled"),r=process;if(r[e])return;Object.defineProperty(r,e,{value:!0,enumerable:!1});let n=()=>{this.flush()};process.once("beforeExit",n)}};import{AsyncLocalStorage as De}from"async_hooks";var v=new De,y={run:(t,e)=>v.run(t,e),withActiveSpan:(t,e)=>{let r=v.getStore();return r?v.run({...r,activeSpanId:t,data:r.data,spans:r.spans},e):e()},current:()=>v.getStore(),addSpan:t=>{let e=v.getStore();e&&y.addSpanToTrace(e,t)},addSpanToTrace:(t,e)=>{if(t.ended)return;let r=t.maxSpans??500;if(t.spans.length>=r){t.droppedSpans=(t.droppedSpans??0)+1;return}t.spans.push(e)}};import{randomUUID as Pt}from"crypto";import de from"http";import le from"https";import{URL as C}from"url";var A=t=>!t||t==="/"?"/":t.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],re=(t,e)=>t.route&&t.route.path?(t.baseUrl||"")+t.route.path:t.context&&t.context.matchedRoute?t.context.matchedRoute.path:t.routerPath?t.routerPath:A(e);var Qe=64,W=2048,je=4,We=20,Ze=/(^|[-_.])(authorization|cookie|set-cookie|password|passwd|pwd|secret|token|api[-_.]?key|x-api-key|access[-_.]?token|refresh[-_.]?token|client[-_.]?secret|private[-_.]?key)([-_.]|$)/i,Ke=t=>({maxAttributes:t?.maxAttributes??Qe,maxAttributeLength:t?.maxAttributeLength??W}),z=(t,e=W)=>t.length<=e?t:`${t.slice(0,Math.max(0,e-15))}...[truncated]`,Ge=t=>Ze.test(t),Be=(t,e)=>{if(t==null||typeof t=="number"||typeof t=="boolean")return t;if(typeof t=="bigint")return t.toString();if(typeof t=="string")return z(t,e)},j=(t,e,r,n)=>{if(Ge(t))return"[REDACTED]";let o=Be(e,r.maxAttributeLength);if(o!==void 0||e===void 0)return o;if(e instanceof Error)return{name:z(e.name,r.maxAttributeLength),message:z(e.message,r.maxAttributeLength),stack:e.stack?z(e.stack,r.maxAttributeLength):void 0};if(n>=je)return"[MaxDepth]";if(Array.isArray(e))return e.slice(0,We).map(a=>j(t,a,r,n+1));if(typeof e=="object"){let a={},s=0;for(let[p,c]of Object.entries(e)){if(s>=r.maxAttributes){a.__truncated=!0;break}a[p]=j(p,c,r,n+1),s++}return a}return z(String(e),r.maxAttributeLength)},x=(t={},e)=>{let r=Ke(e),n={maxAttributes:r.maxAttributes,maxAttributeLength:r.maxAttributeLength},o={},a=0;for(let[s,p]of Object.entries(t)){if(a>=n.maxAttributes){o.__truncated=!0;break}o[s]=j(s,p,n,0),a++}return o},ne=(t,e)=>{if(!t||typeof t!="object")return{};let r={};if(typeof t.forEach=="function")t.forEach((n,o)=>{r[o.toLowerCase()]=n});else for(let[n,o]of Object.entries(t))r[n.toLowerCase()]=Array.isArray(o)?o.join(", "):o;return x(r,e)},I=(t,e)=>{if(typeof t!="string")return;let r=t.replace(/\s+/g," ").trim();if(!r)return;let n=r.replace(/'(?:''|[^'])*'/g,"?").replace(/"(?:\\"|[^"])*"/g,"?").replace(/\b\d+(\.\d+)?\b/g,"?");return z(e?.captureDbStatement===!1?n.split(" ").slice(0,6).join(" "):n,e?.maxAttributeLength??W)},H=t=>typeof t!="string"?void 0:t.trim().match(/^([a-z]+)/i)?.[1]?.toUpperCase();import{isIP as oe}from"net";var Ve=t=>t.startsWith("::ffff:")?t.slice(7):t,Je=t=>{let e=t.lastIndexOf(":");if(e===-1)return t;let r=t.slice(0,e);return oe(r)===4?r:t},Xe=t=>{let e=t.match(/^\[([^\]]+)\](?::\d+)?$/);return e?e[1]:t},T=t=>{if(!t)return null;let e=t.trim();return e?(e=Xe(e),e=Je(e),e=Ve(e),oe(e)!==0?e:null):null},se=t=>!!(t==="127.0.0.1"||t.startsWith("10.")||t.startsWith("192.168.")||t.startsWith("169.254.")||/^172\.(1[6-9]|2\d|3[01])\./.test(t)||t==="::1"||t==="::"||t.toLowerCase().startsWith("fe80:")||t.toLowerCase().startsWith("fc")||t.toLowerCase().startsWith("fd")),Ye=t=>{let e=t.split(",");for(let r of e){let n=r.match(/for=["[]?([^\]",;>\s]+)/i);if(n){let o=T(n[1]);if(o&&!se(o))return o}}return null},et=t=>{let e=t.split(",").map(r=>r.trim());for(let r of e){let n=T(r);if(n&&!se(n))return n}for(let r of e){let n=T(r);if(n)return n}return null},ae=t=>{let e=t.headers;{let r=T(e["cf-connecting-ip"]);if(r)return r}{let r=T(e["true-client-ip"]);if(r)return r}{let r=T(e["x-real-ip"]);if(r)return r}{let r=e.forwarded;if(r){let n=Ye(r);if(n)return n}}{let r=e["x-forwarded-for"];if(r){let n=et(r);if(n)return n}}{let r=t.socket?.remoteAddress,n=T(r);if(n)return n}return null};var tt=/^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/,ie=t=>{if(!t)return null;let e=Array.isArray(t)?t[0]:t;if(typeof e!="string")return null;let r=e.trim().toLowerCase().match(tt);if(!r)return null;let n=r[1],o=r[2],a=r[3];if(n==="00000000000000000000000000000000"||o==="0000000000000000")return null;let s=(parseInt(a,16)&1)===1;return{traceId:n,parentSpanId:o,sampled:s}},O=(t,e,r=!0)=>`00-${t}-${e}-${r?"01":"00"}`;var ce=Symbol.for("senzor.patch.keys"),pe=Symbol.for("senzor.patch.original"),g=(t,e,r,n)=>{if(!t)return!1;let o=t[e];if(typeof o!="function")return!1;let a=o[ce];if(a?.has(r))return!1;let s=o[pe]||o,p=n(o),c=new Set(a||[]);c.add(r);try{Object.defineProperty(p,ce,{value:c,enumerable:!1}),Object.defineProperty(p,pe,{value:s,enumerable:!1})}catch{return!1}try{return t[e]=p,!0}catch{return!1}};import{randomUUID as ue}from"crypto";var Z=()=>ue().replace(/-/g,""),_=()=>ue().replace(/-/g,"").slice(0,16);var k=(t,e,r={},n)=>{let o=y.current();if(!o)return null;let a=_(),s=o.activeSpanId,p=performance.now()-o.startTime,c=performance.now(),i=!1;return{spanId:a,parentSpanId:s,trace:o,end:(d,u={})=>{if(i)return;i=!0;let l=x({...r,...u,parentSpanId:s},n);y.addSpanToTrace(o,{spanId:a,parentSpanId:s,name:t,type:e,startTime:p,duration:performance.now()-c,status:d,meta:l})}}},E=(t,e)=>t?y.withActiveSpan(t.spanId,e):e();var rt=t=>!!t?.debug,fe=t=>typeof t=="object"&&t!==null&&!(t instanceof C)&&!(t instanceof Function)&&!Array.isArray(t),nt=(t,e)=>{if(t){if(typeof Headers<"u"&&t instanceof Headers)return t.get(e);if(Array.isArray(t))return t.find(([n])=>String(n).toLowerCase()===e.toLowerCase())?.[1];if(typeof t=="object"){let r=e.toLowerCase();for(let[n,o]of Object.entries(t))if(n.toLowerCase()===r)return o}}},ye=t=>String(nt(t,w)||"").toLowerCase()==="true",ge=(t,e,r)=>{if(ye(r))return!0;if(!t)return!1;try{let n=new C(t),o=new C(e);return n.hostname===o.hostname&&n.pathname.startsWith("/api/ingest")}catch{return e?t.includes(e):!1}},K=t=>{if(!t)return{};if(typeof Headers<"u"&&t instanceof Headers){let e={};return t.forEach((r,n)=>{e[n]=r}),e}return Array.isArray(t)?t.reduce((e,[r,n])=>(e[r]=n,e),{}):typeof t=="object"?{...t}:{}},R=(t,e,r)=>{let n=Object.keys(t).find(o=>o.toLowerCase()===e.toLowerCase());t[n||e]=r},ot=(t,e)=>{let r=[...t],n=0,o={},a=null;if(typeof r[0]=="string"||r[0]instanceof C){try{a=new C(r[0].toString())}catch{a=null}fe(r[1])?(n=1,o={...r[1],headers:K(r[1].headers)},r[1]=o):(n=1,o={headers:{}},r.splice(1,0,o))}else fe(r[0])?(n=0,o={...r[0],headers:K(r[0].headers)},r[0]=o):(n=0,o={headers:{}},r[0]=o);o.headers||(o.headers={}),r[n]=o;let s=o.protocol||a?.protocol||(o.port===443?"https:":e),p=o.hostname||o.host||a?.hostname||"localhost",c=o.path||`${a?.pathname||"/"}${a?.search||""}`,i=a?a.toString():`${s}//${p}${c}`,d=String(o.method||"GET").toUpperCase();return{args:r,options:o,url:i,method:d,hostname:String(p).replace(/:\d+$/,""),path:c}},st=(t,e,r)=>{if(e?.statusCode===404)return"Not Found";try{return re(t,r)}catch{return A(r)}},he=(t,e,r,n)=>{g(t,"emit",`senzor.${e}.server`,o=>function(s,...p){if(s!=="request")return o.call(this,s,...p);let c=p[0],i=p[1];if(!c||!i||y.current()?.contextType==="apm")return o.call(this,s,...p);let d=c.originalUrl||c.url||"/",u=String(d).split("?")[0]||"/",l=c.headers||{};return ye(l)?o.call(this,s,...p):r.startTrace({method:c.method||"GET",path:d,route:A(u),ip:ae(c),userAgent:l["user-agent"],headers:l,meta:{protocol:e,httpVersion:c.httpVersion,headers:n?.captureHeaders?ne(l,n):void 0}},()=>{let h=y.current(),m=!1,f=S=>{m||!h||(m=!0,setImmediate(()=>{h.ended||y.run(h,()=>{r.endTrace(i.statusCode||0,{route:st(c,i,u),statusMessage:i.statusMessage,meta:{...h.data.meta,endReason:S}})})}))};i.once("finish",()=>f("finish")),i.once("close",()=>f("close")),i.once("error",S=>{r.captureError(S,{instrumentation:`${e}.server`}),f("error")});try{return o.call(this,s,...p)}catch(S){throw r.captureError(S,{instrumentation:`${e}.server`}),f("error"),S}})})},me=(t,e,r,n)=>{let o=e==="https:"?"senzor.https":"senzor.http",a=s=>function(...c){let i=ot(c,e);if(ge(i.url,r,i.options.headers))return s.apply(this,c);let d=y.current();if(!d)return s.apply(this,c);let u=k(`${i.method} ${i.hostname}`,"http",{url:i.url,method:i.method,library:e==="https:"?"https":"http","http.request.method":i.method,"url.full":i.url,"url.path":i.path,"server.address":i.hostname},n);u&&(R(i.options.headers,"traceparent",O(d.id,u.spanId)),R(i.options.headers,"x-senzor-trace-id",d.id),R(i.options.headers,"x-senzor-parent-span-id",u.spanId));let l=()=>{let h=s.apply(this,i.args);if(!u||!h||typeof h.once!="function")return h;let m=!1,f=(S,q={})=>{m||(m=!0,u.end(S,q))};return h.once("response",S=>{let q=S?.statusCode||0,ee=()=>f(q,{"http.response.status_code":q});S.once("end",ee),S.once("close",ee),S.once("error",te=>f(500,{error:te.message,"error.type":te.name}))}),h.once("timeout",()=>f(504,{error:"Request timed out","error.type":"TimeoutError"})),h.once("error",S=>f(500,{error:S.message,"error.type":S.name})),h};return rt(n)&&console.log(`[Senzor] Injecting trace headers to ${i.url}`),E(u,l)};g(t,"request",`${o}.request`,a),g(t,"get",`${o}.get`,a)},Se=(t,e)=>{globalThis.fetch&&g(globalThis,"fetch","senzor.fetch",r=>async function(o,a){let s=typeof o=="string"?o:o instanceof C?o.toString():o?.url||"",p=a?.headers||o?.headers;if(ge(s,t,p))return r.call(this,o,a);let c=y.current();if(!c)return r.call(this,o,a);let i="unknown",d="/";try{let f=new C(s);i=f.hostname,d=`${f.pathname}${f.search}`}catch{}let u=String(a?.method||o?.method||"GET").toUpperCase(),l=k(`${u} ${i}`,"http",{url:s,method:u,library:"fetch","http.request.method":u,"url.full":s,"url.path":d,"server.address":i},e);if(!l)return r.call(this,o,a);let h={...a||{}},m=typeof Headers<"u"?new Headers(p||void 0):K(p);return typeof Headers<"u"&&m instanceof Headers?(m.set("traceparent",O(c.id,l.spanId)),m.set("x-senzor-trace-id",c.id),m.set("x-senzor-parent-span-id",l.spanId)):(R(m,"traceparent",O(c.id,l.spanId)),R(m,"x-senzor-trace-id",c.id),R(m,"x-senzor-parent-span-id",l.spanId)),h.headers=m,E(l,async()=>{try{let f=await r.call(this,o,h);return l.end(f.status,{"http.response.status_code":f.status}),f}catch(f){throw l.end(500,{error:f?.message,"error.type":f?.name||"Error"}),f}})})},ke=(t,e,r)=>{he(de.Server?.prototype,"http",t,r),he(le.Server?.prototype,"https",t,r),me(de,"http:",e,r),me(le,"https:",e,r)};import G from"module";var be=Symbol.for("senzor.require.patched"),F=Symbol.for("senzor.require.hooks");function at(){let t=G;return t[F]||Object.defineProperty(t,F,{value:new Map,enumerable:!1}),t[F]}function it(t,e){let r=G[F];if(!r)return;let n=r.get(t);if(n?.length)for(let o of n)try{o(e)}catch(a){console.error(`[Senzor] instrumentation failed for ${t}`,a)}}function ct(){let t=G;if(t[be])return;let e=t._load;t._load=function(n,o,a){let s=e.apply(this,arguments);return it(n,s),s},Object.defineProperty(t,be,{value:!0,enumerable:!1})}function pt(t,e){try{let r=L.resolve(t),n=L.cache?.[r];n?.exports&&e(n.exports)}catch{}}function ut(t,e){try{let r=L(t);r&&e(r)}catch{}}function dt(t,e){let r=0,n=5,o=setInterval(()=>{r++;try{let a=L(t);a&&(e(a),clearInterval(o))}catch{}r>=n&&clearInterval(o)},200)}var b=(t,e)=>{let r=at();r.has(t)||r.set(t,[]),r.get(t).push(e),ct(),pt(t,e),ut(t,e),dt(t,e)};var lt=t=>t?.collectionName||t?.s?.namespace?.collection||t?.namespace?.collection||"unknown",Ee=t=>t?.dbName||t?.s?.namespace?.db||t?.namespace?.db,ft=t=>t?.namespace?.collection||t?.ns?.collection||t?.cursorNamespace?.collection||"unknown",ht=(t,e,r)=>{g(t,e,`senzor.mongodb.collection.${e}`,n=>function(...a){let s=lt(this),p=k(`MongoDB ${e}`,"db",{collection:s,operation:e,"db.system.name":"mongodb","db.collection.name":s,"db.namespace":Ee(this)?`${Ee(this)}.${s}`:s,"db.operation.name":e,library:"mongodb"},r);return p?E(p,()=>{try{let c=n.apply(this,a);return c&&typeof c.then=="function"?c.then(i=>(p.end(0,{matchedCount:i?.matchedCount,modifiedCount:i?.modifiedCount,deletedCount:i?.deletedCount,insertedCount:i?.insertedCount}),i),i=>{throw p.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}):(p.end(0),c)}catch(c){throw p.end(500,{error:c?.message,"error.type":c?.name||"Error"}),c}}):n.apply(this,a)})},we=(t,e,r,n)=>{g(t,e,`senzor.mongodb.cursor.${r}.${e}`,o=>function(...s){let p=ft(this),c=k(`MongoDB ${r}`,"db",{collection:p,operation:r,"db.system.name":"mongodb","db.collection.name":p,"db.operation.name":r,library:"mongodb"},n);return c?E(c,()=>{try{let i=o.apply(this,s);return i&&typeof i.then=="function"?i.then(d=>(c.end(0,{resultCount:Array.isArray(d)?d.length:void 0}),d),d=>{throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}):(c.end(0),i)}catch(i){throw c.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}}):o.apply(this,s)})},mt=(t,e)=>{let n=(t?.Collection||t?.default?.Collection)?.prototype;["insertOne","insertMany","updateOne","updateMany","replaceOne","deleteOne","deleteMany","findOne","findOneAndUpdate","findOneAndDelete","findOneAndReplace","countDocuments","estimatedDocumentCount","distinct","bulkWrite","createIndex","dropIndex"].forEach(s=>ht(n,s,e));let o=t?.FindCursor||t?.default?.FindCursor,a=t?.AggregationCursor||t?.default?.AggregationCursor;["toArray","next","forEach"].forEach(s=>we(o?.prototype,s,"find",e)),["toArray","next","forEach"].forEach(s=>we(a?.prototype,s,"aggregate",e))},Te=t=>{b("mongodb",e=>mt(e,t))};var yt=t=>{let e=t[0];if(typeof e=="string")return e;if(e&&typeof e.text=="string")return e.text},U=(t,e,r)=>{g(t,"query",`senzor.pg.${e}.query`,n=>function(...a){let s=yt(a),p=H(s)||"QUERY",c=k(`Postgres ${p}`,"db",{query:I(s,r),operation:p,"db.system.name":"postgresql","db.operation.name":p,"db.query.text":I(s,r),library:"pg"},r);if(!c)return n.apply(this,a);let i=a.findIndex(d=>typeof d=="function");if(i>=0){let d=a[i];a[i]=function(l,h){return c.end(l?500:0,{error:l?.message,"error.type":l?.name,rowCount:h?.rowCount,"db.response.row_count":h?.rowCount}),d.apply(this,arguments)}}return E(c,()=>{try{let d=n.apply(this,a);return d&&typeof d.then=="function"?d.then(u=>(c.end(0,{rowCount:u?.rowCount,"db.response.row_count":u?.rowCount}),u),u=>{throw c.end(500,{error:u?.message,"error.type":u?.name||"Error"}),u}):(i<0&&d&&typeof d.once=="function"?(d.once("end",()=>c.end(0)),d.once("error",u=>c.end(500,{error:u.message,"error.type":u.name}))):i<0&&c.end(0),d)}catch(d){throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}})})},gt=(t,e)=>{t&&(U(t.Client?.prototype,"client",e),U(t.Pool?.prototype,"pool",e),t.default&&(U(t.default.Client?.prototype,"default.client",e),U(t.default.Pool?.prototype,"default.pool",e)))},Ce=t=>{b("pg",e=>gt(e,t))};var St=t=>t?Array.isArray(t)?t.some(([e,r])=>String(e).toLowerCase()===w&&String(r).toLowerCase()==="true"):Object.entries(t).some(([e,r])=>e.toLowerCase()===w&&String(r).toLowerCase()==="true"):!1,B=(t,e,r)=>{if(Array.isArray(t))return t.push([e,r]),t;let n={...t||{}},o=Object.keys(n).find(a=>a.toLowerCase()===e.toLowerCase());return n[o||e]=r,n},kt=t=>{try{let e=new URL(String(t));return{url:e.toString(),hostname:e.hostname,path:`${e.pathname}${e.search}`}}catch{return{url:String(t||""),hostname:"unknown",path:"/"}}},D=(t,e,r,n)=>{g(t,e,r,o=>function(s,p,c){if(St(p?.headers))return o.apply(this,arguments);let i=kt(s?.origin?s.origin:s),d=String(p?.method||"GET").toUpperCase(),u=k(`${d} ${i.hostname}`,"http",{url:i.url,method:d,route:A(i.path),library:"undici","http.request.method":d,"url.full":i.url,"url.path":i.path,"server.address":i.hostname},n);if(!u)return o.apply(this,arguments);let l={...p||{}};l.headers=B(l.headers,"traceparent",O(u.trace.id,u.spanId)),l.headers=B(l.headers,"x-senzor-trace-id",u.trace.id),l.headers=B(l.headers,"x-senzor-parent-span-id",u.spanId);let h=typeof c=="function"?function(f,S){return u.end(f?500:S?.statusCode||0,{error:f?.message,"error.type":f?.name,"http.response.status_code":S?.statusCode}),c.apply(this,arguments)}:c;return E(u,()=>{try{let m=o.call(this,s,l,h);return m&&typeof m.then=="function"?m.then(f=>(u.end(f?.statusCode||f?.status||0,{"http.response.status_code":f?.statusCode||f?.status}),f),f=>{throw u.end(500,{error:f?.message,"error.type":f?.name||"Error"}),f}):(typeof h!="function"&&u.end(0),m)}catch(m){throw u.end(500,{error:m?.message,"error.type":m?.name||"Error"}),m}})})},bt=(t,e)=>{D(t,"request","senzor.undici.request",e),D(t,"stream","senzor.undici.stream",e),D(t,"pipeline","senzor.undici.pipeline",e),[t?.Client?.prototype,t?.Pool?.prototype,t?.Agent?.prototype,t?.ProxyAgent?.prototype].forEach((r,n)=>{D(r,"request",`senzor.undici.dispatcher.${n}.request`,e)})},Ae=t=>{b("undici",e=>bt(e,t))};var Et=t=>typeof t=="string"?t.toUpperCase():Array.isArray(t)?String(t[0]||"COMMAND").toUpperCase():t?.name?String(t.name).toUpperCase():Array.isArray(t?.args)?String(t.args[0]||"COMMAND").toUpperCase():"COMMAND",P=(t,e,r)=>{g(t,"sendCommand",`senzor.redis.${e}.sendCommand`,n=>function(a,...s){let p=Et(a),c=k(`Redis ${p}`,"db",{command:p,operation:p,"db.system.name":"redis","db.operation.name":p,library:e},r);return c?E(c,()=>{try{let i=n.call(this,a,...s);return i&&typeof i.then=="function"?i.then(d=>(c.end(0),d),d=>{throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}):(c.end(0),i)}catch(i){throw c.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}}):n.apply(this,arguments)})},wt=(t,e,r)=>(P(t,e,r),P(Object.getPrototypeOf(t),e,r),t),Tt=(t,e)=>{["createClient","createCluster"].forEach(r=>{g(t,r,`senzor.redis.${r}`,n=>function(...a){let s=n.apply(this,a);return wt(s,"redis",e)})})},Ct=(t,e)=>{P(t?.prototype,"ioredis",e),P(t?.Redis?.prototype,"ioredis",e),P(t?.Cluster?.prototype,"ioredis-cluster",e),P(t?.default?.prototype,"ioredis",e)},ze=t=>{b("redis",e=>Tt(e,t)),b("ioredis",e=>Ct(e,t))};var At=t=>{let e=t[0];if(typeof e=="string")return e;if(e&&typeof e.sql=="string")return e.sql},M=(t,e,r,n)=>{g(t,e,`senzor.${r}.${e}`,o=>function(...s){let p=At(s),c=H(p)||e.toUpperCase(),i=k(`MySQL ${c}`,"db",{query:I(p,n),operation:c,"db.system.name":"mysql","db.operation.name":c,"db.query.text":I(p,n),library:r},n);if(!i)return o.apply(this,s);let d=s.findIndex(u=>typeof u=="function");if(d>=0){let u=s[d];s[d]=function(h,m){return i.end(h?500:0,{error:h?.message,"error.type":h?.name,rowCount:Array.isArray(m)?m.length:void 0}),u.apply(this,arguments)}}return E(i,()=>{try{let u=o.apply(this,s);return u&&typeof u.then=="function"?u.then(l=>{let h=Array.isArray(l)?l[0]:l;return i.end(0,{rowCount:Array.isArray(h)?h.length:void 0}),l},l=>{throw i.end(500,{error:l?.message,"error.type":l?.name||"Error"}),l}):(d<0&&u&&typeof u.once=="function"?(u.once("end",()=>i.end(0)),u.once("error",l=>i.end(500,{error:l.message,"error.type":l.name}))):d<0&&i.end(0),u)}catch(u){throw i.end(500,{error:u?.message,"error.type":u?.name||"Error"}),u}})})},zt=(t,e,r)=>{[t?.Connection?.prototype,t?.Pool?.prototype,t?.PoolConnection?.prototype,t?.PromiseConnection?.prototype,t?.PromisePool?.prototype,t?.default?.Connection?.prototype,t?.default?.Pool?.prototype].forEach(n=>{M(n,"query",e,r),M(n,"execute",e,r)})},xt=(t,e,r)=>{["createConnection","createPool"].forEach(n=>{g(t,n,`senzor.${e}.${n}`,o=>function(...s){let p=o.apply(this,s);return M(p,"query",e,r),M(p,"execute",e,r),M(Object.getPrototypeOf(p),"query",e,r),M(Object.getPrototypeOf(p),"execute",e,r),p})})},xe=(t,e,r)=>{zt(t,e,r),xt(t,e,r)},Ie=t=>{b("mysql",e=>xe(e,"mysql",t)),b("mysql2",e=>xe(e,"mysql2",t))};var Re=t=>t?.model?.modelName||t?.constructor?.modelName||t?.modelName||"unknown",Pe=t=>t?.mongooseCollection?.name||t?.collection?.name||t?.model?.collection?.name||"unknown",Q=(t,e,r)=>{g(t,"exec",`senzor.mongoose.${e}.exec`,n=>function(...a){let s=String(this?.op||this?._op||e).toUpperCase(),p=Pe(this),c=k(`Mongoose ${s}`,"db",{collection:p,model:Re(this),operation:s,"db.system.name":"mongodb","db.collection.name":p,"db.operation.name":s,library:"mongoose"},r);return c?E(c,()=>{try{let i=n.apply(this,a);return i&&typeof i.then=="function"?i.then(d=>(c.end(0,{resultCount:Array.isArray(d)?d.length:void 0}),d),d=>{throw c.end(500,{error:d?.message,"error.type":d?.name||"Error"}),d}):(c.end(0),i)}catch(i){throw c.end(500,{error:i?.message,"error.type":i?.name||"Error"}),i}}):n.apply(this,a)})},Oe=(t,e)=>{g(t,"save","senzor.mongoose.model.save",r=>function(...o){let a=Pe(this),s=k("Mongoose SAVE","db",{collection:a,model:Re(this),operation:"SAVE","db.system.name":"mongodb","db.collection.name":a,"db.operation.name":"SAVE",library:"mongoose"},e);return s?E(s,()=>{try{let p=r.apply(this,o);return p&&typeof p.then=="function"?p.then(c=>(s.end(0),c),c=>{throw s.end(500,{error:c?.message,"error.type":c?.name||"Error"}),c}):(s.end(0),p)}catch(p){throw s.end(500,{error:p?.message,"error.type":p?.name||"Error"}),p}}):r.apply(this,o)})},It=(t,e)=>{Q(t?.Query?.prototype,"query",e),Q(t?.Aggregate?.prototype,"aggregate",e),Oe(t?.Model?.prototype,e),t?.default&&(Q(t.default?.Query?.prototype,"query",e),Q(t.default?.Aggregate?.prototype,"aggregate",e),Oe(t.default?.Model?.prototype,e))},Me=t=>{b("mongoose",e=>It(e,t))};var Le=Symbol.for("senzor.bullmq.patched");function ve(t,e,r){if(!t?.Worker?.prototype)return;let n=t.Worker.prototype,o=n.processJob;typeof o!="function"||o[Le]||(n.processJob=async function(a){let s=a.timestamp?Date.now()-a.timestamp:0,p=(a.attemptsMade||0)+1,c=a.opts?.attempts??1,i=p>=c,d=a.name==="__default__"?a.queueName:`${a.queueName}:${a.name}`;return e.startTask(d,"queue",{queueDelay:s,attempts:p,isDeadLetter:!1,metadata:{jobId:a.id,queueName:a.queueName,maxAttempts:c}},async()=>{try{let u=await o.call(this,a);return e.endTask("success"),u}catch(u){try{let l=y.current();l&&l.contextType==="task"&&i&&(l.data.isDeadLetter=!0)}catch{}throw e.captureError(u,{queueName:a.queueName,jobId:a.id,isDeadLetter:i}),e.endTask("failed"),u}})},Object.defineProperty(n.processJob,Le,{value:!0}),r&&console.log("[Senzor] BullMQ instrumented"))}var _e=(t,e)=>{b("bullmq",r=>{ve(r,t,e),r?.default&&ve(r.default,t,e)})};var Ne=Symbol.for("senzor.cron.patched");function Ot(t){return typeof t=="object"&&t!==null?t:t?{timezone:t}:{}}function qe(t,e,r){let n=t.schedule;if(typeof n!="function"||n[Ne])return;let o=n,a=function(s,p,c){if(typeof p!="function")return o.call(this,s,p,c);try{let i=Ot(c),d=i?.name??`cron: ${s}`,u=e.wrapTask(d,"cron",{expression:s,metadata:i},p);return o.call(this,s,u,c)}catch(i){return r&&console.error("[Senzor] cron wrap failed",i),o.call(this,s,p,c)}};Object.defineProperty(a,Ne,{value:!0,enumerable:!1});try{t.schedule=a}catch{r&&console.warn("[Senzor] unable to patch cron schedule (readonly export)")}r&&console.log("[Senzor] node-cron instrumented")}var $e=(t,e)=>{b("node-cron",r=>{r&&(qe(r,t,e),r.default&&qe(r.default,t,e))})};var V={name:"@senzops/apm-node",version:"1.2.0",description:"Universal APM SDK for Senzor",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",require:"./dist/index.js",import:"./dist/index.mjs"},"./register":{types:"./dist/register.d.ts",require:"./dist/register.js",import:"./dist/register.mjs"}},scripts:{build:"tsup",prepublishOnly:"npm run build"},devDependencies:{"@types/node":"^20.19.41",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 J={name:V.name,version:V.version};var Mt=t=>{let e=new Set;return JSON.stringify(t,(r,n)=>{if(typeof n=="object"&&n!==null){if(e.has(n))return"[Circular]";e.add(n)}return n})},X=class{constructor(){this.transport=null;this.options=null;this.isInstrumented=!1}preload(e={}){let r=e.endpoint||"https://api.senzor.dev/api/ingest/apm",n=e.debug||!1;this.options={apiKey:"",...this.options,...e},this.installNativeInstrumentations(r,n)}init(e){if(!e.apiKey){console.warn("[Senzor] API Key missing. SDK disabled.");return}this.options=e;let r=e.endpoint||"https://api.senzor.dev/api/ingest/apm",n=e.debug||!1;this.transport=new $({...e,endpoint:r}),this.installNativeInstrumentations(r,n)}isInstrumentationEnabled(e){let r=this.options?.instrumentations;return r===!1?!1:Array.isArray(r)?r.includes(e):!0}installNativeInstrumentations(e,r){if(!this.isInstrumented){this.setupGlobalErrorHandlers(),this.setupLogInterception();try{this.isInstrumentationEnabled("http")&&ke(this,e,this.options||void 0)}catch{}try{this.isInstrumentationEnabled("fetch")&&Se(e,this.options||void 0)}catch{}try{this.isInstrumentationEnabled("undici")&&Ae(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("mongo")&&Te(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("mongoose")&&Me(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("pg")&&Ce(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("mysql")&&Ie(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("redis")&&ze(this.options||void 0)}catch{}try{this.isInstrumentationEnabled("bullmq")&&_e(this,r)}catch{}try{this.isInstrumentationEnabled("cron")&&$e(this,r)}catch{}this.isInstrumented=!0,r&&console.log("[Senzor] Auto-instrumentation enabled")}}setupLogInterception(){if(this.options?.autoLogs===!1)return;let e=["log","info","warn","error","debug"],r={log:console.log,info:console.info,warn:console.warn,error:console.error,debug:console.debug},n=!1;e.forEach(o=>{console[o]=(...a)=>{if(r[o].apply(console,a),!(n||!this.transport)){n=!0;try{let s="",p={};a.forEach(u=>{if(typeof u=="string")s+=(s?" ":"")+u;else if(u instanceof Error)s+=(s?" ":"")+u.message,p.errorStack=u.stack,p.errorName=u.name;else if(typeof u=="object"&&u!==null)try{let l=JSON.parse(Mt(u));p={...p,...x(l,this.options||void 0)}}catch{p.unparseableObject=!0}else s+=(s?" ":"")+String(u)}),!s&&Object.keys(p).length>0&&(s="Object Log");let c=y.current(),i=c?.contextType==="task"?"task":"apm",d={message:s||"Empty log",level:o==="log"?"info":o,attributes:p,timestamp:new Date().toISOString()};c&&(i==="task"?d.runId=c.id:d.traceId=c.id),this.transport.addLog(d,i)}catch{}finally{n=!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{}}},r=()=>{try{let o=process.memoryUsage();return{rss:o.rss,heapTotal:o.heapTotal,heapUsed:o.heapUsed,external:o.external,arrayBuffers:o.arrayBuffers}}catch{return{}}},n=(o,a={})=>{try{let s;if(o instanceof Error)s=o;else if(typeof o=="string")s=new Error(o);else try{s=new Error(JSON.stringify(o))}catch{s=new Error("Non-serializable rejection reason")}let p={...a,runtime:{name:"node",version:process.version},process:e(),memory:r(),sdk:{name:J.name,version:J.version}};this.captureError(s,p)}catch(s){try{this.options?.debug&&console.error("[Senzor] Error handler failure:",s)}catch{}}};process.on("uncaughtExceptionMonitor",o=>n(o,{type:"uncaughtExceptionMonitor",severity:"fatal"})),process.on("uncaughtException",o=>n(o,{type:"uncaughtException",severity:"fatal"})),process.on("unhandledRejection",o=>n(o,{type:"unhandledRejection",severity:"error"})),process.on("warning",o=>n(o,{type:"processWarning",severity:"warning"})),process.on("multipleResolves",(o,a,s)=>n(s||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",()=>n(new Error("Process received SIGTERM"),{type:"processSignal",signal:"SIGTERM"})),process.on("SIGINT",()=>n(new Error("Process received SIGINT"),{type:"processSignal",signal:"SIGINT"}))}startTrace(e,r){if(!this.transport)return r();let n=y.current();if(n?.contextType==="apm")return n.data={...n.data,...e},r();let o,a;if(e.headers){let i=l=>{if(e.headers[l])return e.headers[l];if(e.headers[l.toLowerCase()])return e.headers[l.toLowerCase()]},d=i("traceparent"),u=ie(d);if(u)o=u.traceId,a=u.parentSpanId;else{let l=i("x-senzor-trace-id"),h=i("x-senzor-parent-span-id");o=Array.isArray(l)?l[0]:l,a=Array.isArray(h)?h[0]:h}}let s=o||Z(),p=_(),c={id:s,contextType:"apm",startTime:performance.now(),rootSpanId:p,activeSpanId:p,data:{...e,parentTraceId:o,parentSpanId:a,rootSpanId:p},spans:[],maxSpans:this.options?.maxSpansPerTrace??500,droppedSpans:0};return y.run(c,r)}endTrace(e,r={}){let n=y.current();if(!n||n.contextType!=="apm"||!this.transport||n.ended)return;n.ended=!0;let o=performance.now()-n.startTime,a={traceId:n.id,parentTraceId:n.data.parentTraceId,parentSpanId:n.data.parentSpanId,rootSpanId:n.rootSpanId,...n.data,...r,status:e,duration:o,spans:n.spans,droppedSpans:n.droppedSpans,timestamp:new Date().toISOString()};this.transport.addTrace(a)}startTask(e,r,n,o){if(!this.transport)return o();let a=y.current(),s=a?.contextType==="apm"?a.id:void 0,p=process.memoryUsage?process.memoryUsage().heapUsed:0,c=process.cpuUsage?process.cpuUsage():void 0,i={id:Pt(),contextType:"task",startTime:performance.now(),rootSpanId:_(),startMemory:p,startCpu:c,data:{taskName:e,taskType:r,triggerTraceId:s,...n},spans:[],maxSpans:this.options?.maxSpansPerTrace??500,droppedSpans:0};return i.activeSpanId=i.rootSpanId,y.run(i,o)}endTask(e,r={}){let n=y.current();if(!n||n.contextType!=="task"||!this.transport)return;let o;if(process.memoryUsage&&n.startMemory!==void 0&&process.cpuUsage&&n.startCpu){let s=process.memoryUsage().heapUsed,p=process.cpuUsage(n.startCpu);o={memoryDeltaBytes:s-n.startMemory,cpuUserUs:p.user,cpuSystemUs:p.system}}let a={runId:n.id,taskName:n.data.taskName,taskType:n.data.taskType,triggerTraceId:n.data.triggerTraceId,queueDelay:n.data.queueDelay,attempts:n.data.attempts,isDeadLetter:n.data.isDeadLetter,metadata:{...n.data.metadata,...r,droppedSpans:n.droppedSpans},resourceMetrics:o,status:e,duration:performance.now()-n.startTime,spans:n.spans,timestamp:new Date().toISOString()};this.transport.addTask(a)}wrapTask(e,r,n={},o){return(async(...a)=>this.startTask(e,r,n,async()=>{try{let s=await o(...a);return this.endTask("success"),s}catch(s){throw this.captureError(s,{taskName:e}),this.endTask("failed"),s}}))}captureError(e,r={}){if(!this.transport)return;let n;e instanceof Error?n=e:n=new Error(String(e));let o=y.current(),a={errorClass:n.name||"Error",message:n.message,stackTrace:n.stack,context:x(r,this.options||void 0),timestamp:new Date().toISOString()};o?.contextType==="task"?this.transport.addError({...a,runId:o.id},"task"):this.transport.addError({...a,traceId:o?.id},"apm")}track(e){this.transport?.addTrace({traceId:Z(),...e,spans:[],timestamp:new Date().toISOString()})}startSpan(e,r="custom"){let n=k(e,r,{},this.options||void 0);return n?{end:(o,a)=>n.end(a,o)}:{end:()=>{}}}async flush(){this.transport&&await this.transport.flush()}},Y=new X;var He=t=>t==="1"||t==="true"||t==="yes",N=t=>{if(!t)return;let e=Number(t);return Number.isFinite(e)&&e>0?e:void 0},Ue=process.env.SENZOR_API_KEY||process.env.SENZOR_APM_API_KEY||process.env.SENZOR_SERVICE_API_KEY,Lt=process.env.SENZOR_ENDPOINT||process.env.SENZOR_APM_ENDPOINT,Fe={apiKey:Ue||"",endpoint:Lt,debug:He(process.env.SENZOR_DEBUG),autoLogs:process.env.SENZOR_AUTO_LOGS==="false"?!1:void 0,batchSize:N(process.env.SENZOR_BATCH_SIZE),flushInterval:N(process.env.SENZOR_FLUSH_INTERVAL),flushTimeoutMs:N(process.env.SENZOR_FLUSH_TIMEOUT_MS),maxQueueSize:N(process.env.SENZOR_MAX_QUEUE_SIZE),maxSpansPerTrace:N(process.env.SENZOR_MAX_SPANS_PER_TRACE),captureHeaders:He(process.env.SENZOR_CAPTURE_HEADERS),captureDbStatement:process.env.SENZOR_CAPTURE_DB_STATEMENT==="false"?!1:void 0};Ue?Y.init(Fe):Y.preload(Fe);
|
|
2
|
+
//# sourceMappingURL=register.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/internal.ts","../src/core/transport.ts","../src/core/context.ts","../src/core/client.ts","../src/instrumentation/http.ts","../src/core/normalizer.ts","../src/core/sanitizer.ts","../src/utils/getClientIp.ts","../src/utils/traceContext.ts","../src/instrumentation/patch.ts","../src/utils/ids.ts","../src/instrumentation/span.ts","../src/instrumentation/hook.ts","../src/instrumentation/mongo.ts","../src/instrumentation/pg.ts","../src/instrumentation/undici.ts","../src/instrumentation/redis.ts","../src/instrumentation/mysql.ts","../src/instrumentation/mongoose.ts","../src/instrumentation/bullmq.ts","../src/instrumentation/cron.ts","../package.json","../src/utils/sdkMeta.ts","../src/register.ts"],"sourcesContent":["export const SENZOR_INTERNAL_HEADER = 'x-senzor-sdk-internal';\n","import { SENZOR_INTERNAL_HEADER } from '../utils/internal';\nimport { SenzorOptions, Trace, TaskRun, SenzorError, SenzorLog } from './types';\n\ninterface ApmPayload {\n traces: Trace[];\n errors: SenzorError[];\n logs: SenzorLog[];\n}\n\ninterface TaskPayload {\n runs: TaskRun[];\n errors: SenzorError[];\n logs: SenzorLog[];\n}\n\nexport class Transport {\n private traceQueue: Trace[] = [];\n private apmErrorQueue: SenzorError[] = [];\n private apmLogQueue: SenzorLog[] = [];\n\n private taskQueue: TaskRun[] = [];\n private taskErrorQueue: SenzorError[] = [];\n private taskLogQueue: SenzorLog[] = [];\n\n private timer: NodeJS.Timeout | null = null;\n private apmEndpoint: string;\n private taskEndpoint: string;\n private isFlushing = false;\n private flushAgain = false;\n private droppedItems = 0;\n\n constructor(private config: SenzorOptions) {\n const baseEndpoint = config.endpoint || 'https://api.senzor.dev';\n this.apmEndpoint = baseEndpoint.includes('/api/ingest')\n ? baseEndpoint\n : `${baseEndpoint}/api/ingest/apm`;\n this.taskEndpoint = baseEndpoint.includes('/api/ingest')\n ? baseEndpoint.replace('/apm', '/task')\n : `${baseEndpoint}/api/ingest/task`;\n\n if (typeof setInterval !== 'undefined') {\n this.timer = setInterval(\n () => void this.flush(),\n config.flushInterval || 10000\n );\n if (this.timer && typeof this.timer.unref === 'function') {\n this.timer.unref();\n }\n }\n\n this.installShutdownFlush();\n }\n\n public addTrace(trace: any) {\n this.enqueue(this.traceQueue, trace);\n this.checkFlush();\n }\n\n public addTask(task: TaskRun) {\n this.enqueue(this.taskQueue, task);\n this.checkFlush();\n }\n\n public addError(error: SenzorError, type: 'apm' | 'task' = 'apm') {\n this.enqueue(\n type === 'task' ? this.taskErrorQueue : this.apmErrorQueue,\n error\n );\n this.checkFlush();\n }\n\n public addLog(log: SenzorLog, type: 'apm' | 'task' = 'apm') {\n this.enqueue(\n type === 'task' ? this.taskLogQueue : this.apmLogQueue,\n log\n );\n this.checkFlush();\n }\n\n private enqueue<T>(queue: T[], item: T) {\n queue.push(item);\n\n const maxQueueSize = this.config.maxQueueSize ?? 10000;\n while (queue.length > maxQueueSize) {\n queue.shift();\n this.droppedItems++;\n }\n }\n\n private prependWithLimit<T>(queue: T[], items: T[]) {\n if (!items.length) return;\n queue.unshift(...items);\n\n const maxQueueSize = this.config.maxQueueSize ?? 10000;\n while (queue.length > maxQueueSize) {\n queue.pop();\n this.droppedItems++;\n }\n }\n\n private checkFlush() {\n const totalApm =\n this.traceQueue.length +\n this.apmErrorQueue.length +\n this.apmLogQueue.length;\n const totalTask =\n this.taskQueue.length +\n this.taskErrorQueue.length +\n this.taskLogQueue.length;\n\n if (\n totalApm >= (this.config.batchSize || 100) ||\n totalTask >= (this.config.batchSize || 100)\n ) {\n void this.flush();\n }\n }\n\n private takeApmPayload(): ApmPayload {\n const payload = {\n traces: this.traceQueue,\n errors: this.apmErrorQueue,\n logs: this.apmLogQueue\n };\n\n this.traceQueue = [];\n this.apmErrorQueue = [];\n this.apmLogQueue = [];\n return payload;\n }\n\n private takeTaskPayload(): TaskPayload {\n const payload = {\n runs: this.taskQueue,\n errors: this.taskErrorQueue,\n logs: this.taskLogQueue\n };\n\n this.taskQueue = [];\n this.taskErrorQueue = [];\n this.taskLogQueue = [];\n return payload;\n }\n\n private restoreApmPayload(payload: ApmPayload) {\n this.prependWithLimit(this.apmLogQueue, payload.logs);\n this.prependWithLimit(this.apmErrorQueue, payload.errors);\n this.prependWithLimit(this.traceQueue, payload.traces);\n }\n\n private restoreTaskPayload(payload: TaskPayload) {\n this.prependWithLimit(this.taskLogQueue, payload.logs);\n this.prependWithLimit(this.taskErrorQueue, payload.errors);\n this.prependWithLimit(this.taskQueue, payload.runs);\n }\n\n private hasApmPayload(payload: ApmPayload): boolean {\n return (\n payload.traces.length > 0 ||\n payload.errors.length > 0 ||\n payload.logs.length > 0\n );\n }\n\n private hasTaskPayload(payload: TaskPayload): boolean {\n return (\n payload.runs.length > 0 ||\n payload.errors.length > 0 ||\n payload.logs.length > 0\n );\n }\n\n private async postJson(endpoint: string, payload: unknown) {\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n this.config.flushTimeoutMs ?? 5000\n );\n\n if (typeof timeout.unref === 'function') timeout.unref();\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-service-api-key': this.config.apiKey,\n [SENZOR_INTERNAL_HEADER]: 'true'\n },\n body: JSON.stringify(payload),\n keepalive: true,\n signal: controller.signal\n });\n\n if (!response.ok) {\n throw new Error(`Senzor ingest failed with status ${response.status}`);\n }\n } finally {\n clearTimeout(timeout);\n }\n }\n\n public async flush() {\n if (this.isFlushing) {\n this.flushAgain = true;\n return;\n }\n\n this.isFlushing = true;\n\n try {\n do {\n this.flushAgain = false;\n\n const apmPayload = this.takeApmPayload();\n const taskPayload = this.takeTaskPayload();\n const sends: Promise<void>[] = [];\n\n if (this.hasApmPayload(apmPayload)) {\n sends.push(\n this.postJson(this.apmEndpoint, apmPayload).catch((error) => {\n this.restoreApmPayload(apmPayload);\n throw error;\n })\n );\n }\n\n if (this.hasTaskPayload(taskPayload)) {\n sends.push(\n this.postJson(this.taskEndpoint, taskPayload).catch((error) => {\n this.restoreTaskPayload(taskPayload);\n throw error;\n })\n );\n }\n\n if (!sends.length) continue;\n\n const results = await Promise.allSettled(sends);\n const failures = results.filter(\n (result) => result.status === 'rejected'\n );\n\n if (this.config.debug) {\n console.log(\n `[Senzor] Flushed: APM(${apmPayload.traces.length} traces, ${apmPayload.logs.length} logs), Task(${taskPayload.runs.length} runs, ${taskPayload.logs.length} logs), failures=${failures.length}, dropped=${this.droppedItems}`\n );\n }\n } while (this.flushAgain);\n } catch (err) {\n if (this.config.debug) console.error('[Senzor] Transport Flush Error:', err);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private installShutdownFlush() {\n const key = Symbol.for('senzor.transport.shutdownFlushInstalled');\n const proc = process as unknown as Record<symbol, boolean>;\n if (proc[key]) return;\n\n Object.defineProperty(proc, key, {\n value: true,\n enumerable: false\n });\n\n const flushSyncBestEffort = () => {\n void this.flush();\n };\n\n process.once('beforeExit', flushSyncBestEffort);\n }\n}\n","import { AsyncLocalStorage } from 'async_hooks';\nimport { ActiveTrace, Span } from './types';\n\nexport const storage = new AsyncLocalStorage<ActiveTrace>();\n\nexport const Context = {\n run: <T>(trace: ActiveTrace, fn: () => T): T => {\n return storage.run(trace, fn);\n },\n\n withActiveSpan: <T>(spanId: string, fn: () => T): T => {\n const store = storage.getStore();\n if (!store) return fn();\n\n return storage.run(\n {\n ...store,\n activeSpanId: spanId,\n data: store.data,\n spans: store.spans\n },\n fn\n );\n },\n\n current: (): ActiveTrace | undefined => {\n return storage.getStore();\n },\n\n addSpan: (span: Span) => {\n const store = storage.getStore();\n if (store) {\n Context.addSpanToTrace(store, span);\n }\n },\n\n addSpanToTrace: (trace: ActiveTrace, span: Span) => {\n if (trace.ended) return;\n\n const maxSpans = trace.maxSpans ?? 500;\n if (trace.spans.length >= maxSpans) {\n trace.droppedSpans = (trace.droppedSpans ?? 0) + 1;\n return;\n }\n\n trace.spans.push(span);\n }\n};\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';\nimport { instrumentUndici } from '../instrumentation/undici';\nimport { instrumentRedis } from '../instrumentation/redis';\nimport { instrumentMysql } from '../instrumentation/mysql';\nimport { instrumentMongoose } from '../instrumentation/mongoose';\nimport { instrumentBullMQ } from '../instrumentation/bullmq';\nimport { instrumentNodeCron } from '../instrumentation/cron';\nimport { SDK_META } from '../utils/sdkMeta';\nimport { parseTraceparent } from '../utils/traceContext';\nimport { generateSpanId, generateTraceId } from '../utils/ids';\nimport { sanitizeAttributes } from './sanitizer';\nimport { startCapturedSpan } from '../instrumentation/span';\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 {\n private transport: Transport | null = null;\n private options: SenzorOptions | null = null;\n private isInstrumented = false;\n\n public preload(options: Partial<SenzorOptions> = {}) {\n const endpoint = options.endpoint || 'https://api.senzor.dev/api/ingest/apm';\n const debug = options.debug || false;\n\n this.options = {\n apiKey: '',\n ...this.options,\n ...options\n };\n\n this.installNativeInstrumentations(endpoint, debug);\n }\n\n public init(options: SenzorOptions) {\n if (!options.apiKey) {\n console.warn('[Senzor] API Key missing. SDK disabled.');\n return;\n }\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\n this.transport = new Transport({ ...options, endpoint });\n this.installNativeInstrumentations(endpoint, debug);\n }\n\n private isInstrumentationEnabled(name: string): boolean {\n const setting = this.options?.instrumentations;\n if (setting === false) return false;\n if (Array.isArray(setting)) return setting.includes(name);\n return true;\n }\n\n private installNativeInstrumentations(endpoint: string, debug: boolean) {\n if (!this.isInstrumented) {\n this.setupGlobalErrorHandlers();\n this.setupLogInterception(); // Fire up Auto Log Instrumentation\n\n try { if (this.isInstrumentationEnabled('http')) instrumentHttp(this, endpoint, this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('fetch')) instrumentFetch(endpoint, this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('undici')) instrumentUndici(this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('mongo')) instrumentMongo(this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('mongoose')) instrumentMongoose(this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('pg')) instrumentPg(this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('mysql')) instrumentMysql(this.options || undefined); } catch (e) { }\n try { if (this.isInstrumentationEnabled('redis')) instrumentRedis(this.options || undefined); } catch (e) { }\n\n // Task Integrations \n try { if (this.isInstrumentationEnabled('bullmq')) instrumentBullMQ(this, debug); } catch (e) { }\n try { if (this.isInstrumentationEnabled('cron')) instrumentNodeCron(this, debug); } catch (e) { }\n\n this.isInstrumented = true;\n if (debug) console.log('[Senzor] Auto-instrumentation enabled');\n }\n }\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 {\n // New Relic Style Destructuring: Merge all object keys into `attributes`\n const parsed = JSON.parse(safeStringify(arg));\n attributes = { ...attributes, ...sanitizeAttributes(parsed, this.options || undefined) };\n } catch (e) {\n attributes.unparseableObject = true;\n }\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 {\n if (!this.transport) return next();\n\n const existingTrace = Context.current();\n if (existingTrace?.contextType === 'apm') {\n existingTrace.data = {\n ...existingTrace.data,\n ...data\n };\n return next();\n }\n\n let inheritedTraceId: string | undefined = undefined;\n let inheritedParentSpanId: string | undefined = undefined;\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 || generateTraceId();\n const rootSpanId = generateSpanId();\n\n const trace: ActiveTrace = {\n id: activeTraceId,\n contextType: 'apm',\n startTime: performance.now(),\n rootSpanId,\n activeSpanId: rootSpanId,\n data: { ...data, parentTraceId: inheritedTraceId, parentSpanId: inheritedParentSpanId, rootSpanId },\n spans: [],\n maxSpans: this.options?.maxSpansPerTrace ?? 500,\n droppedSpans: 0\n };\n\r\n return Context.run(trace, next);\r\n }\r\n\r\n public endTrace(status: number, extraData: any = {}) {\n const trace = Context.current();\n if (!trace || trace.contextType !== 'apm' || !this.transport) return;\n if (trace.ended) return;\n trace.ended = true;\n const duration = performance.now() - trace.startTime;\n\n const payload = {\n traceId: trace.id,\n parentTraceId: trace.data.parentTraceId,\n parentSpanId: trace.data.parentSpanId,\n rootSpanId: trace.rootSpanId,\n ...trace.data,\n ...extraData,\n status,\n duration,\n spans: trace.spans,\n droppedSpans: trace.droppedSpans,\n timestamp: new Date().toISOString()\n };\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 = {\n id: randomUUID(),\n contextType: 'task',\n startTime: performance.now(),\n rootSpanId: generateSpanId(),\n startMemory,\n startCpu,\n data: { taskName: name, taskType: type, triggerTraceId, ...options },\n spans: [],\n maxSpans: this.options?.maxSpansPerTrace ?? 500,\n droppedSpans: 0\n };\n task.activeSpanId = task.rootSpanId;\n return Context.run(task, next);\n }\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, droppedSpans: task.droppedSpans },\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 = {\n errorClass: parsedError.name || 'Error',\n message: parsedError.message,\n stackTrace: parsedError.stack,\n context: sanitizeAttributes(context, this.options || undefined),\n timestamp: new Date().toISOString()\n };\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 }\n\n public track(data: any) {\n this.transport?.addTrace({ traceId: generateTraceId(), ...data, spans: [], timestamp: new Date().toISOString() });\n }\n\n public startSpan(name: string, type: 'db' | 'http' | 'function' | 'custom' = 'custom') {\n const span = startCapturedSpan(name, type, {}, this.options || undefined);\n if (!span) return { end: () => { } };\n return { end: (meta?: any, status?: number) => span.end(status, meta) };\n }\n\r\n public async flush() { if (this.transport) await this.transport.flush(); }\r\n}\r\n\r\nexport const client = new SenzorClient();\n","import http from 'http';\nimport https from 'https';\nimport { URL } from 'url';\nimport type { SenzorClient } from '../core/client';\nimport { Context } from '../core/context';\nimport { getRoute, normalizePath } from '../core/normalizer';\nimport { sanitizeHeaders } from '../core/sanitizer';\nimport { SenzorOptions } from '../core/types';\nimport { getClientIp } from '../utils/getClientIp';\nimport { SENZOR_INTERNAL_HEADER } from '../utils/internal';\nimport { generateTraceparent } from '../utils/traceContext';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst getDebug = (options?: SenzorOptions): boolean =>\n Boolean(options?.debug);\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' &&\n value !== null &&\n !(value instanceof URL) &&\n !(value instanceof Function) &&\n !Array.isArray(value);\n\nconst headerValue = (\n headers: unknown,\n key: string\n): unknown => {\n if (!headers) return undefined;\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n return headers.get(key);\n }\n\n if (Array.isArray(headers)) {\n const found = headers.find(\n ([name]) => String(name).toLowerCase() === key.toLowerCase()\n );\n return found?.[1];\n }\n\n if (typeof headers === 'object') {\n const normalizedKey = key.toLowerCase();\n for (const [name, value] of Object.entries(headers)) {\n if (name.toLowerCase() === normalizedKey) return value;\n }\n }\n\n return undefined;\n};\n\nconst hasInternalHeader = (headers: unknown): boolean =>\n String(headerValue(headers, SENZOR_INTERNAL_HEADER) || '').toLowerCase() ===\n 'true';\n\nconst shouldIgnoreUrl = (\n urlString: string,\n ingestUrl: string,\n headers?: unknown\n): boolean => {\n if (hasInternalHeader(headers)) return true;\n if (!urlString) return false;\n\n try {\n const url = new URL(urlString);\n const ingest = new URL(ingestUrl);\n return (\n url.hostname === ingest.hostname &&\n url.pathname.startsWith('/api/ingest')\n );\n } catch {\n return ingestUrl ? urlString.includes(ingestUrl) : false;\n }\n};\n\nconst cloneHeaders = (headers: unknown): Record<string, unknown> => {\n if (!headers) return {};\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const cloned: Record<string, unknown> = {};\n headers.forEach((value, key) => {\n cloned[key] = value;\n });\n return cloned;\n }\n\n if (Array.isArray(headers)) {\n return headers.reduce<Record<string, unknown>>((acc, [key, value]) => {\n acc[key] = value;\n return acc;\n }, {});\n }\n\n if (typeof headers === 'object') {\n return { ...(headers as Record<string, unknown>) };\n }\n\n return {};\n};\n\nconst setHeader = (\n headers: Record<string, unknown>,\n key: string,\n value: string\n) => {\n const existingKey = Object.keys(headers).find(\n (header) => header.toLowerCase() === key.toLowerCase()\n );\n headers[existingKey || key] = value;\n};\n\ninterface PreparedRequest {\n args: any[];\n options: Record<string, any>;\n url: string;\n method: string;\n hostname: string;\n path: string;\n}\n\nconst prepareRequestArgs = (\n args: any[],\n defaultProtocol: 'http:' | 'https:'\n): PreparedRequest => {\n const nextArgs = [...args];\n let optionsIndex = 0;\n let options: Record<string, any> = {};\n let urlFromArg: URL | null = null;\n\n if (typeof nextArgs[0] === 'string' || nextArgs[0] instanceof URL) {\n try {\n urlFromArg = new URL(nextArgs[0].toString());\n } catch {\n urlFromArg = null;\n }\n\n if (isPlainObject(nextArgs[1])) {\n optionsIndex = 1;\n options = {\n ...nextArgs[1],\n headers: cloneHeaders(nextArgs[1].headers)\n };\n nextArgs[1] = options;\n } else {\n optionsIndex = 1;\n options = { headers: {} };\n nextArgs.splice(1, 0, options);\n }\n } else if (isPlainObject(nextArgs[0])) {\n optionsIndex = 0;\n options = {\n ...nextArgs[0],\n headers: cloneHeaders(nextArgs[0].headers)\n };\n nextArgs[0] = options;\n } else {\n optionsIndex = 0;\n options = { headers: {} };\n nextArgs[0] = options;\n }\n\n if (!options.headers) options.headers = {};\n nextArgs[optionsIndex] = options;\n\n const protocol =\n options.protocol ||\n urlFromArg?.protocol ||\n (options.port === 443 ? 'https:' : defaultProtocol);\n const hostname =\n options.hostname ||\n options.host ||\n urlFromArg?.hostname ||\n 'localhost';\n const path =\n options.path ||\n `${urlFromArg?.pathname || '/'}${urlFromArg?.search || ''}`;\n const url = urlFromArg\n ? urlFromArg.toString()\n : `${protocol}//${hostname}${path}`;\n const method = String(options.method || 'GET').toUpperCase();\n\n return {\n args: nextArgs,\n options,\n url,\n method,\n hostname: String(hostname).replace(/:\\d+$/, ''),\n path\n };\n};\n\nconst resolveIncomingRoute = (\n req: any,\n res: any,\n path: string\n): string => {\n if (res?.statusCode === 404) return 'Not Found';\n\n try {\n return getRoute(req, path);\n } catch {\n return normalizePath(path);\n }\n};\n\nconst patchIncomingServer = (\n proto: any,\n protocol: 'http' | 'https',\n client: SenzorClient,\n options?: SenzorOptions\n) => {\n patchMethod(\n proto,\n 'emit',\n `senzor.${protocol}.server`,\n (original) =>\n function patchedEmit(this: any, event: string, ...args: any[]) {\n if (event !== 'request') {\n return original.call(this, event, ...args);\n }\n\n const req = args[0];\n const res = args[1];\n\n if (!req || !res || Context.current()?.contextType === 'apm') {\n return original.call(this, event, ...args);\n }\n\n const rawPath = req.originalUrl || req.url || '/';\n const path = String(rawPath).split('?')[0] || '/';\n const headers = req.headers || {};\n\n if (hasInternalHeader(headers)) {\n return original.call(this, event, ...args);\n }\n\n return client.startTrace(\n {\n method: req.method || 'GET',\n path: rawPath,\n route: normalizePath(path),\n ip: getClientIp(req),\n userAgent: headers['user-agent'],\n headers,\n meta: {\n protocol,\n httpVersion: req.httpVersion,\n headers: options?.captureHeaders\n ? sanitizeHeaders(headers, options)\n : undefined\n }\n },\n () => {\n const trace = Context.current();\n let finalized = false;\n\n const finalize = (reason: 'finish' | 'close' | 'error') => {\n if (finalized || !trace) return;\n finalized = true;\n\n setImmediate(() => {\n if (trace.ended) return;\n\n Context.run(trace, () => {\n client.endTrace(res.statusCode || 0, {\n route: resolveIncomingRoute(req, res, path),\n statusMessage: res.statusMessage,\n meta: {\n ...trace.data.meta,\n endReason: reason\n }\n });\n });\n });\n };\n\n res.once('finish', () => finalize('finish'));\n res.once('close', () => finalize('close'));\n res.once('error', (error: Error) => {\n client.captureError(error, {\n instrumentation: `${protocol}.server`\n });\n finalize('error');\n });\n\n try {\n return original.call(this, event, ...args);\n } catch (error) {\n client.captureError(error, {\n instrumentation: `${protocol}.server`\n });\n finalize('error');\n throw error;\n }\n }\n );\n }\n );\n};\n\nconst patchOutgoing = (\n moduleRef: typeof http | typeof https,\n protocol: 'http:' | 'https:',\n ingestUrl: string,\n options?: SenzorOptions\n) => {\n const patchKeyPrefix = protocol === 'https:' ? 'senzor.https' : 'senzor.http';\n\n const requestWrapper = (original: Function) =>\n function patchedRequest(this: any, ...args: any[]) {\n const prepared = prepareRequestArgs(args, protocol);\n\n if (\n shouldIgnoreUrl(\n prepared.url,\n ingestUrl,\n prepared.options.headers\n )\n ) {\n return original.apply(this, args);\n }\n\n const trace = Context.current();\n if (!trace) return original.apply(this, args);\n\n const span = startCapturedSpan(\n `${prepared.method} ${prepared.hostname}`,\n 'http',\n {\n url: prepared.url,\n method: prepared.method,\n library: protocol === 'https:' ? 'https' : 'http',\n 'http.request.method': prepared.method,\n 'url.full': prepared.url,\n 'url.path': prepared.path,\n 'server.address': prepared.hostname\n },\n options\n );\n\n if (span) {\n setHeader(\n prepared.options.headers,\n 'traceparent',\n generateTraceparent(trace.id, span.spanId)\n );\n setHeader(prepared.options.headers, 'x-senzor-trace-id', trace.id);\n setHeader(\n prepared.options.headers,\n 'x-senzor-parent-span-id',\n span.spanId\n );\n }\n\n const invoke = () => {\n const req = original.apply(this, prepared.args);\n if (!span || !req || typeof req.once !== 'function') {\n return req;\n }\n\n let completed = false;\n const endSpan = (\n status: number,\n extraMeta: Record<string, unknown> = {}\n ) => {\n if (completed) return;\n completed = true;\n span.end(status, extraMeta);\n };\n\n req.once('response', (res: any) => {\n const statusCode = res?.statusCode || 0;\n const finish = () =>\n endSpan(statusCode, {\n 'http.response.status_code': statusCode\n });\n\n res.once('end', finish);\n res.once('close', finish);\n res.once('error', (error: Error) =>\n endSpan(500, {\n error: error.message,\n 'error.type': error.name\n })\n );\n });\n\n req.once('timeout', () =>\n endSpan(504, {\n error: 'Request timed out',\n 'error.type': 'TimeoutError'\n })\n );\n req.once('error', (error: Error) =>\n endSpan(500, {\n error: error.message,\n 'error.type': error.name\n })\n );\n\n return req;\n };\n\n if (getDebug(options)) {\n console.log(`[Senzor] Injecting trace headers to ${prepared.url}`);\n }\n\n return runWithCapturedSpan(span, invoke);\n };\n\n patchMethod(\n moduleRef,\n 'request',\n `${patchKeyPrefix}.request`,\n requestWrapper\n );\n patchMethod(\n moduleRef,\n 'get',\n `${patchKeyPrefix}.get`,\n requestWrapper\n );\n};\n\nexport const instrumentFetch = (\n ingestUrl: string,\n options?: SenzorOptions\n) => {\n if (!globalThis.fetch) return;\n\n patchMethod(\n globalThis,\n 'fetch',\n 'senzor.fetch',\n (original) =>\n async function patchedFetch(\n this: any,\n input: any,\n init?: any\n ): Promise<Response> {\n const urlString =\n typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.toString()\n : input?.url || '';\n\n const originalHeaders = init?.headers || input?.headers;\n if (shouldIgnoreUrl(urlString, ingestUrl, originalHeaders)) {\n return original.call(this, input, init);\n }\n\n const trace = Context.current();\n if (!trace) return original.call(this, input, init);\n\n let hostname = 'unknown';\n let path = '/';\n try {\n const url = new URL(urlString);\n hostname = url.hostname;\n path = `${url.pathname}${url.search}`;\n } catch { }\n\n const method = String(\n init?.method || input?.method || 'GET'\n ).toUpperCase();\n const span = startCapturedSpan(\n `${method} ${hostname}`,\n 'http',\n {\n url: urlString,\n method,\n library: 'fetch',\n 'http.request.method': method,\n 'url.full': urlString,\n 'url.path': path,\n 'server.address': hostname\n },\n options\n );\n\n if (!span) return original.call(this, input, init);\n\n const nextInit = { ...(init || {}) };\n const headers =\n typeof Headers !== 'undefined'\n ? new Headers(originalHeaders || undefined)\n : cloneHeaders(originalHeaders);\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n headers.set('traceparent', generateTraceparent(trace.id, span.spanId));\n headers.set('x-senzor-trace-id', trace.id);\n headers.set('x-senzor-parent-span-id', span.spanId);\n } else {\n setHeader(headers as Record<string, unknown>, 'traceparent', generateTraceparent(trace.id, span.spanId));\n setHeader(headers as Record<string, unknown>, 'x-senzor-trace-id', trace.id);\n setHeader(headers as Record<string, unknown>, 'x-senzor-parent-span-id', span.spanId);\n }\n nextInit.headers = headers;\n\n return runWithCapturedSpan(span, async () => {\n try {\n const response = await original.call(this, input, nextInit);\n span.end(response.status, {\n 'http.response.status_code': response.status\n });\n return response;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nexport const instrumentHttp = (\n client: SenzorClient,\n ingestUrl: string,\n options?: SenzorOptions\n) => {\n patchIncomingServer(http.Server?.prototype, 'http', client, options);\n patchIncomingServer(https.Server?.prototype, 'https', client, options);\n\n patchOutgoing(http, 'http:', ingestUrl, options);\n patchOutgoing(https, 'https:', ingestUrl, options);\n};\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 { SenzorOptions } from './types';\n\nconst DEFAULT_MAX_ATTRIBUTES = 64;\nconst DEFAULT_MAX_ATTRIBUTE_LENGTH = 2048;\nconst MAX_DEPTH = 4;\nconst MAX_ARRAY_ITEMS = 20;\n\nconst SENSITIVE_KEY_PATTERN =\n /(^|[-_.])(authorization|cookie|set-cookie|password|passwd|pwd|secret|token|api[-_.]?key|x-api-key|access[-_.]?token|refresh[-_.]?token|client[-_.]?secret|private[-_.]?key)([-_.]|$)/i;\n\nexport interface SanitizerOptions {\n maxAttributes?: number;\n maxAttributeLength?: number;\n}\n\nconst getLimits = (options?: SanitizerOptions | SenzorOptions) => ({\n maxAttributes: options?.maxAttributes ?? DEFAULT_MAX_ATTRIBUTES,\n maxAttributeLength:\n options?.maxAttributeLength ?? DEFAULT_MAX_ATTRIBUTE_LENGTH\n});\n\nexport const truncate = (\n value: string,\n maxLength = DEFAULT_MAX_ATTRIBUTE_LENGTH\n): string => {\n if (value.length <= maxLength) return value;\n return `${value.slice(0, Math.max(0, maxLength - 15))}...[truncated]`;\n};\n\nexport const isSensitiveKey = (key: string): boolean =>\n SENSITIVE_KEY_PATTERN.test(key);\n\nconst sanitizePrimitive = (\n value: unknown,\n maxLength: number\n): string | number | boolean | null | undefined => {\n if (value === null || value === undefined) return value;\n\n if (\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (typeof value === 'string') {\n return truncate(value, maxLength);\n }\n\n return undefined;\n};\n\nconst sanitizeValue = (\n key: string,\n value: unknown,\n options: Required<SanitizerOptions>,\n depth: number\n): unknown => {\n if (isSensitiveKey(key)) return '[REDACTED]';\n\n const primitive =\n sanitizePrimitive(value, options.maxAttributeLength);\n\n if (primitive !== undefined || value === undefined) {\n return primitive;\n }\n\n if (value instanceof Error) {\n return {\n name: truncate(value.name, options.maxAttributeLength),\n message: truncate(value.message, options.maxAttributeLength),\n stack: value.stack\n ? truncate(value.stack, options.maxAttributeLength)\n : undefined\n };\n }\n\n if (depth >= MAX_DEPTH) {\n return '[MaxDepth]';\n }\n\n if (Array.isArray(value)) {\n return value\n .slice(0, MAX_ARRAY_ITEMS)\n .map((item) =>\n sanitizeValue(key, item, options, depth + 1)\n );\n }\n\n if (typeof value === 'object') {\n const output: Record<string, unknown> = {};\n let count = 0;\n\n for (const [childKey, childValue] of Object.entries(\n value as Record<string, unknown>\n )) {\n if (count >= options.maxAttributes) {\n output.__truncated = true;\n break;\n }\n\n output[childKey] = sanitizeValue(\n childKey,\n childValue,\n options,\n depth + 1\n );\n count++;\n }\n\n return output;\n }\n\n return truncate(String(value), options.maxAttributeLength);\n};\n\nexport const sanitizeAttributes = (\n attributes: Record<string, unknown> = {},\n options?: SanitizerOptions | SenzorOptions\n): Record<string, unknown> => {\n const limits = getLimits(options);\n const normalizedOptions: Required<SanitizerOptions> = {\n maxAttributes: limits.maxAttributes,\n maxAttributeLength: limits.maxAttributeLength\n };\n\n const output: Record<string, unknown> = {};\n let count = 0;\n\n for (const [key, value] of Object.entries(attributes)) {\n if (count >= normalizedOptions.maxAttributes) {\n output.__truncated = true;\n break;\n }\n\n output[key] = sanitizeValue(\n key,\n value,\n normalizedOptions,\n 0\n );\n count++;\n }\n\n return output;\n};\n\nexport const sanitizeHeaders = (\n headers: unknown,\n options?: SanitizerOptions | SenzorOptions\n): Record<string, unknown> => {\n if (!headers || typeof headers !== 'object') return {};\n\n const plainHeaders: Record<string, unknown> = {};\n\n if (typeof (headers as any).forEach === 'function') {\n (headers as any).forEach((value: unknown, key: string) => {\n plainHeaders[key.toLowerCase()] = value;\n });\n } else {\n for (const [key, value] of Object.entries(\n headers as Record<string, unknown>\n )) {\n plainHeaders[key.toLowerCase()] = Array.isArray(value)\n ? value.join(', ')\n : value;\n }\n }\n\n return sanitizeAttributes(plainHeaders, options);\n};\n\nexport const normalizeSql = (\n sql: unknown,\n options?: SenzorOptions\n): string | undefined => {\n if (typeof sql !== 'string') return undefined;\n\n const collapsed = sql.replace(/\\s+/g, ' ').trim();\n if (!collapsed) return undefined;\n\n const withoutLiterals = collapsed\n .replace(/'(?:''|[^'])*'/g, '?')\n .replace(/\"(?:\\\\\"|[^\"])*\"/g, '?')\n .replace(/\\b\\d+(\\.\\d+)?\\b/g, '?');\n\n return truncate(\n options?.captureDbStatement === false\n ? withoutLiterals.split(' ').slice(0, 6).join(' ')\n : withoutLiterals,\n options?.maxAttributeLength ?? DEFAULT_MAX_ATTRIBUTE_LENGTH\n );\n};\n\nexport const getSqlOperation = (sql: unknown): string | undefined => {\n if (typeof sql !== 'string') return undefined;\n const match = sql.trim().match(/^([a-z]+)/i);\n return match?.[1]?.toUpperCase();\n};\n","/**\r\n * getClientIp.ts\r\n *\r\n * Robust, proxy-aware client IP extraction.\r\n *\r\n * Priority order (mirrors Umami + industry best practice):\r\n * 1. ENV-configured custom header (CLIENT_IP_HEADER)\r\n * 2. CF-Connecting-IP (Cloudflare — single trusted IP)\r\n * 3. True-Client-IP (Cloudflare Enterprise / Akamai)\r\n * 4. X-Real-IP (Nginx realip module)\r\n * 5. Forwarded (RFC 7239 — \"for=\" field)\r\n * 6. X-Forwarded-For (De-facto standard — leftmost public IP)\r\n * 7. req.socket.remoteAddress (Direct connection fallback)\r\n *\r\n * Security note: headers 2-6 can be spoofed by clients when your server is\r\n * directly internet-facing. If that is a concern, restrict extraction to the\r\n * header your trusted reverse-proxy injects (CLIENT_IP_HEADER or X-Real-IP).\r\n */\r\n\r\nimport { isIP } from \"net\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Strip IPv4-mapped IPv6 prefix (::ffff:1.2.3.4 → 1.2.3.4) */\r\nconst stripIPv6Mapped = (ip: string): string =>\r\n ip.startsWith(\"::ffff:\") ? ip.slice(7) : ip;\r\n\r\n/** Strip optional port from an IPv4 address (1.2.3.4:5678 → 1.2.3.4). */\r\nconst stripIPv4Port = (ip: string): string => {\r\n const lastColon = ip.lastIndexOf(\":\");\r\n if (lastColon === -1) return ip;\r\n const maybeIP = ip.slice(0, lastColon);\r\n return isIP(maybeIP) === 4 ? maybeIP : ip;\r\n};\r\n\r\n/** Strip brackets + optional port from an IPv6 address ([::1]:5678 → ::1). */\r\nconst stripIPv6Brackets = (ip: string): string => {\r\n const match = ip.match(/^\\[([^\\]]+)\\](?::\\d+)?$/);\r\n return match ? match[1] : ip;\r\n};\r\n\r\n/** Normalise raw IP string into a clean, routable address (or null). */\r\nexport const normaliseIP = (raw: string | undefined | null): string | null => {\r\n if (!raw) return null;\r\n let ip = raw.trim();\r\n if (!ip) return null;\r\n\r\n ip = stripIPv6Brackets(ip);\r\n ip = stripIPv4Port(ip);\r\n ip = stripIPv6Mapped(ip);\r\n\r\n return isIP(ip) !== 0 ? ip : null;\r\n};\r\n\r\n/**\r\n * Returns true for IPs that will never produce a geo result:\r\n * loopback, link-local, private ranges, and unspecified addresses.\r\n */\r\nexport const isPrivateOrLoopback = (ip: string): boolean => {\r\n // IPv4 private / loopback / link-local\r\n if (\r\n ip === \"127.0.0.1\" ||\r\n ip.startsWith(\"10.\") ||\r\n ip.startsWith(\"192.168.\") ||\r\n ip.startsWith(\"169.254.\") || // link-local\r\n /^172\\.(1[6-9]|2\\d|3[01])\\./.test(ip) // 172.16–31\r\n )\r\n return true;\r\n\r\n // IPv6 loopback / unspecified / link-local / unique-local\r\n if (\r\n ip === \"::1\" ||\r\n ip === \"::\" ||\r\n ip.toLowerCase().startsWith(\"fe80:\") || // link-local\r\n ip.toLowerCase().startsWith(\"fc\") || // unique-local\r\n ip.toLowerCase().startsWith(\"fd\") // unique-local\r\n )\r\n return true;\r\n\r\n return false;\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// RFC 7239 \"Forwarded\" header parser\r\n// e.g. Forwarded: for=192.0.2.60;proto=http, for=\"[2001:db8::cafe]\"\r\n// ---------------------------------------------------------------------------\r\nconst parseForwardedHeader = (header: string): string | null => {\r\n const parts = header.split(\",\");\r\n for (const part of parts) {\r\n const forMatch = part.match(/for=[\"[]?([^\\]\",;>\\s]+)/i);\r\n if (forMatch) {\r\n const ip = normaliseIP(forMatch[1]);\r\n if (ip && !isPrivateOrLoopback(ip)) return ip;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// X-Forwarded-For parser — pick the leftmost *public* IP\r\n// e.g. X-Forwarded-For: client, proxy1, proxy2\r\n// ---------------------------------------------------------------------------\r\nconst parseXForwardedFor = (header: string): string | null => {\r\n const ips = header.split(\",\").map((s) => s.trim());\r\n for (const raw of ips) {\r\n const ip = normaliseIP(raw);\r\n if (ip && !isPrivateOrLoopback(ip)) return ip;\r\n }\r\n // If every hop is private (intranet-only setup) fall back to first valid IP\r\n for (const raw of ips) {\r\n const ip = normaliseIP(raw);\r\n if (ip) return ip;\r\n }\r\n return null;\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main export\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Extract the best-available client IP from a request.\r\n *\r\n * Returns `null` if no valid IP can be determined.\r\n */\r\nexport const getClientIp = (req: any): string | null => {\r\n const h = req.headers;\r\n\r\n // 2. Cloudflare single-IP header (most reliable when behind CF)\r\n {\r\n const ip = normaliseIP(h[\"cf-connecting-ip\"] as string);\r\n if (ip) return ip;\r\n }\r\n\r\n // 3. Cloudflare Enterprise / Akamai\r\n {\r\n const ip = normaliseIP(h[\"true-client-ip\"] as string);\r\n if (ip) return ip;\r\n }\r\n\r\n // 4. Nginx realip module (single, already-trusted IP)\r\n {\r\n const ip = normaliseIP(h[\"x-real-ip\"] as string);\r\n if (ip) return ip;\r\n }\r\n\r\n // 5. RFC 7239 Forwarded header\r\n {\r\n const fwd = h[\"forwarded\"] as string;\r\n if (fwd) {\r\n const ip = parseForwardedHeader(fwd);\r\n if (ip) return ip;\r\n }\r\n }\r\n\r\n // 6. De-facto standard XFF\r\n {\r\n const xff = h[\"x-forwarded-for\"] as string;\r\n if (xff) {\r\n const ip = parseXForwardedFor(xff);\r\n if (ip) return ip;\r\n }\r\n }\r\n\r\n // 7. Direct TCP connection (local dev / no proxy)\r\n {\r\n const raw = req.socket?.remoteAddress;\r\n const ip = normaliseIP(raw);\r\n if (ip) return ip;\r\n }\r\n\r\n return null;\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};","const PATCHES = Symbol.for('senzor.patch.keys');\nconst ORIGINAL = Symbol.for('senzor.patch.original');\n\ntype WrappedFunction = Function & {\n [PATCHES]?: Set<string>;\n [ORIGINAL]?: Function;\n};\n\nexport const patchMethod = (\n target: any,\n methodName: string,\n patchKey: string,\n wrapper: (original: Function) => Function\n): boolean => {\n if (!target) return false;\n\n const current = target[methodName] as WrappedFunction | undefined;\n if (typeof current !== 'function') return false;\n\n const existingPatches = current[PATCHES];\n if (existingPatches?.has(patchKey)) return false;\n\n const original = current[ORIGINAL] || current;\n const wrapped = wrapper(current) as WrappedFunction;\n const patches = new Set(existingPatches || []);\n patches.add(patchKey);\n\n try {\n Object.defineProperty(wrapped, PATCHES, {\n value: patches,\n enumerable: false\n });\n Object.defineProperty(wrapped, ORIGINAL, {\n value: original,\n enumerable: false\n });\n } catch {\n return false;\n }\n\n try {\n target[methodName] = wrapped;\n return true;\n } catch {\n return false;\n }\n};\n\nexport const isPatched = (\n target: any,\n methodName: string,\n patchKey: string\n): boolean => {\n const current = target?.[methodName] as WrappedFunction | undefined;\n return Boolean(current?.[PATCHES]?.has(patchKey));\n};\n","import { randomUUID } from 'crypto';\n\nexport const generateTraceId = (): string =>\n randomUUID().replace(/-/g, '');\n\nexport const generateSpanId = (): string =>\n randomUUID().replace(/-/g, '').slice(0, 16);\n","import { Context } from '../core/context';\nimport { sanitizeAttributes } from '../core/sanitizer';\nimport { ActiveTrace, SenzorOptions, Span } from '../core/types';\nimport { generateSpanId } from '../utils/ids';\n\ntype SpanType = Span['type'];\n\nexport interface CapturedSpan {\n spanId: string;\n parentSpanId?: string;\n trace?: ActiveTrace;\n end: (\n status?: number,\n meta?: Record<string, unknown>\n ) => void;\n}\n\nexport const startCapturedSpan = (\n name: string,\n type: SpanType,\n meta: Record<string, unknown> = {},\n options?: SenzorOptions\n): CapturedSpan | null => {\n const trace = Context.current();\n if (!trace) return null;\n\n const spanId = generateSpanId();\n const parentSpanId = trace.activeSpanId;\n const startTime = performance.now() - trace.startTime;\n const startedAt = performance.now();\n let ended = false;\n\n return {\n spanId,\n parentSpanId,\n trace,\n end: (\n status?: number,\n extraMeta: Record<string, unknown> = {}\n ) => {\n if (ended) return;\n ended = true;\n\n const mergedMeta = sanitizeAttributes(\n {\n ...meta,\n ...extraMeta,\n parentSpanId\n },\n options\n );\n\n Context.addSpanToTrace(trace, {\n spanId,\n parentSpanId,\n name,\n type,\n startTime,\n duration: performance.now() - startedAt,\n status,\n meta: mergedMeta\n });\n }\n };\n};\n\nexport const runWithCapturedSpan = <T>(\n span: CapturedSpan | null,\n fn: () => T\n): T => {\n if (!span) return fn();\n return Context.withActiveSpan(span.spanId, fn);\n};\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 { SenzorOptions } from '../core/types';\nimport { hookRequire } from './hook';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst collectionName = (collection: any): string =>\n collection?.collectionName ||\n collection?.s?.namespace?.collection ||\n collection?.namespace?.collection ||\n 'unknown';\n\nconst databaseName = (collection: any): string | undefined =>\n collection?.dbName ||\n collection?.s?.namespace?.db ||\n collection?.namespace?.db;\n\nconst cursorCollectionName = (cursor: any): string =>\n cursor?.namespace?.collection ||\n cursor?.ns?.collection ||\n cursor?.cursorNamespace?.collection ||\n 'unknown';\n\nconst patchCollectionMethod = (\n proto: any,\n method: string,\n options?: SenzorOptions\n) => {\n patchMethod(\n proto,\n method,\n `senzor.mongodb.collection.${method}`,\n (original) =>\n function patchedMongoCollection(this: any, ...args: any[]) {\n const collection = collectionName(this);\n const span = startCapturedSpan(\n `MongoDB ${method}`,\n 'db',\n {\n collection,\n operation: method,\n 'db.system.name': 'mongodb',\n 'db.collection.name': collection,\n 'db.namespace': databaseName(this)\n ? `${databaseName(this)}.${collection}`\n : collection,\n 'db.operation.name': method,\n library: 'mongodb'\n },\n options\n );\n\n if (!span) return original.apply(this, args);\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.apply(this, args);\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(0, {\n matchedCount: value?.matchedCount,\n modifiedCount: value?.modifiedCount,\n deletedCount: value?.deletedCount,\n insertedCount: value?.insertedCount\n });\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n span.end(0);\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchCursorMethod = (\n proto: any,\n method: string,\n operation: string,\n options?: SenzorOptions\n) => {\n patchMethod(\n proto,\n method,\n `senzor.mongodb.cursor.${operation}.${method}`,\n (original) =>\n function patchedMongoCursor(this: any, ...args: any[]) {\n const collection = cursorCollectionName(this);\n const span = startCapturedSpan(\n `MongoDB ${operation}`,\n 'db',\n {\n collection,\n operation,\n 'db.system.name': 'mongodb',\n 'db.collection.name': collection,\n 'db.operation.name': operation,\n library: 'mongodb'\n },\n options\n );\n\n if (!span) return original.apply(this, args);\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.apply(this, args);\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(0, {\n resultCount: Array.isArray(value) ? value.length : undefined\n });\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n span.end(0);\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchMongo = (mongodb: any, options?: SenzorOptions) => {\n const Collection = mongodb?.Collection || mongodb?.default?.Collection;\n const collectionProto = Collection?.prototype;\n\n [\n 'insertOne',\n 'insertMany',\n 'updateOne',\n 'updateMany',\n 'replaceOne',\n 'deleteOne',\n 'deleteMany',\n 'findOne',\n 'findOneAndUpdate',\n 'findOneAndDelete',\n 'findOneAndReplace',\n 'countDocuments',\n 'estimatedDocumentCount',\n 'distinct',\n 'bulkWrite',\n 'createIndex',\n 'dropIndex'\n ].forEach((method) =>\n patchCollectionMethod(collectionProto, method, options)\n );\n\n const FindCursor =\n mongodb?.FindCursor || mongodb?.default?.FindCursor;\n const AggregationCursor =\n mongodb?.AggregationCursor || mongodb?.default?.AggregationCursor;\n\n ['toArray', 'next', 'forEach'].forEach((method) =>\n patchCursorMethod(FindCursor?.prototype, method, 'find', options)\n );\n ['toArray', 'next', 'forEach'].forEach((method) =>\n patchCursorMethod(\n AggregationCursor?.prototype,\n method,\n 'aggregate',\n options\n )\n );\n};\n\nexport const instrumentMongo = (options?: SenzorOptions) => {\n hookRequire('mongodb', (exports: any) => patchMongo(exports, options));\n};\n","import { getSqlOperation, normalizeSql } from '../core/sanitizer';\nimport { SenzorOptions } from '../core/types';\nimport { hookRequire } from './hook';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst extractSql = (args: any[]): string | undefined => {\n const first = args[0];\n if (typeof first === 'string') return first;\n if (first && typeof first.text === 'string') return first.text;\n return undefined;\n};\n\nconst wrapQueryMethod = (\n proto: any,\n label: string,\n options?: SenzorOptions\n) => {\n patchMethod(\n proto,\n 'query',\n `senzor.pg.${label}.query`,\n (original) =>\n function patchedPgQuery(this: any, ...args: any[]) {\n const sql = extractSql(args);\n const operation = getSqlOperation(sql) || 'QUERY';\n const span = startCapturedSpan(\n `Postgres ${operation}`,\n 'db',\n {\n query: normalizeSql(sql, options),\n operation,\n 'db.system.name': 'postgresql',\n 'db.operation.name': operation,\n 'db.query.text': normalizeSql(sql, options),\n library: 'pg'\n },\n options\n );\n\n if (!span) return original.apply(this, args);\n\n const callbackIndex = args.findIndex(\n (arg) => typeof arg === 'function'\n );\n\n if (callbackIndex >= 0) {\n const originalCallback = args[callbackIndex];\n args[callbackIndex] = function wrappedPgCallback(\n this: unknown,\n err: Error | null,\n result: any\n ) {\n span.end(err ? 500 : 0, {\n error: err?.message,\n 'error.type': err?.name,\n rowCount: result?.rowCount,\n 'db.response.row_count': result?.rowCount\n });\n\n return originalCallback.apply(this, arguments as any);\n };\n }\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.apply(this, args);\n\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(0, {\n rowCount: value?.rowCount,\n 'db.response.row_count': value?.rowCount\n });\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n if (\n callbackIndex < 0 &&\n result &&\n typeof result.once === 'function'\n ) {\n result.once('end', () => span.end(0));\n result.once('error', (error: Error) =>\n span.end(500, {\n error: error.message,\n 'error.type': error.name\n })\n );\n } else if (callbackIndex < 0) {\n span.end(0);\n }\n\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchPg = (pg: any, options?: SenzorOptions) => {\n if (!pg) return;\n\n wrapQueryMethod(pg.Client?.prototype, 'client', options);\n wrapQueryMethod(pg.Pool?.prototype, 'pool', options);\n\n if (pg.default) {\n wrapQueryMethod(pg.default.Client?.prototype, 'default.client', options);\n wrapQueryMethod(pg.default.Pool?.prototype, 'default.pool', options);\n }\n};\n\nexport const instrumentPg = (options?: SenzorOptions) => {\n hookRequire('pg', (exports: any) => patchPg(exports, options));\n};\n","import { normalizePath } from '../core/normalizer';\nimport { SenzorOptions } from '../core/types';\nimport { SENZOR_INTERNAL_HEADER } from '../utils/internal';\nimport { generateTraceparent } from '../utils/traceContext';\nimport { hookRequire } from './hook';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst hasInternalHeader = (headers: any): boolean => {\n if (!headers) return false;\n if (Array.isArray(headers)) {\n return headers.some(\n ([key, value]) =>\n String(key).toLowerCase() === SENZOR_INTERNAL_HEADER &&\n String(value).toLowerCase() === 'true'\n );\n }\n\n return Object.entries(headers).some(\n ([key, value]) =>\n key.toLowerCase() === SENZOR_INTERNAL_HEADER &&\n String(value).toLowerCase() === 'true'\n );\n};\n\nconst setHeader = (headers: any, key: string, value: string) => {\n if (Array.isArray(headers)) {\n headers.push([key, value]);\n return headers;\n }\n\n const nextHeaders = { ...(headers || {}) };\n const existingKey = Object.keys(nextHeaders).find(\n (header) => header.toLowerCase() === key.toLowerCase()\n );\n nextHeaders[existingKey || key] = value;\n return nextHeaders;\n};\n\nconst getUrlDetails = (input: any) => {\n try {\n const url = new URL(String(input));\n return {\n url: url.toString(),\n hostname: url.hostname,\n path: `${url.pathname}${url.search}`\n };\n } catch {\n return {\n url: String(input || ''),\n hostname: 'unknown',\n path: '/'\n };\n }\n};\n\nconst patchRequestLike = (\n target: any,\n methodName: string,\n patchKey: string,\n options?: SenzorOptions\n) => {\n patchMethod(\n target,\n methodName,\n patchKey,\n (original) =>\n function patchedUndiciRequest(this: any, input: any, opts?: any, cb?: any) {\n if (hasInternalHeader(opts?.headers)) {\n return original.apply(this, arguments as any);\n }\n\n const details = getUrlDetails(input?.origin ? input.origin : input);\n const method = String(opts?.method || 'GET').toUpperCase();\n const span = startCapturedSpan(\n `${method} ${details.hostname}`,\n 'http',\n {\n url: details.url,\n method,\n route: normalizePath(details.path),\n library: 'undici',\n 'http.request.method': method,\n 'url.full': details.url,\n 'url.path': details.path,\n 'server.address': details.hostname\n },\n options\n );\n\n if (!span) return original.apply(this, arguments as any);\n\n const nextOptions = { ...(opts || {}) };\n nextOptions.headers = setHeader(\n nextOptions.headers,\n 'traceparent',\n generateTraceparent(span.trace!.id, span.spanId)\n );\n nextOptions.headers = setHeader(\n nextOptions.headers,\n 'x-senzor-trace-id',\n span.trace!.id\n );\n nextOptions.headers = setHeader(\n nextOptions.headers,\n 'x-senzor-parent-span-id',\n span.spanId\n );\n\n const wrappedCallback =\n typeof cb === 'function'\n ? function wrappedUndiciCallback(this: unknown, err: any, data: any) {\n span.end(err ? 500 : data?.statusCode || 0, {\n error: err?.message,\n 'error.type': err?.name,\n 'http.response.status_code': data?.statusCode\n });\n return cb.apply(this, arguments as any);\n }\n : cb;\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.call(\n this,\n input,\n nextOptions,\n wrappedCallback\n );\n\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(value?.statusCode || value?.status || 0, {\n 'http.response.status_code':\n value?.statusCode || value?.status\n });\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n if (typeof wrappedCallback !== 'function') {\n span.end(0);\n }\n\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchUndici = (undici: any, options?: SenzorOptions) => {\n patchRequestLike(undici, 'request', 'senzor.undici.request', options);\n patchRequestLike(undici, 'stream', 'senzor.undici.stream', options);\n patchRequestLike(undici, 'pipeline', 'senzor.undici.pipeline', options);\n\n [\n undici?.Client?.prototype,\n undici?.Pool?.prototype,\n undici?.Agent?.prototype,\n undici?.ProxyAgent?.prototype\n ].forEach((proto, index) => {\n patchRequestLike(\n proto,\n 'request',\n `senzor.undici.dispatcher.${index}.request`,\n options\n );\n });\n};\n\nexport const instrumentUndici = (options?: SenzorOptions) => {\n hookRequire('undici', (exports: any) => patchUndici(exports, options));\n};\n","import { SenzorOptions } from '../core/types';\nimport { hookRequire } from './hook';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst getCommandName = (command: any): string => {\n if (typeof command === 'string') return command.toUpperCase();\n if (Array.isArray(command)) return String(command[0] || 'COMMAND').toUpperCase();\n if (command?.name) return String(command.name).toUpperCase();\n if (Array.isArray(command?.args)) return String(command.args[0] || 'COMMAND').toUpperCase();\n return 'COMMAND';\n};\n\nconst patchSendCommand = (\n target: any,\n label: string,\n options?: SenzorOptions\n) => {\n patchMethod(\n target,\n 'sendCommand',\n `senzor.redis.${label}.sendCommand`,\n (original) =>\n function patchedRedisSendCommand(this: any, command: any, ...args: any[]) {\n const commandName = getCommandName(command);\n const span = startCapturedSpan(\n `Redis ${commandName}`,\n 'db',\n {\n command: commandName,\n operation: commandName,\n 'db.system.name': label === 'ioredis' ? 'redis' : 'redis',\n 'db.operation.name': commandName,\n library: label\n },\n options\n );\n\n if (!span) return original.apply(this, arguments as any);\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.call(this, command, ...args);\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(0);\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n span.end(0);\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchCreatedClient = (\n client: any,\n label: string,\n options?: SenzorOptions\n) => {\n patchSendCommand(client, label, options);\n patchSendCommand(Object.getPrototypeOf(client), label, options);\n return client;\n};\n\nconst patchRedisPackage = (redis: any, options?: SenzorOptions) => {\n ['createClient', 'createCluster'].forEach((factory) => {\n patchMethod(\n redis,\n factory,\n `senzor.redis.${factory}`,\n (original) =>\n function patchedRedisFactory(this: any, ...args: any[]) {\n const client = original.apply(this, args);\n return patchCreatedClient(client, 'redis', options);\n }\n );\n });\n};\n\nconst patchIORedisPackage = (ioredis: any, options?: SenzorOptions) => {\n patchSendCommand(ioredis?.prototype, 'ioredis', options);\n patchSendCommand(ioredis?.Redis?.prototype, 'ioredis', options);\n patchSendCommand(ioredis?.Cluster?.prototype, 'ioredis-cluster', options);\n patchSendCommand(ioredis?.default?.prototype, 'ioredis', options);\n};\n\nexport const instrumentRedis = (options?: SenzorOptions) => {\n hookRequire('redis', (exports: any) => patchRedisPackage(exports, options));\n hookRequire('ioredis', (exports: any) => patchIORedisPackage(exports, options));\n};\n","import { getSqlOperation, normalizeSql } from '../core/sanitizer';\nimport { SenzorOptions } from '../core/types';\nimport { hookRequire } from './hook';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst extractSql = (args: any[]): string | undefined => {\n const first = args[0];\n if (typeof first === 'string') return first;\n if (first && typeof first.sql === 'string') return first.sql;\n return undefined;\n};\n\nconst patchSqlMethod = (\n proto: any,\n method: 'query' | 'execute',\n library: string,\n options?: SenzorOptions\n) => {\n patchMethod(\n proto,\n method,\n `senzor.${library}.${method}`,\n (original) =>\n function patchedMysqlMethod(this: any, ...args: any[]) {\n const sql = extractSql(args);\n const operation = getSqlOperation(sql) || method.toUpperCase();\n const span = startCapturedSpan(\n `MySQL ${operation}`,\n 'db',\n {\n query: normalizeSql(sql, options),\n operation,\n 'db.system.name': 'mysql',\n 'db.operation.name': operation,\n 'db.query.text': normalizeSql(sql, options),\n library\n },\n options\n );\n\n if (!span) return original.apply(this, args);\n\n const callbackIndex = args.findIndex(\n (arg) => typeof arg === 'function'\n );\n if (callbackIndex >= 0) {\n const originalCallback = args[callbackIndex];\n args[callbackIndex] = function wrappedMysqlCallback(\n this: unknown,\n err: any,\n rows: any\n ) {\n span.end(err ? 500 : 0, {\n error: err?.message,\n 'error.type': err?.name,\n rowCount: Array.isArray(rows) ? rows.length : undefined\n });\n return originalCallback.apply(this, arguments as any);\n };\n }\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.apply(this, args);\n\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n const rows = Array.isArray(value) ? value[0] : value;\n span.end(0, {\n rowCount: Array.isArray(rows) ? rows.length : undefined\n });\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n if (\n callbackIndex < 0 &&\n result &&\n typeof result.once === 'function'\n ) {\n result.once('end', () => span.end(0));\n result.once('error', (error: Error) =>\n span.end(500, {\n error: error.message,\n 'error.type': error.name\n })\n );\n } else if (callbackIndex < 0) {\n span.end(0);\n }\n\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchKnownPrototypes = (\n mysql: any,\n library: string,\n options?: SenzorOptions\n) => {\n [\n mysql?.Connection?.prototype,\n mysql?.Pool?.prototype,\n mysql?.PoolConnection?.prototype,\n mysql?.PromiseConnection?.prototype,\n mysql?.PromisePool?.prototype,\n mysql?.default?.Connection?.prototype,\n mysql?.default?.Pool?.prototype\n ].forEach((proto) => {\n patchSqlMethod(proto, 'query', library, options);\n patchSqlMethod(proto, 'execute', library, options);\n });\n};\n\nconst patchFactories = (\n mysql: any,\n library: string,\n options?: SenzorOptions\n) => {\n ['createConnection', 'createPool'].forEach((factory) => {\n patchMethod(\n mysql,\n factory,\n `senzor.${library}.${factory}`,\n (original) =>\n function patchedMysqlFactory(this: any, ...args: any[]) {\n const client = original.apply(this, args);\n patchSqlMethod(client, 'query', library, options);\n patchSqlMethod(client, 'execute', library, options);\n patchSqlMethod(Object.getPrototypeOf(client), 'query', library, options);\n patchSqlMethod(Object.getPrototypeOf(client), 'execute', library, options);\n return client;\n }\n );\n });\n};\n\nconst patchMysql = (\n mysql: any,\n library: string,\n options?: SenzorOptions\n) => {\n patchKnownPrototypes(mysql, library, options);\n patchFactories(mysql, library, options);\n};\n\nexport const instrumentMysql = (options?: SenzorOptions) => {\n hookRequire('mysql', (exports: any) => patchMysql(exports, 'mysql', options));\n hookRequire('mysql2', (exports: any) => patchMysql(exports, 'mysql2', options));\n};\n","import { SenzorOptions } from '../core/types';\nimport { hookRequire } from './hook';\nimport { patchMethod } from './patch';\nimport { runWithCapturedSpan, startCapturedSpan } from './span';\n\nconst modelName = (target: any): string =>\n target?.model?.modelName ||\n target?.constructor?.modelName ||\n target?.modelName ||\n 'unknown';\n\nconst collectionName = (target: any): string =>\n target?.mongooseCollection?.name ||\n target?.collection?.name ||\n target?.model?.collection?.name ||\n 'unknown';\n\nconst patchExec = (\n proto: any,\n label: 'query' | 'aggregate',\n options?: SenzorOptions\n) => {\n patchMethod(\n proto,\n 'exec',\n `senzor.mongoose.${label}.exec`,\n (original) =>\n function patchedMongooseExec(this: any, ...args: any[]) {\n const operation =\n String(this?.op || this?._op || label).toUpperCase();\n const collection = collectionName(this);\n const span = startCapturedSpan(\n `Mongoose ${operation}`,\n 'db',\n {\n collection,\n model: modelName(this),\n operation,\n 'db.system.name': 'mongodb',\n 'db.collection.name': collection,\n 'db.operation.name': operation,\n library: 'mongoose'\n },\n options\n );\n\n if (!span) return original.apply(this, args);\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.apply(this, args);\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(0, {\n resultCount: Array.isArray(value) ? value.length : undefined\n });\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n span.end(0);\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchSave = (modelProto: any, options?: SenzorOptions) => {\n patchMethod(\n modelProto,\n 'save',\n 'senzor.mongoose.model.save',\n (original) =>\n function patchedMongooseSave(this: any, ...args: any[]) {\n const collection = collectionName(this);\n const span = startCapturedSpan(\n 'Mongoose SAVE',\n 'db',\n {\n collection,\n model: modelName(this),\n operation: 'SAVE',\n 'db.system.name': 'mongodb',\n 'db.collection.name': collection,\n 'db.operation.name': 'SAVE',\n library: 'mongoose'\n },\n options\n );\n\n if (!span) return original.apply(this, args);\n\n return runWithCapturedSpan(span, () => {\n try {\n const result = original.apply(this, args);\n if (result && typeof result.then === 'function') {\n return result.then(\n (value: any) => {\n span.end(0);\n return value;\n },\n (error: any) => {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n );\n }\n\n span.end(0);\n return result;\n } catch (error: any) {\n span.end(500, {\n error: error?.message,\n 'error.type': error?.name || 'Error'\n });\n throw error;\n }\n });\n }\n );\n};\n\nconst patchMongoose = (mongoose: any, options?: SenzorOptions) => {\n patchExec(mongoose?.Query?.prototype, 'query', options);\n patchExec(mongoose?.Aggregate?.prototype, 'aggregate', options);\n patchSave(mongoose?.Model?.prototype, options);\n\n if (mongoose?.default) {\n patchExec(mongoose.default?.Query?.prototype, 'query', options);\n patchExec(mongoose.default?.Aggregate?.prototype, 'aggregate', options);\n patchSave(mongoose.default?.Model?.prototype, options);\n }\n};\n\nexport const instrumentMongoose = (options?: SenzorOptions) => {\n hookRequire('mongoose', (exports: any) => patchMongoose(exports, options));\n};\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.2.0\",\r\n \"description\": \"Universal APM SDK for Senzor\",\r\n \"main\": \"dist/index.js\",\r\n \"types\": \"dist/index.d.ts\",\r\n \"exports\": {\r\n \".\": {\r\n \"types\": \"./dist/index.d.ts\",\r\n \"require\": \"./dist/index.js\",\r\n \"import\": \"./dist/index.mjs\"\r\n },\r\n \"./register\": {\r\n \"types\": \"./dist/register.d.ts\",\r\n \"require\": \"./dist/register.js\",\r\n \"import\": \"./dist/register.mjs\"\r\n }\r\n },\r\n \"scripts\": {\r\n \"build\": \"tsup\",\r\n \"prepublishOnly\": \"npm run build\"\r\n },\r\n \"devDependencies\": {\r\n \"@types/node\": \"^20.19.41\",\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';\n\nconst truthy = (value: string | undefined): boolean =>\n value === '1' || value === 'true' || value === 'yes';\n\nconst numberFromEnv = (value: string | undefined): number | undefined => {\n if (!value) return undefined;\n const parsed = Number(value);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n};\n\nconst apiKey =\n process.env.SENZOR_API_KEY ||\n process.env.SENZOR_APM_API_KEY ||\n process.env.SENZOR_SERVICE_API_KEY;\n\nconst endpoint =\n process.env.SENZOR_ENDPOINT ||\n process.env.SENZOR_APM_ENDPOINT;\n\nconst options = {\n apiKey: apiKey || '',\n endpoint,\n debug: truthy(process.env.SENZOR_DEBUG),\n autoLogs: process.env.SENZOR_AUTO_LOGS === 'false' ? false : undefined,\n batchSize: numberFromEnv(process.env.SENZOR_BATCH_SIZE),\n flushInterval: numberFromEnv(process.env.SENZOR_FLUSH_INTERVAL),\n flushTimeoutMs: numberFromEnv(process.env.SENZOR_FLUSH_TIMEOUT_MS),\n maxQueueSize: numberFromEnv(process.env.SENZOR_MAX_QUEUE_SIZE),\n maxSpansPerTrace: numberFromEnv(process.env.SENZOR_MAX_SPANS_PER_TRACE),\n captureHeaders: truthy(process.env.SENZOR_CAPTURE_HEADERS),\n captureDbStatement:\n process.env.SENZOR_CAPTURE_DB_STATEMENT === 'false'\n ? false\n : undefined\n};\n\nif (apiKey) {\n client.init(options);\n} else {\n client.preload(options);\n}\n"],"mappings":"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","names":["SENZOR_INTERNAL_HEADER","Transport","config","baseEndpoint","trace","task","error","type","log","queue","item","maxQueueSize","items","totalApm","totalTask","payload","endpoint","controller","timeout","response","SENZOR_INTERNAL_HEADER","apmPayload","taskPayload","sends","failures","result","err","key","proc","flushSyncBestEffort","AsyncLocalStorage","storage","Context","trace","fn","spanId","store","span","maxSpans","randomUUID","http","https","URL","normalizePath","path","getRoute","req","fallbackPath","DEFAULT_MAX_ATTRIBUTES","DEFAULT_MAX_ATTRIBUTE_LENGTH","MAX_DEPTH","MAX_ARRAY_ITEMS","SENSITIVE_KEY_PATTERN","getLimits","options","truncate","value","maxLength","isSensitiveKey","key","sanitizePrimitive","sanitizeValue","depth","primitive","item","output","count","childKey","childValue","sanitizeAttributes","attributes","limits","normalizedOptions","sanitizeHeaders","headers","plainHeaders","normalizeSql","sql","collapsed","withoutLiterals","getSqlOperation","isIP","stripIPv6Mapped","ip","stripIPv4Port","lastColon","maybeIP","stripIPv6Brackets","match","normaliseIP","raw","isPrivateOrLoopback","parseForwardedHeader","header","parts","part","forMatch","parseXForwardedFor","ips","s","getClientIp","req","h","fwd","xff","TRACEPARENT_REGEX","parseTraceparent","header","traceparent","match","traceId","parentSpanId","flags","sampled","generateTraceparent","spanId","PATCHES","ORIGINAL","patchMethod","target","methodName","patchKey","wrapper","current","existingPatches","original","wrapped","patches","randomUUID","generateTraceId","generateSpanId","startCapturedSpan","name","type","meta","options","trace","Context","spanId","generateSpanId","parentSpanId","startTime","startedAt","ended","status","extraMeta","mergedMeta","sanitizeAttributes","runWithCapturedSpan","span","fn","getDebug","options","isPlainObject","value","URL","headerValue","headers","key","name","normalizedKey","hasInternalHeader","SENZOR_INTERNAL_HEADER","shouldIgnoreUrl","urlString","ingestUrl","url","ingest","cloneHeaders","cloned","acc","setHeader","existingKey","header","prepareRequestArgs","args","defaultProtocol","nextArgs","optionsIndex","urlFromArg","protocol","hostname","path","method","resolveIncomingRoute","req","res","getRoute","normalizePath","patchIncomingServer","proto","client","patchMethod","original","event","Context","rawPath","getClientIp","sanitizeHeaders","trace","finalized","finalize","reason","error","patchOutgoing","moduleRef","patchKeyPrefix","requestWrapper","prepared","span","startCapturedSpan","generateTraceparent","invoke","completed","endSpan","status","extraMeta","statusCode","finish","runWithCapturedSpan","instrumentFetch","input","init","originalHeaders","nextInit","response","instrumentHttp","http","https","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","collectionName","collection","databaseName","cursorCollectionName","cursor","patchCollectionMethod","proto","method","options","patchMethod","original","args","span","startCapturedSpan","runWithCapturedSpan","result","value","error","patchCursorMethod","operation","patchMongo","mongodb","collectionProto","FindCursor","AggregationCursor","instrumentMongo","hookRequire","exports","extractSql","args","first","wrapQueryMethod","proto","label","options","patchMethod","original","sql","operation","getSqlOperation","span","startCapturedSpan","normalizeSql","callbackIndex","arg","originalCallback","err","result","runWithCapturedSpan","value","error","patchPg","pg","instrumentPg","hookRequire","exports","hasInternalHeader","headers","key","value","SENZOR_INTERNAL_HEADER","setHeader","nextHeaders","existingKey","header","getUrlDetails","input","url","patchRequestLike","target","methodName","patchKey","options","patchMethod","original","opts","cb","details","method","span","startCapturedSpan","normalizePath","nextOptions","generateTraceparent","wrappedCallback","err","data","runWithCapturedSpan","result","error","patchUndici","undici","proto","index","instrumentUndici","hookRequire","exports","getCommandName","command","patchSendCommand","target","label","options","patchMethod","original","args","commandName","span","startCapturedSpan","runWithCapturedSpan","result","value","error","patchCreatedClient","client","patchRedisPackage","redis","factory","patchIORedisPackage","ioredis","instrumentRedis","hookRequire","exports","extractSql","args","first","patchSqlMethod","proto","method","library","options","patchMethod","original","sql","operation","getSqlOperation","span","startCapturedSpan","normalizeSql","callbackIndex","arg","originalCallback","err","rows","runWithCapturedSpan","result","value","error","patchKnownPrototypes","mysql","patchFactories","factory","client","patchMysql","instrumentMysql","hookRequire","exports","modelName","target","collectionName","patchExec","proto","label","options","patchMethod","original","args","operation","collection","span","startCapturedSpan","runWithCapturedSpan","result","value","error","patchSave","modelProto","patchMongoose","mongoose","instrumentMongoose","hookRequire","exports","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","safeStringify","obj","cache","key","value","SenzorClient","options","endpoint","debug","Transport","name","setting","instrumentHttp","instrumentFetch","instrumentUndici","instrumentMongo","instrumentMongoose","instrumentPg","instrumentMysql","instrumentRedis","instrumentBullMQ","instrumentNodeCron","levels","originalConsole","isIntercepting","level","args","message","attributes","arg","parsed","sanitizeAttributes","currentTrace","Context","logType","logPayload","getProcessContext","getMemoryContext","mem","safeCapture","error","meta","parsedError","enrichedMeta","SDK_META","internalFailure","reason","warning","type","promise","data","next","existingTrace","inheritedTraceId","inheritedParentSpanId","getHeader","traceparent","parsedContext","parseTraceparent","rawTrace","rawSpan","activeTraceId","generateTraceId","rootSpanId","generateSpanId","trace","status","extraData","duration","payload","currentContext","triggerTraceId","startMemory","startCpu","task","randomUUID","extraMetadata","resourceMetrics","endMemory","cpuDelta","fn","result","context","errPayload","span","startCapturedSpan","client","truthy","value","numberFromEnv","parsed","apiKey","endpoint","options","client"]}
|
package/package.json
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@senzops/apm-node",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Universal APM SDK for Senzor",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"import": "./dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"./register": {
|
|
14
|
+
"types": "./dist/register.d.ts",
|
|
15
|
+
"require": "./dist/register.js",
|
|
16
|
+
"import": "./dist/register.mjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
7
19
|
"scripts": {
|
|
8
|
-
"build": "tsup
|
|
20
|
+
"build": "tsup",
|
|
9
21
|
"prepublishOnly": "npm run build"
|
|
10
22
|
},
|
|
11
|
-
"dependencies": {},
|
|
12
23
|
"devDependencies": {
|
|
13
|
-
"@types/node": "^20.
|
|
24
|
+
"@types/node": "^20.19.41",
|
|
14
25
|
"tsup": "^8.0.0",
|
|
15
26
|
"typescript": "^5.0.0"
|
|
16
27
|
},
|