@lunora/observability 1.0.0-alpha.18 → 1.0.0-alpha.19

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/index.d.mts CHANGED
@@ -1196,6 +1196,8 @@ interface LogEntry {
1196
1196
  level: LogLevel;
1197
1197
  message: string;
1198
1198
  timestamp: number;
1199
+ /** Trace the line was emitted under; absent outside a dispatch (container lifecycle, hibernation-path errors). What the Studio joins a log line to its waterfall on. */
1200
+ traceId?: string;
1199
1201
  }
1200
1202
  /**
1201
1203
  * A bounded, in-memory ring buffer of recent {@link LogEntry} records.
@@ -1498,6 +1500,8 @@ interface RequestLogEntry {
1498
1500
  tablesRead: string[];
1499
1501
  /** Tables the handler wrote (from the change tracker); empty for a read-only dispatch. */
1500
1502
  tablesWritten: string[];
1503
+ /** W3C trace id (32-hex) of the dispatch; `undefined` on a row appended before this column existed. See the module docstring on the retention asymmetry. */
1504
+ traceId?: string;
1501
1505
  /** Wall-clock millis when the dispatch completed. */
1502
1506
  ts: number;
1503
1507
  /** Acting userId forwarded by the runtime, or `undefined` when anonymous. */
@@ -1516,6 +1520,7 @@ interface AppendRequestLogEntry {
1516
1520
  subscriptionsReRun?: number;
1517
1521
  tablesRead?: string[];
1518
1522
  tablesWritten?: string[];
1523
+ traceId?: string;
1519
1524
  ts: number;
1520
1525
  userId?: string;
1521
1526
  }
@@ -1651,12 +1656,17 @@ declare const redactArgs: (value: unknown, captureRaw?: boolean) => unknown;
1651
1656
  *
1652
1657
  * `error_fingerprint` is the {@link fingerprintError} grouping hash captured
1653
1658
  * from the RAW `error_message` at write time, before {@link appendRequestLogEntry}
1654
- * redacts it — see that function's docstring. It is added via a guarded
1655
- * `ALTER TABLE` rather than baked into the `CREATE`, mirroring
1659
+ * redacts it — see that function's docstring. `trace_id` is the dispatch's W3C
1660
+ * trace id, the correlation key to the span ring and to whatever collector
1661
+ * `otlpSink` ships to.
1662
+ *
1663
+ * Both are also added via a guarded `ALTER TABLE`, mirroring
1656
1664
  * `function-metrics.ts`'s `ensureFunctionMetricsTables`, so a shard whose
1657
- * `__lunora_reqlog__` predates this column gains it on the next call without a
1665
+ * `__lunora_reqlog__` predates a column gains it on the next call without a
1658
1666
  * migration. SQLite has no `ADD COLUMN IF NOT EXISTS`, so the duplicate-column
1659
- * error from a re-run (or the freshly-created schema above) is swallowed.
1667
+ * error from a re-run (or from the freshly-created schema above) is swallowed
1668
+ * per column — the loop is what keeps one column's duplicate from skipping the
1669
+ * next column's add.
1660
1670
  */
1661
1671
  declare const ensureRequestLogTable: (sql: SqlExec) => void;
1662
1672
  /**
@@ -1842,6 +1852,15 @@ interface TraceSpan {
1842
1852
  message: string;
1843
1853
  type: string;
1844
1854
  };
1855
+ /**
1856
+ * Timestamped occurrences inside the span — `span.addEvent(...)` and
1857
+ * `span.recordException(...)`. Carried through so a handled retry or a
1858
+ * swallowed exception is visible on the span it happened in, which is the
1859
+ * only place it is interpretable. Absent when the body recorded none.
1860
+ */
1861
+ events?: SpanEventPoint[];
1862
+ /** OTel `SpanKind`; absent means `"internal"`. */
1863
+ kind?: OtlpSpanKind;
1845
1864
  name: string;
1846
1865
  /** Start of this span relative to the trace's start, in ms. */
1847
1866
  offsetMs: number;
package/dist/index.d.ts CHANGED
@@ -1196,6 +1196,8 @@ interface LogEntry {
1196
1196
  level: LogLevel;
1197
1197
  message: string;
1198
1198
  timestamp: number;
1199
+ /** Trace the line was emitted under; absent outside a dispatch (container lifecycle, hibernation-path errors). What the Studio joins a log line to its waterfall on. */
1200
+ traceId?: string;
1199
1201
  }
1200
1202
  /**
1201
1203
  * A bounded, in-memory ring buffer of recent {@link LogEntry} records.
@@ -1498,6 +1500,8 @@ interface RequestLogEntry {
1498
1500
  tablesRead: string[];
1499
1501
  /** Tables the handler wrote (from the change tracker); empty for a read-only dispatch. */
1500
1502
  tablesWritten: string[];
1503
+ /** W3C trace id (32-hex) of the dispatch; `undefined` on a row appended before this column existed. See the module docstring on the retention asymmetry. */
1504
+ traceId?: string;
1501
1505
  /** Wall-clock millis when the dispatch completed. */
1502
1506
  ts: number;
1503
1507
  /** Acting userId forwarded by the runtime, or `undefined` when anonymous. */
@@ -1516,6 +1520,7 @@ interface AppendRequestLogEntry {
1516
1520
  subscriptionsReRun?: number;
1517
1521
  tablesRead?: string[];
1518
1522
  tablesWritten?: string[];
1523
+ traceId?: string;
1519
1524
  ts: number;
1520
1525
  userId?: string;
1521
1526
  }
@@ -1651,12 +1656,17 @@ declare const redactArgs: (value: unknown, captureRaw?: boolean) => unknown;
1651
1656
  *
1652
1657
  * `error_fingerprint` is the {@link fingerprintError} grouping hash captured
1653
1658
  * from the RAW `error_message` at write time, before {@link appendRequestLogEntry}
1654
- * redacts it — see that function's docstring. It is added via a guarded
1655
- * `ALTER TABLE` rather than baked into the `CREATE`, mirroring
1659
+ * redacts it — see that function's docstring. `trace_id` is the dispatch's W3C
1660
+ * trace id, the correlation key to the span ring and to whatever collector
1661
+ * `otlpSink` ships to.
1662
+ *
1663
+ * Both are also added via a guarded `ALTER TABLE`, mirroring
1656
1664
  * `function-metrics.ts`'s `ensureFunctionMetricsTables`, so a shard whose
1657
- * `__lunora_reqlog__` predates this column gains it on the next call without a
1665
+ * `__lunora_reqlog__` predates a column gains it on the next call without a
1658
1666
  * migration. SQLite has no `ADD COLUMN IF NOT EXISTS`, so the duplicate-column
1659
- * error from a re-run (or the freshly-created schema above) is swallowed.
1667
+ * error from a re-run (or from the freshly-created schema above) is swallowed
1668
+ * per column — the loop is what keeps one column's duplicate from skipping the
1669
+ * next column's add.
1660
1670
  */
1661
1671
  declare const ensureRequestLogTable: (sql: SqlExec) => void;
1662
1672
  /**
@@ -1842,6 +1852,15 @@ interface TraceSpan {
1842
1852
  message: string;
1843
1853
  type: string;
1844
1854
  };
1855
+ /**
1856
+ * Timestamped occurrences inside the span — `span.addEvent(...)` and
1857
+ * `span.recordException(...)`. Carried through so a handled retry or a
1858
+ * swallowed exception is visible on the span it happened in, which is the
1859
+ * only place it is interpretable. Absent when the body recorded none.
1860
+ */
1861
+ events?: SpanEventPoint[];
1862
+ /** OTel `SpanKind`; absent means `"internal"`. */
1863
+ kind?: OtlpSpanKind;
1845
1864
  name: string;
1846
1865
  /** Start of this span relative to the trace's start, in ms. */
