Conversation
Wire evlog/elysia into API, basket, links, and uptime with initLogger. Replace the old @databuddy/shared pino logger with evlog (including an RPC-compatible shim). Basket uses wide-event context via useLogger, moves producer/geo/schema enrichment off OTel span attributes, and drops setAttributes from basket tracing. Update lockfile and dependencies.
…xiom Remove OTLP trace SDK; wire createAxiomDrain in initLogger and simplify tracing helpers to evlog-only captureError/record.
Remove OTLP Node SDK, HTTP/pg/ORPC instrumentations, and request span plumbing. Wire createAxiomDrain on initLogger; map setAttributes/captureError to evlog; simplify agent query execution without active spans.
- Add structured-errors with basketErrors factories, ingest helpers, and buildBasketErrorPayload for consistent success/error/message responses. - Throw EvlogErrors from track, llm, request-validation (non-billing), and basket ingest routes; keep billing Response and pixel/bot ignore behavior. - Centralize onError JSON via buildBasketErrorPayload; fix invalid Biome nursery key useMaxParams so biome check runs.
|
You have used all of your free Bugbot PR reviews. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR is a large-scale observability infrastructure swap: OpenTelemetry (SDK, exporters, span processors) is removed from Key changes:
Issues found:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant Elysia as Elysia Middleware
participant evlog as evlog Plugin<br/>(Wide Event)
participant Handler as Route Handler
participant ValidateReq as validateRequest()
participant ErrorHandler as Global onError
Client->>Elysia: HTTP Request
Elysia->>evlog: Initialise wide event per request
evlog->>Handler: request context available
Handler->>Handler: useLogger().set({ route })
Handler->>ValidateReq: validateRequest(body, query, request)
alt Validation error (payload, clientId, origin, IP)
ValidateReq-->>Handler: throw EvlogError (status 4xx)
Handler-->>ErrorHandler: EvlogError re-thrown
ErrorHandler->>ErrorHandler: buildBasketErrorPayload()
ErrorHandler-->>Client: { status, error, why, fix }
else Billing exceeded
ValidateReq-->>Handler: return { error: Response }
Handler-->>Client: billing.response (429)
else Success
ValidateReq-->>Handler: return ValidatedRequest
Handler->>Handler: useLogger().set({ clientId, eventType, … })
Handler-->>Client: 200 OK
end
evlog->>evlog: Flush wide event to Axiom drain
|
| log[level]({ ...base, message: fieldsOrMessage }); | ||
| } else if (message !== undefined) { | ||
| log[level]({ ...base, ...fieldsOrMessage, message }); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Pino-compatible (obj, msg) or (msg) logging via evlog global `log`. | ||
| */ | ||
| export const logger = { | ||
| error: (fieldsOrMessage: Fields | string, message?: string) => | ||
| emit("error", fieldsOrMessage, message), | ||
| info: (fieldsOrMessage: Fields | string, message?: string) => | ||
| emit("info", fieldsOrMessage, message), | ||
| warn: (fieldsOrMessage: Fields | string, message?: string) => |
There was a problem hiding this comment.
Silent log drop when called with only an object
The emit helper has no else branch. When it is called as logger.info({ someField }) — an object with no message string — neither condition matches and the call is silently discarded. Pino (which this shim is replacing) would emit the entry with an empty msg field.
All current call-sites happen to pass a message, but the contract mismatch is a latent trap for any future caller.
| log[level]({ ...base, message: fieldsOrMessage }); | |
| } else if (message !== undefined) { | |
| log[level]({ ...base, ...fieldsOrMessage, message }); | |
| } | |
| } | |
| /** | |
| * Pino-compatible (obj, msg) or (msg) logging via evlog global `log`. | |
| */ | |
| export const logger = { | |
| error: (fieldsOrMessage: Fields | string, message?: string) => | |
| emit("error", fieldsOrMessage, message), | |
| info: (fieldsOrMessage: Fields | string, message?: string) => | |
| emit("info", fieldsOrMessage, message), | |
| warn: (fieldsOrMessage: Fields | string, message?: string) => | |
| function emit( | |
| level: "error" | "info" | "warn", | |
| fieldsOrMessage: Fields | string, | |
| message?: string | |
| ): void { | |
| if (typeof fieldsOrMessage === "string") { | |
| log[level]({ ...base, message: fieldsOrMessage }); | |
| } else if (message !== undefined) { | |
| log[level]({ ...base, ...fieldsOrMessage, message }); | |
| } else { | |
| // Object-only call (no message string) – emit as-is | |
| log[level]({ ...base, ...fieldsOrMessage }); | |
| } | |
| } |
| }); | ||
|
|
||
| initLogger({ | ||
| env: { service: "links" }, |
There was a problem hiding this comment.
Missing Axiom drain — logs stay local
api and basket both configure drain: createAxiomDrain() in their initLogger calls. links (and uptime — same pattern at apps/uptime/src/index.ts:9-11) omit it, so structured logs from these services will never reach Axiom.
| }); | |
| initLogger({ | |
| env: { service: "links" }, | |
| initLogger({ | |
| env: { service: "links" }, | |
| drain: createAxiomDrain(), | |
| }); |
Wire api and basket through createDrainPipeline, initLogger tail sampling, middleware enrich (UA, request size, trace context), and optional NDJSON to apps/*/.evlog/logs in development. Basket: structured errors in auth, geo, producer, and request validation wide events. Ignore **/.evlog/ at repo root. Biome: disable useHookAtTopLevel for evlog useLogger in api and basket.
Replace z.record output schemas with explicit Zod models for getAnalytics and getAnalyticsByReferrer so handlers match processFunnelAnalytics return types.
- Replace OpenTelemetry span helpers in @databuddy/rpc with evlog wide-event helpers (rpc-log-context.ts); remove @opentelemetry/api and @orpc/otel. - API: mergeWideEvent/captureError patterns, drop no-op record() wrapper, basket-style uncaught handlers, logging on MCP/health/insights/public routes. - Touch RPC routers and lockfile for consistency with the RPC logging changes.
…vent enricher Replace fragmented API key enricher with applyAuthWideEvent that resolves both session and API key in parallel. Strip duplicated auth fields from RPC enricher, remove redundant route fields from health/mcp/insights.
…ext output - Pre-fetch summary, top pages, errors, referrers for WoW comparison - Replace ToolLoopAgent with generateText + Output.object (non-deprecated) - Tighten prompts and expand insight type taxonomy
Description
Please include a summary of the change and which issue is fixed. Also include relevant motivation and context.
Checklist