@lunora/container 1.0.0-alpha.44 → 1.0.0-alpha.46

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/dist/bridge.mjs CHANGED
@@ -1 +1 @@
1
- import{LunoraError as u}from"@lunora/errors";const h="/_lunora/rpc";class w extends u{constructor(r,e){super(r,e,{name:"ContainerBridgeError"})}}const p=(t,r)=>{let e=t;for(;e.endsWith("/");)e=e.slice(0,-1);return`${e}${r}`},g=(t,r)=>new Error(`createContainerBridge: request to "${t}" failed (status ${String(r.status)}${r.statusText?` ${r.statusText}`:""})`),m=async(t,r)=>{try{return await t.json()}catch{throw t.ok?new u("INTERNAL",`createContainerBridge: request to "${r}" returned a non-JSON response (status ${String(t.status)})`):g(r,t)}},B=t=>{if(typeof t.baseUrl!="string"||t.baseUrl.length===0)throw new TypeError("createContainerBridge: `baseUrl` must be a non-empty Worker URL (e.g. https://my-app.workers.dev) — is the URL env var set?");const r=t.fetch??globalThis.fetch,e=async(n,i={},c)=>{if(typeof r!="function")throw new TypeError("createContainerBridge: no `fetch` available — pass `fetch` in options for this runtime.");const d={"content-type":"application/json"};t.token!==void 0&&(d.authorization=`Bearer ${t.token}`);const s=await r(p(t.baseUrl,h),{body:JSON.stringify({args:i,functionPath:n,shardKey:c}),headers:d,method:"POST"}),o=await m(s,n);if(typeof o=="object"&&o!==null&&"error"in o){const{error:a}=o;if(typeof a=="object"&&a!==null){const{code:f,message:y}=a;if(typeof f=="string"&&typeof y=="string")throw new w(f,y)}let l;try{l=JSON.stringify(a)}catch{l=String(a)}throw new u("INTERNAL",`createContainerBridge: request to "${n}" returned a malformed error envelope (status ${String(s.status)}): ${l}`)}if(!s.ok)throw g(n,s);return o.result};return{action:e,call:e,mutation:e,query:e,run:async(n,i,c)=>e(n.__lunoraRef,i,c)}};export{w as ContainerBridgeError,B as createContainerBridge};
1
+ import{LunoraError as p}from"@lunora/errors";const m=r=>{let t="";for(let c=0;c<r.length;c+=32768)t+=String.fromCharCode(...r.subarray(c,c+32768));return btoa(t)},R=r=>{const t=atob(r),o=new Uint8Array(t.length);for(let c=0;c<t.length;c+=1)o[c]=t.codePointAt(c)??0;return o},f="$lunora.wire$",w=64,E=1024,g="__proto__",j={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},O={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},U=r=>{if(r===null||typeof r!="object")return!1;const t=Object.getPrototypeOf(r);return t===null||t===Object.prototype},d=(r,t=0)=>{if(t>w)throw new RangeError(`wire-codec: value nesting exceeds the ${w}-level limit`);if(r===void 0)return[f,"undefined"];if(r===null)return null;const o=typeof r;if(o==="bigint")return[f,"bigint",r.toString()];if(o==="number"){const e=r;return Number.isNaN(e)?[f,"nan"]:e===1/0?[f,"inf"]:e===-1/0?[f,"-inf"]:e}if(o!=="object")return r;if(r instanceof Date)return[f,"date",d(r.getTime(),t+1)];if(r instanceof Error){const e=r,n={};for(const i of Object.keys(e)){if(e[i]===void 0)continue;const u=d(e[i],t+1);i===g?Object.defineProperty(n,i,{configurable:!0,enumerable:!0,value:u,writable:!0}):n[i]=u}const a=[f,"error",String(e.name),String(e.message),n];return e.cause!==void 0&&a.push(d(e.cause,t+1)),a}if(r instanceof URL)return[f,"url",r.href];if(r instanceof Map)return[f,"map",[...r.entries()].map(([e,n])=>[d(e,t+1),d(n,t+1)])];if(r instanceof Set)return[f,"set",[...r].map(e=>d(e,t+1))];if(r instanceof ArrayBuffer)return[f,"bytes",m(new Uint8Array(r)),"ArrayBuffer"];if(ArrayBuffer.isView(r)){const e=r,n=e.constructor.name,a=new Uint8Array(e.buffer,e.byteOffset,e.byteLength);return n==="Uint8Array"?[f,"bytes",m(a)]:[f,"bytes",m(a),n]}if(Array.isArray(r)){const e=r.map(n=>d(n,t+1));return e.length>0&&e[0]===f?[f,"arr",e]:e}if(!U(r)){const e=r.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${e} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const c=r,s={};for(const e of Object.keys(c)){const n=c[e];if(n===void 0)continue;const a=d(n,t+1);e===g?Object.defineProperty(s,e,{configurable:!0,enumerable:!0,value:a,writable:!0}):s[e]=a}return s},b=(r,t=0)=>{if(t>w)throw new RangeError(`wire-codec: value nesting exceeds the ${w}-level limit`);if(r===null||typeof r!="object")return r;if(Array.isArray(r)){if(r[0]===f)switch(r[1]){case"-inf":return-1/0;case"arr":return r[2].map(e=>b(e,t+1));case"bigint":{const e=r[2];if(typeof e!="string"||e.length>E||!/^-?\d+$/.test(e))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${E} digits)`);return BigInt(e)}case"date":{const e=b(r[2],t+1);if(typeof e!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(e)}case"map":{const e=r[2];return new Map(e.map(n=>{if(!Array.isArray(n)||n.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[b(n[0],t+1),b(n[1],t+1)]}))}case"set":return new Set(r[2].map(e=>b(e,t+1)));case"url":{const e=r[2];if(typeof e!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(e)}case"error":{const e=r[2],n=r[3];if(typeof e!="string"||typeof n!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const a=(Object.hasOwn(O,e)?O[e]:void 0)??Error,i=new a(n);i.name!==e&&Object.defineProperty(i,"name",{configurable:!0,value:e,writable:!0});const u=b(r[4],t+1);if(u===null||typeof u!="object"||Array.isArray(u))throw new TypeError("wire-codec: malformed error — props must be an object");for(const y of Object.keys(u))y===g?Object.defineProperty(i,y,{configurable:!0,enumerable:!0,value:u[y],writable:!0}):i[y]=u[y];return r.length>5&&Object.defineProperty(i,"cause",{configurable:!0,value:b(r[5],t+1),writable:!0}),i}case"bytes":{const e=r[2];if(typeof e!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const n=R(e);if(m(n)!==e)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const a=r[3]??"Uint8Array";if(a==="ArrayBuffer")return n.buffer.byteLength===n.byteLength?n.buffer:n.slice().buffer;const i=Object.hasOwn(j,a)?j[a]:void 0;return i?new i(n.slice().buffer):n}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return r.map(e=>b(e,t+1))}return r.map(s=>b(s,t+1))}const o=r,c={};for(const s of Object.keys(o)){const e=b(o[s],t+1);s===g?Object.defineProperty(c,s,{configurable:!0,enumerable:!0,value:e,writable:!0}):c[s]=e}return c},B="/_lunora/rpc";class S extends p{constructor(t,o){super(t,o,{name:"ContainerBridgeError"})}}const k=(r,t)=>{let o=r;for(;o.endsWith("/");)o=o.slice(0,-1);return`${o}${t}`},T=(r,t)=>new Error(`createContainerBridge: request to "${r}" failed (status ${String(t.status)}${t.statusText?` ${t.statusText}`:""})`),$=async(r,t)=>{try{return await r.json()}catch{throw r.ok?new p("INTERNAL",`createContainerBridge: request to "${t}" returned a non-JSON response (status ${String(r.status)})`):T(t,r)}},N=r=>{if(typeof r.baseUrl!="string"||r.baseUrl.length===0)throw new TypeError("createContainerBridge: `baseUrl` must be a non-empty Worker URL (e.g. https://my-app.workers.dev) — is the URL env var set?");const t=r.fetch??globalThis.fetch,o=async(s,e={},n)=>{if(typeof t!="function")throw new TypeError("createContainerBridge: no `fetch` available — pass `fetch` in options for this runtime.");const a={"content-type":"application/json"};r.token!==void 0&&(a.authorization=`Bearer ${r.token}`);const i=await t(k(r.baseUrl,B),{body:JSON.stringify({args:d(e),functionPath:s,shardKey:n}),headers:a,method:"POST"}),u=await $(i,s);if(typeof u=="object"&&u!==null&&"error"in u){const{error:y}=u;if(typeof y=="object"&&y!==null){const{code:h,message:A}=y;if(typeof h=="string"&&typeof A=="string")throw new S(h,A)}let l;try{l=JSON.stringify(y)}catch{l=String(y)}throw new p("INTERNAL",`createContainerBridge: request to "${s}" returned a malformed error envelope (status ${String(i.status)}): ${l}`)}if(!i.ok)throw T(s,i);return b(u.result)};return{action:o,call:o,mutation:o,query:o,run:async(s,e,n)=>o(s.__lunoraRef,e,n)}};export{S as ContainerBridgeError,N as createContainerBridge};
package/dist/otel.d.mts CHANGED
@@ -97,7 +97,15 @@ interface ContainerTelemetryOptions {
97
97
  * W3C `traceparent` of the Worker RPC that invoked this container; defaults to
98
98
  * the `LUNORA_TRACEPARENT` env var. When present (and well-formed) every span
99
99
  * inherits its trace id and hangs off its span id, so container spans stitch
100
- * under the Worker's trace instead of forming a fresh, disconnected trace.
100
+ * under the Worker's trace instead of forming a fresh, disconnected trace, and
101
+ * every log record is stamped with the same ids so a request's container logs
102
+ * are reachable from its trace.
103
+ *
104
+ * It also carries the trace's settled **sampling verdict**, which this exporter
105
+ * OBEYS rather than re-derives: a `traceparent` whose flags say the trace was
106
+ * sampled out (`…-00`) suppresses span export, because the worker and shard
107
+ * spans of that trace were dropped and shipping ours would leave the collector
108
+ * holding the middle of a trace. Logs are never sampled and are unaffected.
101
109
  *
102
110
  * `@lunora/container` stamps this trace context as the **`traceparent` request
103
111
  * header** on every proxied fetch (`ctx.containers.<name>.…`), so a container
package/dist/otel.d.ts CHANGED
@@ -97,7 +97,15 @@ interface ContainerTelemetryOptions {
97
97
  * W3C `traceparent` of the Worker RPC that invoked this container; defaults to
98
98
  * the `LUNORA_TRACEPARENT` env var. When present (and well-formed) every span
99
99
  * inherits its trace id and hangs off its span id, so container spans stitch
100
- * under the Worker's trace instead of forming a fresh, disconnected trace.
100
+ * under the Worker's trace instead of forming a fresh, disconnected trace, and
101
+ * every log record is stamped with the same ids so a request's container logs
102
+ * are reachable from its trace.
103
+ *
104
+ * It also carries the trace's settled **sampling verdict**, which this exporter
105
+ * OBEYS rather than re-derives: a `traceparent` whose flags say the trace was
106
+ * sampled out (`…-00`) suppresses span export, because the worker and shard
107
+ * spans of that trace were dropped and shipping ours would leave the collector
108
+ * holding the middle of a trace. Logs are never sampled and are unaffected.
101
109
  *
102
110
  * `@lunora/container` stamps this trace context as the **`traceparent` request
103
111
  * header** on every proxied fetch (`ctx.containers.<name>.…`), so a container
package/dist/otel.mjs CHANGED
@@ -1 +1 @@
1
- import{a as $}from"./packem_shared/abort-deadline-jwbW9Ala.mjs";const j={debug:5,error:17,fatal:21,info:9,log:9,trace:1,warn:13},N=e=>`${String(Math.round(e))}000000`,F=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0")),y=512,I=new Uint8Array(y);let T=y;const x=(e,t,r)=>{let n="";for(let o=0;o<r;o+=1)n+=F[e[t+o]];return n},L=e=>{if(e>y){const r=new Uint8Array(e);return crypto.getRandomValues(r),x(r,0,e)}T+e>y&&(crypto.getRandomValues(I),T=0);const t=x(I,T,e);return T+=e,t},S=/^[0-9a-f]+$/,Y=e=>{if(e==null)return;const t=e.trim().toLowerCase().split("-"),[r,n,o,s]=t;if(!(t.length<4||r===void 0||r.length!==2||!S.test(r)||r==="ff"||r==="00"&&t.length!==4||n===void 0||o===void 0||s===void 0||s.length!==2||!S.test(s)||n.length!==32||o.length!==16||!S.test(n)||!S.test(o)||n==="00000000000000000000000000000000"||o==="0000000000000000"))return{parentSpanId:o,sampled:(Number.parseInt(s,16)&1)===1,traceId:n}},h=(e,t)=>typeof t=="boolean"?{key:e,value:{boolValue:t}}:typeof t=="number"?Number.isFinite(t)?Number.isSafeInteger(t)?{key:e,value:{intValue:String(t)}}:{key:e,value:{doubleValue:t}}:{key:e,value:{stringValue:String(t)}}:{key:e,value:{stringValue:t}},V=e=>e===void 0?[]:Object.entries(e).map(([t,r])=>h(t,r)),X=(e,t,r)=>{const n={},o=new Map,s=(i,d)=>{const m=i.toLowerCase(),f=o.get(m);f===void 0?(o.set(m,i),n[i]=d):n[f]=d};for(const[i,d]of Object.entries(e))s(i,d);for(const[i,d]of Object.entries(t??{}))s(i,d);return r!==void 0&&r.length>0&&s("authorization",`Bearer ${r}`),n},P=e=>Array.isArray(e)?e:[e],D=(e,t)=>{const r={"service.name":e};for(const[n,o]of Object.entries(t??{}))r[n]=o;return Object.entries(r).map(([n,o])=>h(n,o))},K=(e,t,r,n)=>({resourceSpans:[{resource:{attributes:D(r,n)},scopeSpans:[{scope:{name:t},spans:P(e)}]}]}),z=(e,t,r,n)=>({resourceLogs:[{resource:{attributes:D(r,n)},scopeLogs:[{logRecords:P(e),scope:{name:t}}]}]}),G=512,W=200,U=e=>{const t=e.maxItems??G,r=e.maxDelayMs??W;let n=[],o,s,i;const d=()=>{o!==void 0&&(clearTimeout(o),o=void 0)},m=async()=>{d();const a=n;n=[];const l=i;s=void 0,i=void 0;try{a.length>0&&await e.export(a)}catch{}finally{l?.()}},f=a=>{s===void 0&&(s=new Promise(l=>{i=l}),o=setTimeout(()=>{m()},r)),a?.(s)};return{add:(a,l)=>{for(n.push(a);n.length>t;)n.shift();f(l),n.length>=t&&m()},flush:async a=>{if(n.length===0){d();return}const l=m();return a?.(l),l},get size(){return n.length}}},k=e=>{const t={},r=e("SERVICE_VERSION")??e("CF_VERSION_METADATA")??e("VERCEL_GIT_COMMIT_SHA")??e("GITHUB_SHA")??e("COMMIT_SHA");r!==void 0&&(t["service.version"]=r);const n=e("DEPLOYMENT_ENVIRONMENT")??e("ENVIRONMENT")??e("NODE_ENV");return n!==void 0&&(t["deployment.environment"]=n),t},J=(e,t)=>{const r={},n=e("HOSTNAME")??e("COMPUTERNAME");n!==void 0&&(r["host.name"]=n);const o=e("KUBERNETES_POD_NAME")??(e("KUBERNETES_SERVICE_HOST")===void 0?void 0:e("HOSTNAME"));return o!==void 0&&(r["k8s.pod.name"]=o),t!==void 0&&Number.isFinite(t)&&(r["process.pid"]=t),r},C=(...e)=>{const t={};for(const r of e)if(r!==void 0)for(const[n,o]of Object.entries(r))t[n]=o;return t},q=1e4,g=e=>process.env[e],Q=()=>{const e=typeof process.pid!="number"?void 0:process.pid;return C(k(g),J(g,e))},Z=e=>e??(typeof globalThis.fetch=="function"?globalThis.fetch:void 0),ee=(e,t)=>{const r=V(e.attributes);e.error?.type!==void 0&&r.push(h("error.type",e.error.type));const n={attributes:r,endTimeUnixNano:N(e.endMs),kind:1,name:e.name,...t===void 0?{}:{parentSpanId:t.parentSpanId},spanId:L(8),startTimeUnixNano:N(e.startMs),status:e.error===void 0?{code:1}:{code:2,message:e.error.message},traceId:t?.traceId??L(16)};return e.error&&(n.events=[{attributes:[h("exception.type",e.error.type??"Error"),h("exception.message",e.error.message)],name:"exception",timeUnixNano:N(e.endMs)}]),n},te=(e,t)=>{const r=e.level??"info";return{attributes:V(e.attributes),body:{stringValue:e.message},severityNumber:j[r],severityText:r.toUpperCase(),timeUnixNano:N(e.ts??t)}},ie=(e={})=>{const t=e.endpoint??g("LUNORA_OTLP_ENDPOINT"),r=t!==void 0&&t.length>0,n=e.token??g("LUNORA_OTLP_TOKEN"),o=e.serviceName??g("LUNORA_SERVICE_NAME")??"lunora-container",s=Y(e.traceparent??g("LUNORA_TRACEPARENT")),i=e.timeoutMs??q,d=Z(e.fetch),m=X({"content-type":"application/json"},e.headers,n),f=e.detectResources===!0?Q():void 0,a={};e.serviceVersion!==void 0&&(a["service.version"]=e.serviceVersion),e.deploymentEnvironment!==void 0&&(a["deployment.environment"]=e.deploymentEnvironment),e.resourceAttributes!==void 0&&Object.assign(a,e.resourceAttributes);const l=C(f,a);let p=t??"";for(;p.endsWith("/");)p=p.slice(0,-1);const H=`${p}/v1/traces`,B=`${p}/v1/logs`,b=new Set,_=(c,A)=>{if(d===void 0)return e.onError?.(new TypeError("createContainerTelemetry: no `fetch` available — pass `fetch` in options for this runtime.")),Promise.resolve();const v=(async()=>{const u=$(void 0,i,()=>new DOMException(`OTLP export to ${c} timed out after ${String(i)}ms`,"TimeoutError"));try{const E=await d(c,{body:JSON.stringify(A),headers:m,method:"POST",signal:u.signal});E.ok||e.onError?.(new Error(`createContainerTelemetry: OTLP export to ${c} failed with status ${String(E.status)}.`));try{await E.body?.cancel()}catch{}}catch(E){e.onError?.(E)}finally{u.dispose()}})().finally(()=>{b.delete(v)});return b.add(v),v},R=U({export:c=>_(H,K(c,"@lunora/container",o,l))}),w=U({export:c=>_(B,z(c,"@lunora/container",o,l))}),O=c=>{r&&R.add(ee(c,s))};return{emitLog:c=>{r&&w.add(te(c,Date.now()))},emitSpan:O,enabled:r,flush:async()=>{await Promise.allSettled([R.flush(),w.flush()]),await Promise.allSettled(b)},trace:async(c,A,M)=>{const v=Date.now();try{const u=await A();return O({attributes:M,endMs:Date.now(),name:c,startMs:v}),u}catch(u){throw O({attributes:M,endMs:Date.now(),error:{message:u instanceof Error?u.message:String(u),type:u instanceof Error?u.name:void 0},name:c,startMs:v}),u}}}};export{ie as createContainerTelemetry};
1
+ import{a as F}from"./packem_shared/abort-deadline-jwbW9Ala.mjs";const Y={debug:5,error:17,fatal:21,info:9,log:9,trace:1,warn:13},N=e=>`${String(Math.round(e))}000000`,X=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0")),y=512,x=new Uint8Array(y);let T=y;const L=(e,t,r)=>{let n="";for(let o=0;o<r;o+=1)n+=X[e[t+o]];return n},U=e=>{if(e>y){const r=new Uint8Array(e);return crypto.getRandomValues(r),L(r,0,e)}T+e>y&&(crypto.getRandomValues(x),T=0);const t=L(x,T,e);return T+=e,t},S=/^[0-9a-f]+$/,G=e=>{if(e==null)return;const t=e.trim().toLowerCase().split("-"),[r,n,o,s]=t;if(!(t.length<4||r===void 0||r.length!==2||!S.test(r)||r==="ff"||r==="00"&&t.length!==4||n===void 0||o===void 0||s===void 0||s.length!==2||!S.test(s)||n.length!==32||o.length!==16||!S.test(n)||!S.test(o)||n==="00000000000000000000000000000000"||o==="0000000000000000"))return{parentSpanId:o,sampled:(Number.parseInt(s,16)&1)===1,traceId:n}},h=(e,t)=>typeof t=="boolean"?{key:e,value:{boolValue:t}}:typeof t=="number"?Number.isFinite(t)?Number.isSafeInteger(t)?{key:e,value:{intValue:String(t)}}:{key:e,value:{doubleValue:t}}:{key:e,value:{stringValue:String(t)}}:{key:e,value:{stringValue:t}},P=e=>e===void 0?[]:Object.entries(e).map(([t,r])=>h(t,r)),K=(e,t,r)=>{const n={},o=new Map,s=(c,d)=>{const m=c.toLowerCase(),f=o.get(m);f===void 0?(o.set(m,c),n[c]=d):n[f]=d};for(const[c,d]of Object.entries(e))s(c,d);for(const[c,d]of Object.entries(t??{}))s(c,d);return r!==void 0&&r.length>0&&s("authorization",`Bearer ${r}`),n},D=e=>Array.isArray(e)?e:[e],C=(e,t)=>{const r={"service.name":e};for(const[n,o]of Object.entries(t??{}))r[n]=o;return Object.entries(r).map(([n,o])=>h(n,o))},z=(e,t,r,n)=>({resourceSpans:[{resource:{attributes:C(r,n)},scopeSpans:[{scope:{name:t},spans:D(e)}]}]}),W=(e,t,r,n)=>({resourceLogs:[{resource:{attributes:C(r,n)},scopeLogs:[{logRecords:D(e),scope:{name:t}}]}]}),k=512,J=200,V=e=>{const t=e.maxItems??k,r=e.maxDelayMs??J;let n=[],o,s,c;const d=()=>{o!==void 0&&(clearTimeout(o),o=void 0)},m=async()=>{d();const u=n;n=[];const a=c;s=void 0,c=void 0;try{u.length>0&&await e.export(u)}catch{}finally{a?.()}},f=u=>{s===void 0&&(s=new Promise(a=>{c=a}),o=setTimeout(()=>{m()},r)),u?.(s)};return{add:(u,a)=>{for(n.push(u);n.length>t;)n.shift();f(a),n.length>=t&&m()},flush:async u=>{if(n.length===0){d();return}const a=m();return u?.(a),a},get size(){return n.length}}},q=e=>{const t={},r=e("SERVICE_VERSION")??e("CF_VERSION_METADATA")??e("VERCEL_GIT_COMMIT_SHA")??e("GITHUB_SHA")??e("COMMIT_SHA");r!==void 0&&(t["service.version"]=r);const n=e("DEPLOYMENT_ENVIRONMENT")??e("ENVIRONMENT")??e("NODE_ENV");return n!==void 0&&(t["deployment.environment"]=n),t},Q=(e,t)=>{const r={},n=e("HOSTNAME")??e("COMPUTERNAME");n!==void 0&&(r["host.name"]=n);const o=e("KUBERNETES_POD_NAME")??(e("KUBERNETES_SERVICE_HOST")===void 0?void 0:e("HOSTNAME"));return o!==void 0&&(r["k8s.pod.name"]=o),t!==void 0&&Number.isFinite(t)&&(r["process.pid"]=t),r},H=(...e)=>{const t={};for(const r of e)if(r!==void 0)for(const[n,o]of Object.entries(r))t[n]=o;return t},Z=1e4,B=1,p=e=>process.env[e],ee=()=>{const e=typeof process.pid!="number"?void 0:process.pid;return H(q(p),Q(p,e))},te=e=>e??(typeof globalThis.fetch=="function"?globalThis.fetch:void 0),re=(e,t)=>{const r=P(e.attributes);e.error?.type!==void 0&&r.push(h("error.type",e.error.type));const n={attributes:r,endTimeUnixNano:N(e.endMs),flags:t?.sampled??!0?B:0,kind:1,name:e.name,...t===void 0?{}:{parentSpanId:t.parentSpanId},spanId:U(8),startTimeUnixNano:N(e.startMs),status:e.error===void 0?{code:1}:{code:2,message:e.error.message},traceId:t?.traceId??U(16)};return e.error&&(n.events=[{attributes:[h("exception.type",e.error.type??"Error"),h("exception.message",e.error.message)],name:"exception",timeUnixNano:N(e.endMs)}]),n},ne=(e,t,r)=>{const n=e.level??"info";return{attributes:P(e.attributes),body:{stringValue:e.message},severityNumber:Y[n],severityText:n.toUpperCase(),timeUnixNano:N(e.ts??t),...r===void 0?{}:{flags:r.sampled?B:0,spanId:r.parentSpanId,traceId:r.traceId}}},ae=(e={})=>{const t=e.endpoint??p("LUNORA_OTLP_ENDPOINT"),r=t!==void 0&&t.length>0,n=e.token??p("LUNORA_OTLP_TOKEN"),o=e.serviceName??p("LUNORA_SERVICE_NAME")??"lunora-container",s=G(e.traceparent??p("LUNORA_TRACEPARENT")),c=s?.sampled!==!1,d=e.timeoutMs??Z,m=te(e.fetch),f=K({"content-type":"application/json"},e.headers,n),u=e.detectResources===!0?ee():void 0,a={};e.serviceVersion!==void 0&&(a["service.version"]=e.serviceVersion),e.deploymentEnvironment!==void 0&&(a["deployment.environment"]=e.deploymentEnvironment),e.resourceAttributes!==void 0&&Object.assign(a,e.resourceAttributes);const M=H(u,a);let g=t??"";for(;g.endsWith("/");)g=g.slice(0,-1);const $=`${g}/v1/traces`,j=`${g}/v1/logs`,A=new Set,R=(i,O)=>{if(m===void 0)return e.onError?.(new TypeError("createContainerTelemetry: no `fetch` available — pass `fetch` in options for this runtime.")),Promise.resolve();const v=(async()=>{const l=F(void 0,d,()=>new DOMException(`OTLP export to ${i} timed out after ${String(d)}ms`,"TimeoutError"));try{const E=await m(i,{body:JSON.stringify(O),headers:f,method:"POST",signal:l.signal});E.ok||e.onError?.(new Error(`createContainerTelemetry: OTLP export to ${i} failed with status ${String(E.status)}.`));try{await E.body?.cancel()}catch{}}catch(E){e.onError?.(E)}finally{l.dispose()}})().finally(()=>{A.delete(v)});return A.add(v),v},I=V({export:i=>R($,z(i,"@lunora/container",o,M))}),w=V({export:i=>R(j,W(i,"@lunora/container",o,M))}),b=i=>{!r||!c||I.add(re(i,s))};return{emitLog:i=>{r&&w.add(ne(i,Date.now(),s))},emitSpan:b,enabled:r,flush:async()=>{await Promise.allSettled([I.flush(),w.flush()]),await Promise.allSettled(A)},trace:async(i,O,_)=>{const v=Date.now();try{const l=await O();return b({attributes:_,endMs:Date.now(),name:i,startMs:v}),l}catch(l){throw b({attributes:_,endMs:Date.now(),error:{message:l instanceof Error?l.message:String(l),type:l instanceof Error?l.name:void 0},name:i,startMs:v}),l}}}};export{ae as createContainerTelemetry};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/container",
3
- "version": "1.0.0-alpha.44",
3
+ "version": "1.0.0-alpha.46",
4
4
  "description": "Cloudflare Containers for Lunora: defineContainer, generated Container DO classes, and the ctx.containers action surface",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -56,7 +56,7 @@
56
56
  "access": "public"
57
57
  },
58
58
  "dependencies": {
59
- "@lunora/errors": "1.0.0-alpha.31"
59
+ "@lunora/errors": "1.0.0-alpha.33"
60
60
  },
61
61
  "engines": {
62
62
  "node": "^22.15.0 || >=24.11.0"