1847
1866
  offsetMs: number;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{AUTH_METRICS_BUCKETS_TABLE as t,AUTH_METRICS_BUCKET_MS as T,AUTH_METRICS_BUCKET_RETENTION as o,AUTH_METRICS_TABLE as a,ensureAuthMetricsTables as s,readAuthMetrics as E,recordAuthEvent as _}from"./packem_shared/AUTH_METRICS_BUCKETS_TABLE-DpVJl1bU.mjs";import{createMetrics as S,createSpanCollector as I,createTracedFetch as i,createTracer as n,dispatchRootSpan as M}from"./packem_shared/createMetrics-1k6z1bld.mjs";import{createDatabaseTally as A,formatTally as C,instrumentDatabase as N}from"./packem_shared/createDatabaseTally-_X8tMObq.mjs";import{FUNCTION_METRICS_BUCKETS_TABLE as U,FUNCTION_METRICS_BUCKET_MS as d,FUNCTION_METRICS_BUCKET_RETENTION as f,FUNCTION_METRICS_INDEX_TABLE as R,FUNCTION_METRICS_MAX_PATHS as L,FUNCTION_METRICS_READ_LIMIT as m,FUNCTION_METRICS_SCANS_TABLE as x,FUNCTION_METRICS_TABLE as B,ensureFunctionMetricsTables as F,mergeScanAttribution as l,readFunctionMetricBuckets as g,readFunctionMetricIndexHits as O,readFunctionMetricScans as H,readFunctionMetrics as y,readFunctionMetricsTotals as h,recordFunctionMetric as D}from"./packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-BXPeggfa.mjs";import{DEFAULT_EXPLAIN_ISSUE_MODEL as b,explainIssue as v,parseExplainIssueArgs as q}from"./packem_shared/DEFAULT_EXPLAIN_ISSUE_MODEL-xF11R4vX.mjs";import{ISSUE_SEVERITIES as X,ISSUE_STATE_TABLE as G,ISSUE_STATUSES as P,upsertIssueState as k}from"./packem_shared/ISSUE_SEVERITIES-E91cPcjt.mjs";import{LogBuffer as V}from"./packem_shared/LogBuffer-bIvCelI-.mjs";import{M as z}from"./packem_shared/metric-buffer-CdgXal7w.mjs";import{readMetricHistory as W,recordMetricHistory as Y}from"./packem_shared/readMetricHistory-BdC01ptv.mjs";import{readQueryInsights as $,readQueryMetrics as ee,recordQueryMetric as re}from"./packem_shared/readQueryInsights-BprtfEp-.mjs";import{d as Te,v as oe,K as ae,w as se,h as Ee,F as _e,X as ce,C as Se,c as Ie}from"./packem_shared/request-log-CHl9HlyL.mjs";import{MIN_ADMIN_TOKEN_LENGTH as ne,MIN_AUTH_SECRET_LENGTH as Me,buildSecurityAudit as ue}from"./packem_shared/MIN_ADMIN_TOKEN_LENGTH-T-zuwRVR.mjs";import{SpanBuffer as Ce,foldTraces as Ne}from"./packem_shared/SpanBuffer-BR6Ff0M-.mjs";import{findDanglingReferences as Ue}from"./packem_shared/findDanglingReferences-D-x9LvY0.mjs";import{r as fe}from"./packem_shared/trace-context-DrdF960P.mjs";export{t as AUTH_METRICS_BUCKETS_TABLE,T as AUTH_METRICS_BUCKET_MS,o as AUTH_METRICS_BUCKET_RETENTION,a as AUTH_METRICS_TABLE,b as DEFAULT_EXPLAIN_ISSUE_MODEL,U as FUNCTION_METRICS_BUCKETS_TABLE,d as FUNCTION_METRICS_BUCKET_MS,f as FUNCTION_METRICS_BUCKET_RETENTION,R as FUNCTION_METRICS_INDEX_TABLE,L as FUNCTION_METRICS_MAX_PATHS,m as FUNCTION_METRICS_READ_LIMIT,x as FUNCTION_METRICS_SCANS_TABLE,B as FUNCTION_METRICS_TABLE,X as ISSUE_SEVERITIES,G as ISSUE_STATE_TABLE,P as ISSUE_STATUSES,V as LogBuffer,ne as MIN_ADMIN_TOKEN_LENGTH,Me as MIN_AUTH_SECRET_LENGTH,z as MetricBuffer,Te as REQUEST_LOG_TABLE,Ce as SpanBuffer,oe as appendRequestLogEntry,ue as buildSecurityAudit,A as createDatabaseTally,S as createMetrics,I as createSpanCollector,i as createTracedFetch,n as createTracer,M as dispatchRootSpan,ae as emitLogEvent,se as emitRequestLogEvent,s as ensureAuthMetricsTables,F as ensureFunctionMetricsTables,Ee as ensureRequestLogTable,v as explainIssue,Ue as findDanglingReferences,Ne as foldTraces,C as formatTally,N as instrumentDatabase,l as mergeScanAttribution,q as parseExplainIssueArgs,_e as parseLogArgs,E as readAuthMetrics,ce as readErrorIssues,g as readFunctionMetricBuckets,O as readFunctionMetricIndexHits,H as readFunctionMetricScans,y as readFunctionMetrics,h as readFunctionMetricsTotals,W as readMetricHistory,$ as readQueryInsights,ee as readQueryMetrics,Se as readRequestLog,_ as recordAuthEvent,D as recordFunctionMetric,Y as recordMetricHistory,re as recordQueryMetric,Ie as redactArgs,fe as resolveTraceAnchor,k as upsertIssueState};
