@lunora/container 1.0.0-alpha.37 → 1.0.0-alpha.38
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 +9 -2
- package/dist/otel.d.ts +9 -2
- package/dist/otel.mjs +1 -1
- package/package.json +2 -2
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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.
|
|
3
|
+
"version": "1.0.0-alpha.38",
|
|
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.
|
|
59
|
+
"@lunora/errors": "1.0.0-alpha.27"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": "^22.15.0 || >=24.11.0"
|