@lunora/container 1.0.0-alpha.37 → 1.0.0-alpha.39

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/otel.d.mts CHANGED
@@ -127,7 +127,7 @@ interface ContainerTelemetry {
127
127
  emitSpan: (span: ContainerSpanInput) => void;
128
128
  /** True when an endpoint resolved and exports are actually sent. */
129
129
  readonly enabled: boolean;
130
- /** Await all in-flight sends — call before the process exits. */
130
+ /** Drain the span/log buffers and await every in-flight send — call before the process exits, or buffered signals are lost. */
131
131
  flush: () => Promise<void>;
132
132
  /** Time `run()`, recording a span named `name` (ok, or errored if it throws). Always runs `run()`, even when disabled. */
133
133
  trace: <T>(name: string, run: () => Promise<T>, attributes?: Record<string, ContainerAttributeValue>) => Promise<T>;
@@ -139,9 +139,16 @@ interface ContainerTelemetry {
139
139
  * const telemetry = createContainerTelemetry(); // reads LUNORA_OTLP_ENDPOINT / _TOKEN
140
140
  * await telemetry.trace("transcode", () => transcode(job), { jobId: job.id });
141
141
  * telemetry.emitLog({ level: "info", message: "done", attributes: { jobId: job.id } });
142
- * await telemetry.flush(); // before the process exits
142
+ * await telemetry.flush(); // REQUIRED before the process exits — see below
143
143
  * ```
144
144
  *
145
+ * `flush()` is mandatory, not an optimisation. Spans and log records are
146
+ * BATCHED: nothing leaves the process until the batcher's timer elapses or
147
+ * `flush()` drains it, so a job that finishes and exits inside that window
148
+ * reports NOTHING without it. A long job between flushes can also reach the
149
+ * batcher's item cap, which drops the OLDEST buffered records — flush at
150
+ * checkpoints, not only at exit.
151
+ *
145
152
  * With no endpoint resolvable the returned exporter is disabled (`enabled ===
146
153
  * false`): `emitSpan`/`emitLog` no-op and `trace` still runs its work but records
147
154
  * nothing — so the same code runs unchanged locally and in the cloud.
package/dist/otel.d.ts CHANGED
@@ -127,7 +127,7 @@ interface ContainerTelemetry {
127
127
  emitSpan: (span: ContainerSpanInput) => void;
128
128
  /** True when an endpoint resolved and exports are actually sent. */
129
129
  readonly enabled: boolean;
130
- /** Await all in-flight sends — call before the process exits. */
130
+ /** Drain the span/log buffers and await every in-flight send — call before the process exits, or buffered signals are lost. */
131
131
  flush: () => Promise<void>;
132
132
  /** Time `run()`, recording a span named `name` (ok, or errored if it throws). Always runs `run()`, even when disabled. */
133
133
  trace: <T>(name: string, run: () => Promise<T>, attributes?: Record<string, ContainerAttributeValue>) => Promise<T>;
@@ -139,9 +139,16 @@ interface ContainerTelemetry {
139
139
  * const telemetry = createContainerTelemetry(); // reads LUNORA_OTLP_ENDPOINT / _TOKEN
140
140
  * await telemetry.trace("transcode", () => transcode(job), { jobId: job.id });
141
141
  * telemetry.emitLog({ level: "info", message: "done", attributes: { jobId: job.id } });
142
- * await telemetry.flush(); // before the process exits
142
+ * await telemetry.flush(); // REQUIRED before the process exits — see below
143
143
  * ```
144
144
  *
145
+ * `flush()` is mandatory, not an optimisation. Spans and log records are
146
+ * BATCHED: nothing leaves the process until the batcher's timer elapses or
147
+ * `flush()` drains it, so a job that finishes and exits inside that window
148
+ * reports NOTHING without it. A long job between flushes can also reach the
149
+ * batcher's item cap, which drops the OLDEST buffered records — flush at
150
+ * checkpoints, not only at exit.
151
+ *
145
152
  * With no endpoint resolvable the returned exporter is disabled (`enabled ===
146
153
  * false`): `emitSpan`/`emitLog` no-op and `trace` still runs its work but records
147
154
  * nothing — so the same code runs unchanged locally and in the cloud.
package/dist/otel.mjs CHANGED
@@ -1 +1 @@
1
- import{a as D}from"./packem_shared/abort-deadline-jwbW9Ala.mjs";const H={debug:5,error:17,fatal:21,info:9,log:9,trace:1,warn:13},h=e=>`${String(Math.round(e))}000000`,$=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0")),O=512,M=new Uint8Array(O);let N=O;const w=(e,t,r)=>{let n="";for(let o=0;o<r;o+=1)n+=$[e[t+o]];return n},I=e=>{if(e>O){const r=new Uint8Array(e);return crypto.getRandomValues(r),w(r,0,e)}N+e>O&&(crypto.getRandomValues(M),N=0);const t=w(M,N,e);return N+=e,t},T=/^[0-9a-f]+$/,j=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||!T.test(r)||r==="ff"||r==="00"&&t.length!==4||n===void 0||o===void 0||s===void 0||s.length!==2||!T.test(s)||n.length!==32||o.length!==16||!T.test(n)||!T.test(o)||n==="00000000000000000000000000000000"||o==="0000000000000000"))return{parentSpanId:o,sampled:(Number.parseInt(s,16)&1)===1,traceId:n}},v=(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}},L=e=>e===void 0?[]:Object.entries(e).map(([t,r])=>v(t,r)),B=(e,t,r)=>{const n={},o=new Map,s=(c,d)=>{const E=c.toLowerCase(),p=o.get(E);p===void 0?(o.set(E,c),n[c]=d):n[p]=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},V=e=>Array.isArray(e)?e:[e],U=(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])=>v(n,o))},F=(e,t,r,n)=>({resourceSpans:[{resource:{attributes:U(r,n)},scopeSpans:[{scope:{name:t},spans:V(e)}]}]}),Y=(e,t,r,n)=>({resourceLogs:[{resource:{attributes:U(r,n)},scopeLogs:[{logRecords:V(e),scope:{name:t}}]}]}),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},G=(e,t)=>{const r={},n=e("HOSTNAME")??e("COMPUTERNAME");n!==void 0&&(r["host.name"]=n);const o=e("KUBERNETES_POD_NAME")??e("HOSTNAME");return o!==void 0&&e("KUBERNETES_SERVICE_HOST")!==void 0&&(r["k8s.pod.name"]=o),t!==void 0&&Number.isFinite(t)&&(r["process.pid"]=t),r},x=(...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},X=1e4,u=e=>process.env[e],k=()=>{const e=typeof process.pid!="number"?void 0:process.pid;return x(K(u),G(u,e))},z=e=>e??(typeof globalThis.fetch=="function"?globalThis.fetch:void 0),J=(e,t,r,n)=>{const o=L(e.attributes);e.error?.type!==void 0&&o.push(v("error.type",e.error.type));const s={attributes:o,endTimeUnixNano:h(e.endMs),kind:1,name:e.name,...r===void 0?{}:{parentSpanId:r.parentSpanId},spanId:I(8),startTimeUnixNano:h(e.startMs),status:e.error===void 0?{code:1}:{code:2,message:e.error.message},traceId:r?.traceId??I(16)};return e.error&&(s.events=[{attributes:[v("exception.type",e.error.type??"Error"),v("exception.message",e.error.message)],name:"exception",timeUnixNano:h(e.endMs)}]),F(s,"@lunora/container",t,n)},W=(e,t,r,n)=>{const o=e.level??"info",s={attributes:L(e.attributes),body:{stringValue:e.message},severityNumber:H[o],severityText:o.toUpperCase(),timeUnixNano:h(e.ts??r)};return Y(s,"@lunora/container",t,n)},te=(e={})=>{const t=e.endpoint??u("LUNORA_OTLP_ENDPOINT"),r=t!==void 0&&t.length>0,n=e.token??u("LUNORA_OTLP_TOKEN"),o=e.serviceName??u("LUNORA_SERVICE_NAME")??"lunora-container",s=j(e.traceparent??u("LUNORA_TRACEPARENT")),c=e.timeoutMs??X,d=z(e.fetch),E=B({"content-type":"application/json"},e.headers,n),p=e.detectResources===!0?k():void 0,g={};e.serviceVersion!==void 0&&(g["service.version"]=e.serviceVersion),e.deploymentEnvironment!==void 0&&(g["deployment.environment"]=e.deploymentEnvironment),e.resourceAttributes!==void 0&&Object.assign(g,e.resourceAttributes);const R=x(p,g);let l=t??"";for(;l.endsWith("/");)l=l.slice(0,-1);const C=`${l}/v1/traces`,P=`${l}/v1/logs`,S=new Set,_=(a,y)=>{if(d===void 0){e.onError?.(new TypeError("createContainerTelemetry: no `fetch` available — pass `fetch` in options for this runtime."));return}const f=(async()=>{const i=D(void 0,c,()=>new DOMException(`OTLP export to ${a} timed out after ${String(c)}ms`,"TimeoutError"));try{const m=await d(a,{body:JSON.stringify(y),headers:E,method:"POST",signal:i.signal});m.ok||e.onError?.(new Error(`createContainerTelemetry: OTLP export to ${a} failed with status ${String(m.status)}.`));try{await m.body?.cancel()}catch{}}catch(m){e.onError?.(m)}finally{i.dispose()}})().finally(()=>{S.delete(f)});S.add(f)},b=a=>{r&&_(C,J(a,o,s,R))};return{emitLog:a=>{r&&_(P,W(a,o,Date.now(),R))},emitSpan:b,enabled:r,flush:async()=>{await Promise.allSettled(S)},trace:async(a,y,A)=>{const f=Date.now();try{const i=await y();return b({attributes:A,endMs:Date.now(),name:a,startMs:f}),i}catch(i){throw b({attributes:A,endMs:Date.now(),error:{message:i instanceof Error?i.message:String(i),type:i instanceof Error?i.name:void 0},name:a,startMs:f}),i}}}};export{te as createContainerTelemetry};
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("HOSTNAME");return o!==void 0&&e("KUBERNETES_SERVICE_HOST")!==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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/container",
3
- "version": "1.0.0-alpha.37",
3
+ "version": "1.0.0-alpha.39",
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.26"
59
+ "@lunora/errors": "1.0.0-alpha.28"
60
60
  },
61
61
  "engines": {
62
62
  "node": "^22.15.0 || >=24.11.0"