1
+ import{AUTH_METRICS_BUCKETS_TABLE as t,AUTH_METRICS_BUCKET_MS as T,AUTH_METRICS_BUCKET_RETENTION as o,AUTH_METRICS_TABLE as a,ensureAuthMetricsTables as s,readAuthMetrics as E,recordAuthEvent as _}from"./packem_shared/AUTH_METRICS_BUCKETS_TABLE-DpVJl1bU.mjs";import{createMetrics as S,createSpanCollector as I,createTracedFetch as i,createTracer as n,dispatchRootSpan as M}from"./packem_shared/createMetrics-BD9PSRte.mjs";import{createDatabaseTally as A,formatTally as C,instrumentDatabase as N}from"./packem_shared/createDatabaseTally-oPXdBqRN.mjs";import{FUNCTION_METRICS_BUCKETS_TABLE as U,FUNCTION_METRICS_BUCKET_MS as d,FUNCTION_METRICS_BUCKET_RETENTION as f,FUNCTION_METRICS_INDEX_TABLE as R,FUNCTION_METRICS_MAX_PATHS as L,FUNCTION_METRICS_READ_LIMIT as m,FUNCTION_METRICS_SCANS_TABLE as x,FUNCTION_METRICS_TABLE as B,ensureFunctionMetricsTables as F,mergeScanAttribution as l,readFunctionMetricBuckets as g,readFunctionMetricIndexHits as O,readFunctionMetricScans as H,readFunctionMetrics as y,readFunctionMetricsTotals as D,recordFunctionMetric as h}from"./packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-BXPeggfa.mjs";import{DEFAULT_EXPLAIN_ISSUE_MODEL as b,explainIssue as q,parseExplainIssueArgs as v}from"./packem_shared/DEFAULT_EXPLAIN_ISSUE_MODEL-xF11R4vX.mjs";import{ISSUE_SEVERITIES as G,ISSUE_STATE_TABLE as X,ISSUE_STATUSES as P,upsertIssueState as k}from"./packem_shared/ISSUE_SEVERITIES-E91cPcjt.mjs";import{LogBuffer as V}from"./packem_shared/LogBuffer-bIvCelI-.mjs";import{M as j}from"./packem_shared/metric-buffer-CdgXal7w.mjs";import{readMetricHistory as J,recordMetricHistory as Y}from"./packem_shared/readMetricHistory-BdC01ptv.mjs";import{readQueryInsights as $,readQueryMetrics as ee,recordQueryMetric as re}from"./packem_shared/readQueryInsights-BprtfEp-.mjs";import{d as Te,w as oe,K as ae,x as se,h as Ee,F as _e,W as ce,D as Se,c as Ie}from"./packem_shared/request-log-BKVYrL1-.mjs";import{MIN_ADMIN_TOKEN_LENGTH as ne,MIN_AUTH_SECRET_LENGTH as Me,buildSecurityAudit as ue}from"./packem_shared/MIN_ADMIN_TOKEN_LENGTH-T-zuwRVR.mjs";import{SpanBuffer as Ce,foldTraces as Ne}from"./packem_shared/SpanBuffer-Z-gV9PQk.mjs";import{findDanglingReferences as Ue}from"./packem_shared/findDanglingReferences-D-x9LvY0.mjs";import{r as fe}from"./packem_shared/trace-context-DrdF960P.mjs";export{t as AUTH_METRICS_BUCKETS_TABLE,T as AUTH_METRICS_BUCKET_MS,o as AUTH_METRICS_BUCKET_RETENTION,a as AUTH_METRICS_TABLE,b as DEFAULT_EXPLAIN_ISSUE_MODEL,U as FUNCTION_METRICS_BUCKETS_TABLE,d as FUNCTION_METRICS_BUCKET_MS,f as FUNCTION_METRICS_BUCKET_RETENTION,R as FUNCTION_METRICS_INDEX_TABLE,L as FUNCTION_METRICS_MAX_PATHS,m as FUNCTION_METRICS_READ_LIMIT,x as FUNCTION_METRICS_SCANS_TABLE,B as FUNCTION_METRICS_TABLE,G as ISSUE_SEVERITIES,X as ISSUE_STATE_TABLE,P as ISSUE_STATUSES,V as LogBuffer,ne as MIN_ADMIN_TOKEN_LENGTH,Me as MIN_AUTH_SECRET_LENGTH,j as MetricBuffer,Te as REQUEST_LOG_TABLE,Ce as SpanBuffer,oe as appendRequestLogEntry,ue as buildSecurityAudit,A as createDatabaseTally,S as createMetrics,I as createSpanCollector,i as createTracedFetch,n as createTracer,M as dispatchRootSpan,ae as emitLogEvent,se as emitRequestLogEvent,s as ensureAuthMetricsTables,F as ensureFunctionMetricsTables,Ee as ensureRequestLogTable,q as explainIssue,Ue as findDanglingReferences,Ne as foldTraces,C as formatTally,N as instrumentDatabase,l as mergeScanAttribution,v as parseExplainIssueArgs,_e as parseLogArgs,E as readAuthMetrics,ce as readErrorIssues,g as readFunctionMetricBuckets,O as readFunctionMetricIndexHits,H as readFunctionMetricScans,y as readFunctionMetrics,D as readFunctionMetricsTotals,J as readMetricHistory,$ as readQueryInsights,ee as readQueryMetrics,Se as readRequestLog,_ as recordAuthEvent,h as recordFunctionMetric,Y as recordMetricHistory,re as recordQueryMetric,Ie as redactArgs,fe as resolveTraceAnchor,k as upsertIssueState};
@@ -1 +1 @@
1
- import"@lunora/fingerprint";import"@visulima/redact";import{E,d as g,v as L,K as p,w as m,h as R,F as d,X as i,C as n,c as u,I as T}from"./request-log-CHl9HlyL.mjs";import"./ISSUE_SEVERITIES-E91cPcjt.mjs";import"./run-sql-BP8BI9zV.mjs";export{E as REQUEST_LOG_RETENTION,g as REQUEST_LOG_TABLE,L as appendRequestLogEntry,p as emitLogEvent,m as emitRequestLogEvent,R as ensureRequestLogTable,d as parseLogArgs,i as readErrorIssues,n as readRequestLog,u as redactArgs,T as renderLogMessage};
1
+ import"@lunora/fingerprint";import"@visulima/redact";import{E,d as g,w as L,K as p,x as m,h as R,F as d,W as i,D as n,c as u,S as T}from"./request-log-BKVYrL1-.mjs";import"./ISSUE_SEVERITIES-E91cPcjt.mjs";import"./run-sql-BP8BI9zV.mjs";export{E as REQUEST_LOG_RETENTION,g as REQUEST_LOG_TABLE,L as appendRequestLogEntry,p as emitLogEvent,m as emitRequestLogEvent,R as ensureRequestLogTable,d as parseLogArgs,i as readErrorIssues,n as readRequestLog,u as redactArgs,T as renderLogMessage};
@@ -0,0 +1 @@
1
+ class m{buffer=[];capacity;constructor(s=500){this.capacity=s>0?Math.trunc(s):500}get size(){return this.buffer.length}clear(){this.buffer.length=0}entries(){return[...this.buffer]}hasTrace(s){return this.buffer.some(r=>r.traceId===s)}push(s){this.buffer.push(s),this.buffer.length>this.capacity&&this.buffer.shift()}}const T=50,b=i=>{const s=new Map;for(const r of i){const d=s.get(r.traceId);d===void 0?s.set(r.traceId,[r]):d.push(r)}return s},v=(i,s)=>{const r=i.find(o=>o.dispatch===!0);if(r!==void 0)return r;const d=i.toSorted((o,a)=>o.startTs-a.startTs);return d.find(o=>!s.has(o.parentSpanId))??d[0]},M=(i,s)=>{const r=new Map([[i.spanId,0]]);return d=>{const o=[],a=new Set;let n=d,p=0;for(;;){const e=r.get(n.spanId);if(e!==void 0){p=e;break}if(a.has(n.spanId))break;a.add(n.spanId),o.push(n);const c=s.get(n.parentSpanId);if(c===void 0)break;n=c}for(const[e,c]of o.toReversed().entries())r.set(c.spanId,p+e+1);return r.get(d.spanId)??p}},S=(i,s=T)=>{const r=b(i),d=[...r.entries()].map(([a,n])=>({group:n,startTs:Math.min(...n.map(p=>p.startTs)),traceId:a})).toSorted((a,n)=>n.startTs-a.startTs).slice(0,s),o=[];for(const{group:a,traceId:n}of d){const p=new Map(a.map(t=>[t.spanId,t])),e=v(a,p);if(e===void 0)continue;const c=M(e,p),{startTs:f}=e,h=Math.max(...a.map(t=>t.startTs+t.durationMs)),I=a.map(t=>({...t.attributes===void 0?{}:{attributes:t.attributes},depth:c(t),durationMs:t.durationMs,...t.error===void 0?{}:{error:t.error},...t.events===void 0?{}:{events:t.events},...t.kind===void 0?{}:{kind:t.kind},name:t.name,offsetMs:Math.max(0,t.startTs-f),ok:t.ok,parentSpanId:t.parentSpanId,spanId:t.spanId})).toSorted((t,u)=>t.offsetMs-u.offsetMs||t.depth-u.depth);o.push({durationMs:h-f,functionPath:e.functionPath,ok:a.every(t=>t.ok),rootName:e.name,...e.shardKey===void 0?{}:{shardKey:e.shardKey},spans:I,startTs:f,traceId:n})}return{total:r.size,traces:o.toSorted((a,n)=>n.startTs-a.startTs)}};export{T as DEFAULT_TRACE_LIMIT,m as SpanBuffer,S as foldTraces};
@@ -1 +1 @@
1
- import{O as h,t as m}from"./trace-context-DrdF960P.mjs";import{c as b}from"./request-log-CHl9HlyL.mjs";const M=100,w=new Set(["aggregate","count","delete","deleteMany","deleteWhere","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","insertMany","insertManyUnsafe","lookupById","patch","patchMany","patchWhere","rank","rankBefore","rankPage","rankPageRows","replace","restore"]),k=new Set(["aggregate","count","deleteWhere","findFirst","findFirstOrThrow","findMany","groupBy","insert","insertMany","insertManyUnsafe","patchWhere","rank","rankBefore","rankPage","rankPageRows"]),O=(t,r)=>{if(!k.has(t))return;const e=r[0];return typeof e=="string"&&e.length>0?e:void 0},T=t=>t instanceof Error?t.message:typeof t=="string"?t:JSON.stringify(t)??String(t),I=t=>{const{deps:r,durationMs:e,failure:n,operation:s,startTs:a,table:o}=t;return{attributes:{"db.operation.name":s,...o===void 0?{}:{"db.collection.name":o},"db.system.name":"sqlite"},durationMs:e,...n===void 0?{}:{error:{message:b(T(n),r.captureRaw),type:m(n)}},functionPath:r.functionPath,kind:"client",name:o===void 0?`db.${s}`:`db.${s} ${o}`,ok:n===void 0,parentSpanId:r.anchor.rootSpanId,shardKey:r.shardKey,spanId:h(8),startTs:a,traceId:r.anchor.traceId,userId:r.userId()}},S=(t,r)=>{if(r.mode==="off")return t;const{tally:e}=r,n=new Map;return new Proxy(t,{get(s,a,o){const d=Reflect.get(s,a,o);if(typeof a!="string"||typeof d!="function"||!w.has(a))return d;const p=n.get(a);if(p!==void 0)return p;const y=d,u=async(...f)=>{const l=Date.now(),g=O(a,f);let c;try{return await y.apply(s,f)}catch(i){throw c=i,i}finally{const i=Date.now()-l;e.calls+=1,e.durationMs+=i,e.perOperation[a]=(e.perOperation[a]??0)+1,c!==void 0&&(e.errors+=1);try{r.mode==="spans"&&(e.spansEmitted>=M?e.spansTruncated=!0:(e.spansEmitted+=1,r.record(I({deps:r,durationMs:i,failure:c,operation:a,startTs:l,table:g}))))}catch{}}};return n.set(a,u),u}})},E=()=>({calls:0,durationMs:0,errors:0,perOperation:{},spansEmitted:0,spansTruncated:!1}),B=t=>{const r={"db.calls":t.calls,"db.duration_ms":t.durationMs};t.errors>0&&(r["db.errors"]=t.errors),t.spansTruncated&&(r["db.spans_truncated"]=!0);for(const[e,n]of Object.entries(t.perOperation))r[`db.op.${e}`]=n;return r};export{E as createDatabaseTally,B as formatTally,S as instrumentDatabase};
1
+ import{O as h,t as m}from"./trace-context-DrdF960P.mjs";import{c as b}from"./request-log-BKVYrL1-.mjs";const M=100,w=new Set(["aggregate","count","delete","deleteMany","deleteWhere","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","insertMany","insertManyUnsafe","lookupById","patch","patchMany","patchWhere","rank","rankBefore","rankPage","rankPageRows","replace","restore"]),k=new Set(["aggregate","count","deleteWhere","findFirst","findFirstOrThrow","findMany","groupBy","insert","insertMany","insertManyUnsafe","patchWhere","rank","rankBefore","rankPage","rankPageRows"]),O=(t,r)=>{if(!k.has(t))return;const e=r[0];return typeof e=="string"&&e.length>0?e:void 0},T=t=>t instanceof Error?t.message:typeof t=="string"?t:JSON.stringify(t)??String(t),I=t=>{const{deps:r,durationMs:e,failure:n,operation:s,startTs:a,table:o}=t;return{attributes:{"db.operation.name":s,...o===void 0?{}:{"db.collection.name":o},"db.system.name":"sqlite"},durationMs:e,...n===void 0?{}:{error:{message:b(T(n),r.captureRaw),type:m(n)}},functionPath:r.functionPath,kind:"client",name:o===void 0?`db.${s}`:`db.${s} ${o}`,ok:n===void 0,parentSpanId:r.anchor.rootSpanId,shardKey:r.shardKey,spanId:h(8),startTs:a,traceId:r.anchor.traceId,userId:r.userId()}},S=(t,r)=>{if(r.mode==="off")return t;const{tally:e}=r,n=new Map;return new Proxy(t,{get(s,a,o){const d=Reflect.get(s,a,o);if(typeof a!="string"||typeof d!="function"||!w.has(a))return d;const p=n.get(a);if(p!==void 0)return p;const y=d,u=async(...f)=>{const l=Date.now(),g=O(a,f);let c;try{return await y.apply(s,f)}catch(i){throw c=i,i}finally{const i=Date.now()-l;e.calls+=1,e.durationMs+=i,e.perOperation[a]=(e.perOperation[a]??0)+1,c!==void 0&&(e.errors+=1);try{r.mode==="spans"&&(e.spansEmitted>=M?e.spansTruncated=!0:(e.spansEmitted+=1,r.record(I({deps:r,durationMs:i,failure:c,operation:a,startTs:l,table:g}))))}catch{}}};return n.set(a,u),u}})},E=()=>({calls:0,durationMs:0,errors:0,perOperation:{},spansEmitted:0,spansTruncated:!1}),B=t=>{const r={"db.calls":t.calls,"db.duration_ms":t.durationMs};t.errors>0&&(r["db.errors"]=t.errors),t.spansTruncated&&(r["db.spans_truncated"]=!0);for(const[e,n]of Object.entries(t.perOperation))r[`db.op.${e}`]=n;return r};export{E as createDatabaseTally,B as formatTally,S as instrumentDatabase};
@@ -1 +1 @@
1
- import{c as K,n as g}from"./request-log-CHl9HlyL.mjs";import{w as b,O as M,m as R,t as T}from"./trace-context-DrdF960P.mjs";const x=/[\w.-]/u,D=t=>{let e="";for(const r of t)e+=x.test(r)?r:"_";return e},L=t=>{if(typeof t.name!="string"||t.name.length===0)throw new Error("recordEvaluation requires a non-empty `name`");if(typeof t.score!="number"||!Number.isFinite(t.score))throw new Error("recordEvaluation `score` must be a finite number");const e=D(t.name),r={[`gen_ai.evaluation.${e}.score`]:t.score};return t.label!==void 0&&(r[`gen_ai.evaluation.${e}.label`]=t.label),r},_=t=>{const e=Object.keys(t);return e.length>0&&e.every(r=>r==="attributes"||r==="kind"||r==="links")},F=128,H=128,U=t=>{try{const e=new URL(t);return`${e.protocol}//${e.host}${e.pathname}`}catch{return t}},q=t=>{try{return new URL(t).host}catch{return t}},C=(t,e)=>{try{return t(new URL(e))}catch{return!1}},N=t=>t===void 0?{}:_(t)?t:{attributes:t},z=(t,e)=>{if(t.isTraced){t.setAttribute(b.functionPath,e.functionPath),t.setAttribute(b.ok,e.ok),t.setAttribute(b.durationMs,e.durationMs),e.shardKey!==void 0&&t.setAttribute(b.shardKey,e.shardKey),e.userId!==void 0&&t.setAttribute(b.userId,e.userId),e.error!==void 0&&(t.setAttribute(b.errorType,e.error.type),t.setAttribute(b.errorMessage,e.error.message));for(const[r,s]of Object.entries(e.attributes))(typeof s=="boolean"||typeof s=="number"||typeof s=="string")&&t.setAttribute(`lunora.attr.${r}`,s)}},B=(t,e=!1)=>{const r={attributes:{},events:[],links:[]},s={spanContext:()=>t,addEvent:(n,a)=>{if(r.events.length>=F)return;const o=g(a);r.events.push({...o===void 0?{}:{attributes:o},name:n,ts:Date.now()})},addLink:n=>{if(r.links.length>=H)return;const a=g(n.attributes);r.links.push({...a===void 0?{}:{attributes:a},spanId:n.spanId,traceId:n.traceId})},recordEvaluation:n=>{Object.assign(r.attributes,g(L(n)))},recordException:n=>{const a=n instanceof Error?n.message:String(n);s.addEvent("exception",{"exception.message":K(a,e),...e&&n instanceof Error&&typeof n.stack=="string"?{"exception.stacktrace":n.stack}:{},"exception.type":T(n)})},setAttribute:(n,a)=>{Object.assign(r.attributes,g({[n]:a}))},setAttributes:n=>{Object.assign(r.attributes,g(n))}};return{collected:r,handle:s}},Q=t=>{const{anchor:e,captureRaw:r=!1,fuseHostSpans:s,functionPath:n,record:a,resolveHostTracing:o,shardKey:i,userId:h}=t,u=p=>async(m,d,f)=>{const y=M(8),c=Date.now(),I=N(f),j=g(I.attributes),{collected:w,handle:O}=B({spanId:y,traceId:e.traceId},r),P=async v=>{let k=!0,S;try{return await d(u(y),O)}catch(l){k=!1;const E=l instanceof Error?l.message:String(l);throw S={message:K(E,r),type:T(l)},l}finally{const l=Date.now()-c,E=h(),A={...j,...w.attributes},$=[...I.links??[],...w.links];try{a({...Object.keys(A).length===0?{}:{attributes:A},durationMs:l,...w.events.length===0?{}:{events:w.events},...S===void 0?{}:{error:S},functionPath:n,...I.kind===void 0||I.kind==="internal"?{}:{kind:I.kind},...$.length===0?{}:{links:$},name:m,ok:k,parentSpanId:p,shardKey:i,spanId:y,startTs:c,traceId:e.traceId,userId:E})}catch{}if(v!==void 0)try{z(v,{attributes:A,durationMs:l,error:S,functionPath:n,ok:k,shardKey:i,userId:E})}catch{}}};if(s===!0&&o!==void 0){const v=await o();if(v!==void 0&&typeof v.enterSpan=="function")return await v.enterSpan(m,k=>P(k))}return await P()};return u(e.rootSpanId)},V=(t,e)=>{const{anchor:r,functionPath:s,propagate:n=!0,record:a,shardKey:o,userId:i}=t;return async(h,u)=>{const p=M(8),m=Date.now(),d=new Request(h,u);(typeof n=="function"?C(n,d.url):n)&&d.headers.set("traceparent",R(r.traceId,p,r.sampled??!0));let f,y;try{const c=await e(d);return y=c.status,c.ok||(f={message:`HTTP ${String(c.status)}`,type:`HTTP_${String(c.status)}`}),c}catch(c){throw f={message:c instanceof Error?c.message:String(c),type:T(c)},c}finally{try{a({attributes:{"http.request.method":d.method,...y===void 0?{}:{"http.response.status_code":y},"url.full":U(d.url)},durationMs:Date.now()-m,...f===void 0?{}:{error:f},functionPath:s,kind:"client",name:`${d.method} ${q(d.url)}`,ok:f===void 0,parentSpanId:r.rootSpanId,shardKey:o,spanId:p,startTs:m,traceId:r.traceId,userId:i()})}catch{}}}},W=t=>{const{functionPath:e,record:r,shardKey:s}=t,n=(a,o,i,h)=>{if(!Number.isFinite(i))return;const u=g(h);try{r({...u===void 0?{}:{attributes:u},functionPath:e,kind:a,name:o,shardKey:s,ts:Date.now(),value:i})}catch{}};return{count:(a,o=1,i)=>{n("counter",a,o,i)},gauge:(a,o,i)=>{n("gauge",a,o,i)},record:(a,o,i)=>{n("histogram",a,o,i)}}},X=t=>{const{anchor:e,captureRaw:r=!1,collected:s,durationMs:n,failure:a,functionPath:o,shardKey:i,startTs:h,userId:u}=t,p=s?.attributes??{};return{...Object.keys(p).length===0?{}:{attributes:p},dispatch:!0,durationMs:n,...s===void 0||s.events.length===0?{}:{events:s.events},...a===void 0?{}:{error:{message:K(a.thrown instanceof Error?a.thrown.message:String(a.thrown),r),type:T(a.thrown)}},functionPath:o,...s===void 0||s.links.length===0?{}:{links:s.links},name:o,ok:a===void 0,parentSpanId:"",shardKey:i,spanId:e.rootSpanId,startTs:h,traceId:e.traceId,userId:u}};export{z as applyHostSpanAttributes,W as createMetrics,B as createSpanCollector,V as createTracedFetch,Q as createTracer,X as dispatchRootSpan};
1
+ import{c as K,n as g}from"./request-log-BKVYrL1-.mjs";import{w as b,O as M,m as R,t as T}from"./trace-context-DrdF960P.mjs";const x=/[\w.-]/u,D=t=>{let e="";for(const r of t)e+=x.test(r)?r:"_";return e},L=t=>{if(typeof t.name!="string"||t.name.length===0)throw new Error("recordEvaluation requires a non-empty `name`");if(typeof t.score!="number"||!Number.isFinite(t.score))throw new Error("recordEvaluation `score` must be a finite number");const e=D(t.name),r={[`gen_ai.evaluation.${e}.score`]:t.score};return t.label!==void 0&&(r[`gen_ai.evaluation.${e}.label`]=t.label),r},_=t=>{const e=Object.keys(t);return e.length>0&&e.every(r=>r==="attributes"||r==="kind"||r==="links")},F=128,H=128,U=t=>{try{const e=new URL(t);return`${e.protocol}//${e.host}${e.pathname}`}catch{return t}},q=t=>{try{return new URL(t).host}catch{return t}},C=(t,e)=>{try{return t(new URL(e))}catch{return!1}},N=t=>t===void 0?{}:_(t)?t:{attributes:t},z=(t,e)=>{if(t.isTraced){t.setAttribute(b.functionPath,e.functionPath),t.setAttribute(b.ok,e.ok),t.setAttribute(b.durationMs,e.durationMs),e.shardKey!==void 0&&t.setAttribute(b.shardKey,e.shardKey),e.userId!==void 0&&t.setAttribute(b.userId,e.userId),e.error!==void 0&&(t.setAttribute(b.errorType,e.error.type),t.setAttribute(b.errorMessage,e.error.message));for(const[r,s]of Object.entries(e.attributes))(typeof s=="boolean"||typeof s=="number"||typeof s=="string")&&t.setAttribute(`lunora.attr.${r}`,s)}},B=(t,e=!1)=>{const r={attributes:{},events:[],links:[]},s={spanContext:()=>t,addEvent:(n,a)=>{if(r.events.length>=F)return;const o=g(a);r.events.push({...o===void 0?{}:{attributes:o},name:n,ts:Date.now()})},addLink:n=>{if(r.links.length>=H)return;const a=g(n.attributes);r.links.push({...a===void 0?{}:{attributes:a},spanId:n.spanId,traceId:n.traceId})},recordEvaluation:n=>{Object.assign(r.attributes,g(L(n)))},recordException:n=>{const a=n instanceof Error?n.message:String(n);s.addEvent("exception",{"exception.message":K(a,e),...e&&n instanceof Error&&typeof n.stack=="string"?{"exception.stacktrace":n.stack}:{},"exception.type":T(n)})},setAttribute:(n,a)=>{Object.assign(r.attributes,g({[n]:a}))},setAttributes:n=>{Object.assign(r.attributes,g(n))}};return{collected:r,handle:s}},Q=t=>{const{anchor:e,captureRaw:r=!1,fuseHostSpans:s,functionPath:n,record:a,resolveHostTracing:o,shardKey:i,userId:h}=t,u=p=>async(m,d,f)=>{const y=M(8),c=Date.now(),I=N(f),j=g(I.attributes),{collected:w,handle:O}=B({spanId:y,traceId:e.traceId},r),P=async v=>{let k=!0,S;try{return await d(u(y),O)}catch(l){k=!1;const E=l instanceof Error?l.message:String(l);throw S={message:K(E,r),type:T(l)},l}finally{const l=Date.now()-c,E=h(),A={...j,...w.attributes},$=[...I.links??[],...w.links];try{a({...Object.keys(A).length===0?{}:{attributes:A},durationMs:l,...w.events.length===0?{}:{events:w.events},...S===void 0?{}:{error:S},functionPath:n,...I.kind===void 0||I.kind==="internal"?{}:{kind:I.kind},...$.length===0?{}:{links:$},name:m,ok:k,parentSpanId:p,shardKey:i,spanId:y,startTs:c,traceId:e.traceId,userId:E})}catch{}if(v!==void 0)try{z(v,{attributes:A,durationMs:l,error:S,functionPath:n,ok:k,shardKey:i,userId:E})}catch{}}};if(s===!0&&o!==void 0){const v=await o();if(v!==void 0&&typeof v.enterSpan=="function")return await v.enterSpan(m,k=>P(k))}return await P()};return u(e.rootSpanId)},V=(t,e)=>{const{anchor:r,functionPath:s,propagate:n=!0,record:a,shardKey:o,userId:i}=t;return async(h,u)=>{const p=M(8),m=Date.now(),d=new Request(h,u);(typeof n=="function"?C(n,d.url):n)&&d.headers.set("traceparent",R(r.traceId,p,r.sampled??!0));let f,y;try{const c=await e(d);return y=c.status,c.ok||(f={message:`HTTP ${String(c.status)}`,type:`HTTP_${String(c.status)}`}),c}catch(c){throw f={message:c instanceof Error?c.message:String(c),type:T(c)},c}finally{try{a({attributes:{"http.request.method":d.method,...y===void 0?{}:{"http.response.status_code":y},"url.full":U(d.url)},durationMs:Date.now()-m,...f===void 0?{}:{error:f},functionPath:s,kind:"client",name:`${d.method} ${q(d.url)}`,ok:f===void 0,parentSpanId:r.rootSpanId,shardKey:o,spanId:p,startTs:m,traceId:r.traceId,userId:i()})}catch{}}}},W=t=>{const{functionPath:e,record:r,shardKey:s}=t,n=(a,o,i,h)=>{if(!Number.isFinite(i))return;const u=g(h);try{r({...u===void 0?{}:{attributes:u},functionPath:e,kind:a,name:o,shardKey:s,ts:Date.now(),value:i})}catch{}};return{count:(a,o=1,i)=>{n("counter",a,o,i)},gauge:(a,o,i)=>{n("gauge",a,o,i)},record:(a,o,i)=>{n("histogram",a,o,i)}}},X=t=>{const{anchor:e,captureRaw:r=!1,collected:s,durationMs:n,failure:a,functionPath:o,shardKey:i,startTs:h,userId:u}=t,p=s?.attributes??{};return{...Object.keys(p).length===0?{}:{attributes:p},dispatch:!0,durationMs:n,...s===void 0||s.events.length===0?{}:{events:s.events},...a===void 0?{}:{error:{message:K(a.thrown instanceof Error?a.thrown.message:String(a.thrown),r),type:T(a.thrown)}},functionPath:o,...s===void 0||s.links.length===0?{}:{links:s.links},name:o,ok:a===void 0,parentSpanId:"",shardKey:i,spanId:e.rootSpanId,startTs:h,traceId:e.traceId,userId:u}};export{z as applyHostSpanAttributes,W as createMetrics,B as createSpanCollector,V as createTracedFetch,Q as createTracer,X as dispatchRootSpan};
@@ -0,0 +1,22 @@
1
+ import{fingerprintError as N}from"@lunora/fingerprint";import{redact as R,standardRules as M}from"@visulima/redact";import{readIssueStates as P}from"./ISSUE_SEVERITIES-E91cPcjt.mjs";import{e as f}from"./run-sql-BP8BI9zV.mjs";const w=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},T=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:w(e),m=(e,t)=>{if(e===void 0&&t===void 0)return;const s={};if(t!==void 0)for(const[o,r]of Object.entries(t))s[o]=T(r);if(e!==void 0)for(const[o,r]of Object.entries(e))s[o]=T(r);return Object.keys(s).length===0?void 0:s},d="__lunora_reqlog__",p=1e3,I="lunora",X=["error_fingerprint TEXT","trace_id TEXT"],c=(e,t=!1)=>t||e===null||e===void 0?e:R(e,M),E=e=>{f(e,`CREATE TABLE IF NOT EXISTS "${d}" (
2
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
3
+ ts REAL NOT NULL,
4
+ function_path TEXT NOT NULL,
5
+ shard_key TEXT,
6
+ user_id TEXT,
7
+ identity TEXT,
8
+ args TEXT,
9
+ outcome TEXT NOT NULL,
10
+ error_message TEXT,
11
+ error_fingerprint TEXT,
12
+ trace_id TEXT,
13
+ duration_ms REAL NOT NULL,
14
+ tables_read TEXT NOT NULL DEFAULT '[]',
15
+ tables_written TEXT NOT NULL DEFAULT '[]',
16
+ cache_hit INTEGER,
17
+ subscriptions_rerun INTEGER NOT NULL DEFAULT 0
18
+ )`);for(const t of X)try{f(e,`ALTER TABLE "${d}" ADD COLUMN ${t}`)}catch{}},S=e=>JSON.stringify([...new Set(e)].toSorted((t,s)=>t.localeCompare(s))),U=e=>e===void 0?null:e?1:0,x=(e,t,s={})=>{E(e);const o=s.captureRaw??!1,r=s.retention??p,i=t.outcome==="error"&&t.errorMessage!==void 0?N({functionPath:t.functionPath,message:t.errorMessage}).hash:void 0;f(e,`INSERT INTO "${d}"
19
+ (ts, function_path, shard_key, user_id, identity, args, outcome, error_message, error_fingerprint, trace_id, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun)
20
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,t.ts,t.functionPath,t.shardKey??null,t.userId??null,t.identity===void 0?null:JSON.stringify(c(t.identity,o)),t.redactedArgs===void 0?null:JSON.stringify(c(t.redactedArgs,o)),t.outcome,t.errorMessage===void 0?null:c(t.errorMessage,o),i??null,t.traceId??null,t.durationMs,S(t.tablesRead),S(t.tablesWritten),U(t.cacheHit),t.subscriptionsReRun??0),f(e,`DELETE FROM "${d}" WHERE seq <= (SELECT MAX(seq) - ? FROM "${d}")`,r)},W=(e,t={})=>{const s=t.captureRaw??!1,o={args:e.redactedArgs===void 0?void 0:c(e.redactedArgs,s),cacheHit:e.cacheHit,durationMs:e.durationMs,error:e.errorMessage===void 0?void 0:c(e.errorMessage,s),function:e.functionPath,identity:e.identity===void 0?void 0:c(e.identity,s),outcome:e.outcome,shard:e.shardKey,source:I,tablesRead:e.tablesRead??[],tablesWritten:e.tablesWritten??[],traceId:e.traceId,ts:e.ts,type:"request",userId:e.userId},r=JSON.stringify(o);e.outcome==="error"?console.error(r):console.log(r)},q="log",C=e=>e.map(t=>{if(typeof t=="string")return t;try{return JSON.stringify(t)??String(t)}catch{return String(t)}}).join(" "),D=e=>{if(typeof e!="object"||e===null||Array.isArray(e))return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null},$=(e,t)=>e.length===2&&typeof e[0]=="string"&&D(e[1])?{fields:m(e[1],t),message:e[0]}:{fields:m(void 0,t),message:C(e)},H=(e,t={})=>{const s=t.captureRaw??!1,o={fields:e.fields===void 0?void 0:c(e.fields,s),function:e.functionPath,level:e.level,message:e.message,shard:e.shardKey,source:I,spanId:e.spanId,traceId:e.traceId,ts:e.ts,type:q,userId:e.userId};let r;try{r=JSON.stringify(o)}catch{r=JSON.stringify({...o,fields:void 0})}e.level==="error"||e.level==="fatal"?console.error(r):e.level==="warn"?console.warn(r):console.log(r)},O=e=>e.replaceAll(/[\\%_]/g,t=>`\\${t}`),b=(e,t,s)=>{s.functionPathPrefix!==void 0&&s.functionPathPrefix!==""&&(e.push(String.raw`function_path LIKE ? ESCAPE '\'`),t.push(`${O(s.functionPathPrefix)}%`)),s.userId!==void 0&&s.userId!==""&&(e.push("user_id = ?"),t.push(s.userId)),s.shardKey!==void 0&&s.shardKey!==""&&(e.push("shard_key = ?"),t.push(s.shardKey))},v=e=>{try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}catch{return[]}},Y=(e,t={})=>{E(e);const s=Math.max(1,Math.min(t.limit??p,1e4)),o=["seq > ?"],r=[t.sinceSeq??0];if(b(o,r,t),t.outcome!==void 0&&(o.push("outcome = ?"),r.push(t.outcome)),t.tableTouched!==void 0&&t.tableTouched!==""){const i=`%${O(JSON.stringify(t.tableTouched))}%`;o.push(String.raw`(tables_read LIKE ? ESCAPE '\' OR tables_written LIKE ? ESCAPE '\')`),r.push(i,i)}return r.push(s),f(e,`SELECT seq, ts, function_path, shard_key, user_id, identity, args, outcome, error_message, trace_id, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun
21
+ FROM "${d}" WHERE ${o.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray().map(i=>{const n={durationMs:i.duration_ms,functionPath:i.function_path,outcome:i.outcome==="error"?"error":"ok",seq:i.seq,subscriptionsReRun:i.subscriptions_rerun,tablesRead:v(i.tables_read),tablesWritten:v(i.tables_written),ts:i.ts};return i.shard_key!==null&&(n.shardKey=i.shard_key),i.user_id!==null&&(n.userId=i.user_id),i.identity!==null&&(n.identity=JSON.parse(i.identity)),i.args!==null&&(n.redactedArgs=JSON.parse(i.args)),i.error_message!==null&&(n.errorMessage=i.error_message),i.cache_hit!==null&&(n.cacheHit=i.cache_hit===1),i.trace_id!==null&&(n.traceId=i.trace_id),n})},F=(e,t)=>{const s=P(e,[...t.keys()]);for(const o of t.values()){const r=s.get(o.hash);r!==void 0&&(o.stateUpdatedAt=r.updatedAt,r.assignee!==void 0&&(o.assignee=r.assignee),r.severity!==void 0&&(o.severity=r.severity),o.status=r.status==="resolved"&&o.lastSeen>r.updatedAt?"open":r.status)}},B=(e,t={})=>{E(e);const s=Math.max(1,Math.min(t.limit??p,1e4)),o=["outcome = 'error'"],r=[];b(o,r,t),r.push(s);const i=f(e,`SELECT function_path, error_message, error_fingerprint, ts
22
+ FROM "${d}" WHERE ${o.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray(),n=new Map,g=new Map;for(const a of i){const h=a.error_message??"",{culprit:A,hash:L,title:y}=N({functionPath:a.function_path,message:h}),l=a.error_fingerprint??L,u=n.get(l);if(u===void 0){n.set(l,{count:1,culprit:A,firstSeen:a.ts,hash:l,lastSeen:a.ts,sampleMessage:h,status:"open",title:y}),g.set(l,a.ts);continue}u.count+=1,u.firstSeen=Math.min(u.firstSeen,a.ts),u.lastSeen=Math.max(u.lastSeen,a.ts),a.ts>(g.get(l)??Number.NEGATIVE_INFINITY)&&(g.set(l,a.ts),u.sampleMessage=h,u.title=y)}F(e,n);const _=[...n.values()];return(t.status===void 0?_:_.filter(a=>a.status===t.status)).toSorted((a,h)=>h.lastSeen-a.lastSeen)};export{Y as D,p as E,$ as F,H as K,C as S,B as W,c,d,E as h,m as n,x as w,W as x};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/observability",
3
- "version": "1.0.0-alpha.18",
3
+ "version": "1.0.0-alpha.19",
4
4
  "description": "Host-neutral telemetry storage and read models for Lunora, backing the Studio's Logs, Traces, Metrics and Issues views",
5
5
  "keywords": [
6
6
  "lunora",
@@ -1 +0,0 @@
1
- class S{buffer=[];capacity;constructor(s=500){this.capacity=s>0?Math.trunc(s):500}get size(){return this.buffer.length}clear(){this.buffer.length=0}entries(){return[...this.buffer]}hasTrace(s){return this.buffer.some(r=>r.traceId===s)}push(s){this.buffer.push(s),this.buffer.length>this.capacity&&this.buffer.shift()}}const T=50,b=i=>{const s=new Map;for(const r of i){const d=s.get(r.traceId);d===void 0?s.set(r.traceId,[r]):d.push(r)}return s},M=(i,s)=>{const r=i.find(o=>o.dispatch===!0);if(r!==void 0)return r;const d=i.toSorted((o,a)=>o.startTs-a.startTs);return d.find(o=>!s.has(o.parentSpanId))??d[0]},m=(i,s)=>{const r=new Map([[i.spanId,0]]);return d=>{const o=[],a=new Set;let e=d,p=0;for(;;){const n=r.get(e.spanId);if(n!==void 0){p=n;break}if(a.has(e.spanId))break;a.add(e.spanId),o.push(e);const c=s.get(e.parentSpanId);if(c===void 0)break;e=c}for(const[n,c]of o.toReversed().entries())r.set(c.spanId,p+n+1);return r.get(d.spanId)??p}},g=(i,s=T)=>{const r=b(i),d=[...r.entries()].map(([a,e])=>({group:e,startTs:Math.min(...e.map(p=>p.startTs)),traceId:a})).toSorted((a,e)=>e.startTs-a.startTs).slice(0,s),o=[];for(const{group:a,traceId:e}of d){const p=new Map(a.map(t=>[t.spanId,t])),n=M(a,p);if(n===void 0)continue;const c=m(n,p),{startTs:f}=n,h=Math.max(...a.map(t=>t.startTs+t.durationMs)),I=a.map(t=>({...t.attributes===void 0?{}:{attributes:t.attributes},depth:c(t),durationMs:t.durationMs,...t.error===void 0?{}:{error:t.error},name:t.name,offsetMs:Math.max(0,t.startTs-f),ok:t.ok,parentSpanId:t.parentSpanId,spanId:t.spanId})).toSorted((t,u)=>t.offsetMs-u.offsetMs||t.depth-u.depth);o.push({durationMs:h-f,functionPath:n.functionPath,ok:a.every(t=>t.ok),rootName:n.name,...n.shardKey===void 0?{}:{shardKey:n.shardKey},spans:I,startTs:f,traceId:e})}return{total:r.size,traces:o.toSorted((a,e)=>e.startTs-a.startTs)}};export{T as DEFAULT_TRACE_LIMIT,S as SpanBuffer,g as foldTraces};
@@ -1,21 +0,0 @@
1
- import{fingerprintError as N}from"@lunora/fingerprint";import{redact as I,standardRules as M}from"@visulima/redact";import{readIssueStates as P}from"./ISSUE_SEVERITIES-E91cPcjt.mjs";import{e as f}from"./run-sql-BP8BI9zV.mjs";const w=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},m=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:w(e),T=(e,t)=>{if(e===void 0&&t===void 0)return;const s={};if(t!==void 0)for(const[i,r]of Object.entries(t))s[i]=m(r);if(e!==void 0)for(const[i,r]of Object.entries(e))s[i]=m(r);return Object.keys(s).length===0?void 0:s},d="__lunora_reqlog__",p=1e3,b="lunora",c=(e,t=!1)=>t||e===null||e===void 0?e:I(e,M),E=e=>{f(e,`CREATE TABLE IF NOT EXISTS "${d}" (
2
- seq INTEGER PRIMARY KEY AUTOINCREMENT,
3
- ts REAL NOT NULL,
4
- function_path TEXT NOT NULL,
5
- shard_key TEXT,
6
- user_id TEXT,
7
- identity TEXT,
8
- args TEXT,
9
- outcome TEXT NOT NULL,
10
- error_message TEXT,
11
- error_fingerprint TEXT,
12
- duration_ms REAL NOT NULL,
13
- tables_read TEXT NOT NULL DEFAULT '[]',
14
- tables_written TEXT NOT NULL DEFAULT '[]',
15
- cache_hit INTEGER,
16
- subscriptions_rerun INTEGER NOT NULL DEFAULT 0
17
- )`);try{f(e,`ALTER TABLE "${d}" ADD COLUMN error_fingerprint TEXT`)}catch{}},S=e=>JSON.stringify([...new Set(e)].toSorted((t,s)=>t.localeCompare(s))),U=e=>e===void 0?null:e?1:0,k=(e,t,s={})=>{E(e);const i=s.captureRaw??!1,r=s.retention??p,o=t.outcome==="error"&&t.errorMessage!==void 0?N({functionPath:t.functionPath,message:t.errorMessage}).hash:void 0;f(e,`INSERT INTO "${d}"
18
- (ts, function_path, shard_key, user_id, identity, args, outcome, error_message, error_fingerprint, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun)
19
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,t.ts,t.functionPath,t.shardKey??null,t.userId??null,t.identity===void 0?null:JSON.stringify(c(t.identity,i)),t.redactedArgs===void 0?null:JSON.stringify(c(t.redactedArgs,i)),t.outcome,t.errorMessage===void 0?null:c(t.errorMessage,i),o??null,t.durationMs,S(t.tablesRead),S(t.tablesWritten),U(t.cacheHit),t.subscriptionsReRun??0),f(e,`DELETE FROM "${d}" WHERE seq <= (SELECT MAX(seq) - ? FROM "${d}")`,r)},x=(e,t={})=>{const s=t.captureRaw??!1,i={args:e.redactedArgs===void 0?void 0:c(e.redactedArgs,s),cacheHit:e.cacheHit,durationMs:e.durationMs,error:e.errorMessage===void 0?void 0:c(e.errorMessage,s),function:e.functionPath,identity:e.identity===void 0?void 0:c(e.identity,s),outcome:e.outcome,shard:e.shardKey,source:b,tablesRead:e.tablesRead??[],tablesWritten:e.tablesWritten??[],ts:e.ts,type:"request",userId:e.userId},r=JSON.stringify(i);e.outcome==="error"?console.error(r):console.log(r)},X="log",q=e=>e.map(t=>{if(typeof t=="string")return t;try{return JSON.stringify(t)??String(t)}catch{return String(t)}}).join(" "),C=e=>{if(typeof e!="object"||e===null||Array.isArray(e))return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null},W=(e,t)=>e.length===2&&typeof e[0]=="string"&&C(e[1])?{fields:T(e[1],t),message:e[0]}:{fields:T(void 0,t),message:q(e)},H=(e,t={})=>{const s=t.captureRaw??!1,i={fields:e.fields===void 0?void 0:c(e.fields,s),function:e.functionPath,level:e.level,message:e.message,shard:e.shardKey,source:b,spanId:e.spanId,traceId:e.traceId,ts:e.ts,type:X,userId:e.userId};let r;try{r=JSON.stringify(i)}catch{r=JSON.stringify({...i,fields:void 0})}e.level==="error"||e.level==="fatal"?console.error(r):e.level==="warn"?console.warn(r):console.log(r)},O=e=>e.replaceAll(/[\\%_]/g,t=>`\\${t}`),A=(e,t,s)=>{s.functionPathPrefix!==void 0&&s.functionPathPrefix!==""&&(e.push(String.raw`function_path LIKE ? ESCAPE '\'`),t.push(`${O(s.functionPathPrefix)}%`)),s.userId!==void 0&&s.userId!==""&&(e.push("user_id = ?"),t.push(s.userId)),s.shardKey!==void 0&&s.shardKey!==""&&(e.push("shard_key = ?"),t.push(s.shardKey))},v=e=>{try{const t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}catch{return[]}},$=(e,t={})=>{E(e);const s=Math.max(1,Math.min(t.limit??p,1e4)),i=["seq > ?"],r=[t.sinceSeq??0];if(A(i,r,t),t.outcome!==void 0&&(i.push("outcome = ?"),r.push(t.outcome)),t.tableTouched!==void 0&&t.tableTouched!==""){const o=`%${O(JSON.stringify(t.tableTouched))}%`;i.push(String.raw`(tables_read LIKE ? ESCAPE '\' OR tables_written LIKE ? ESCAPE '\')`),r.push(o,o)}return r.push(s),f(e,`SELECT seq, ts, function_path, shard_key, user_id, identity, args, outcome, error_message, duration_ms, tables_read, tables_written, cache_hit, subscriptions_rerun
20
- FROM "${d}" WHERE ${i.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray().map(o=>{const n={durationMs:o.duration_ms,functionPath:o.function_path,outcome:o.outcome==="error"?"error":"ok",seq:o.seq,subscriptionsReRun:o.subscriptions_rerun,tablesRead:v(o.tables_read),tablesWritten:v(o.tables_written),ts:o.ts};return o.shard_key!==null&&(n.shardKey=o.shard_key),o.user_id!==null&&(n.userId=o.user_id),o.identity!==null&&(n.identity=JSON.parse(o.identity)),o.args!==null&&(n.redactedArgs=JSON.parse(o.args)),o.error_message!==null&&(n.errorMessage=o.error_message),o.cache_hit!==null&&(n.cacheHit=o.cache_hit===1),n})},F=(e,t)=>{const s=P(e,[...t.keys()]);for(const i of t.values()){const r=s.get(i.hash);r!==void 0&&(i.stateUpdatedAt=r.updatedAt,r.assignee!==void 0&&(i.assignee=r.assignee),r.severity!==void 0&&(i.severity=r.severity),i.status=r.status==="resolved"&&i.lastSeen>r.updatedAt?"open":r.status)}},Y=(e,t={})=>{E(e);const s=Math.max(1,Math.min(t.limit??p,1e4)),i=["outcome = 'error'"],r=[];A(i,r,t),r.push(s);const o=f(e,`SELECT function_path, error_message, error_fingerprint, ts
21
- FROM "${d}" WHERE ${i.join(" AND ")} ORDER BY seq DESC LIMIT ?`,...r).toArray(),n=new Map,g=new Map;for(const a of o){const h=a.error_message??"",{culprit:L,hash:R,title:_}=N({functionPath:a.function_path,message:h}),l=a.error_fingerprint??R,u=n.get(l);if(u===void 0){n.set(l,{count:1,culprit:L,firstSeen:a.ts,hash:l,lastSeen:a.ts,sampleMessage:h,status:"open",title:_}),g.set(l,a.ts);continue}u.count+=1,u.firstSeen=Math.min(u.firstSeen,a.ts),u.lastSeen=Math.max(u.lastSeen,a.ts),a.ts>(g.get(l)??Number.NEGATIVE_INFINITY)&&(g.set(l,a.ts),u.sampleMessage=h,u.title=_)}F(e,n);const y=[...n.values()];return(t.status===void 0?y:y.filter(a=>a.status===t.status)).toSorted((a,h)=>h.lastSeen-a.lastSeen)};export{$ as C,p as E,W as F,q as I,H as K,Y as X,c,d,E as h,T as n,k as v,x as w};