chore: concluir Sprint 2 — Observabilidade e Logs#5
Conversation
…ing distribuído - Implementação completa do logger unificado com Pino (PrettyPrint / JSON) - Contexto de logs por pacote (core, api, shared) - Integração OpenTelemetry (setupTelemetry + OTLPTraceExporter) - Plugins Fastify: correlationId, logging, tracing, telemetry, errorHandler - Spans automáticos e helper req.withSpan() - Integração Railway CI/CD e deploy automatizado - Rotas observáveis: /v1/health, /v1/tasks, /v1/review - Atualização dos workflows CI + release + sync Notion - Estrutura final validada para observabilidade e infraestrutura
…odeReviewInput
- focus agora explicitamente tipado como ('bugs'|'style'|'architecture'|'performance'|'security')[]
- build da API finalizado com sucesso
- Logger unificado com Pino (pretty em dev / JSON em prod) - OpenTelemetry integrado com setupTelemetry - Plugins Fastify: correlationId, logging, tracing e errorHandler - Server validado localmente (localhost:3333) - Build e execução estáveis no monorepo
There was a problem hiding this comment.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| span.setStatus({ code: 2, message: err.message }); | ||
| span.end(); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Bug: Telemetry spans closed prematurely on error
The onError hook calls span.end(), which closes the trace span before the onResponse hook executes. Since onResponse runs after onError, it attempts to add the final HTTP status code to an already ended span, resulting in missing status codes in traces for failed requests. onError should only record the exception.
|
|
||
| export async function getHealthStatus(): Promise<HealthPayload> { | ||
| const tracer = trace.getTracer("vibe-api"); | ||
| const span = tracer.startSpan("health:get-status"); |
There was a problem hiding this comment.
Bug: Detached trace span in health service
The service creates a new span using tracer.startSpan without passing the active request context. Since the telemetry plugin stores the context in req._otelContext rather than activating it globally, this span becomes a root span, disconnected from the incoming request trace hierarchy.
| // Propaga contexto ativo | ||
| const ctx = trace.setSpan(context.active(), span); | ||
| req._otelContext = ctx; | ||
| }); |
There was a problem hiding this comment.
Bug: Telemetry plugin fails to activate trace context
The plugin creates a span and stores it in req._otelContext but never makes it active via context.with(). Consequently, context.active() remains empty during the request, causing the logger and downstream services (like healthService) to create detached spans or miss trace IDs entirely.
| const tracer = trace.getTracer("vibe-api"); | ||
|
|
||
| app.addHook("onRequest", async (req: any) => { | ||
| const span = tracer.startSpan(`${req.method} ${req.url}`, undefined, ROOT_CONTEXT); |
There was a problem hiding this comment.
Bug: Telemetry plugin ignores incoming trace headers
The onRequest hook starts a new span using ROOT_CONTEXT, which explicitly ignores any current active context. This breaks distributed tracing because valid traceparent headers sent by upstream services are discarded instead of being used as the parent span.
| name: 🌐 Deploy API to Railway | ||
| runs-on: ubuntu-latest | ||
| needs: [release] | ||
| if: github.ref == 'refs/heads/main' || startsWith(github.ref_name, 'sprint/') |
There was a problem hiding this comment.
Bug: Deployment skipped on sprint branches due to dependency
The deploy job depends on the release job, but release is restricted to run only on main. This causes deployments for sprint/ branches (which are configured to run in deploy) to be skipped entirely because their dependency condition is not met.
| } finally { | ||
| span.end(); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Bug: Telemetry context not propagated in withSpan helper
The withSpan helper creates a new span but does not make it active using context.with(). Consequently, any operations or traces generated within the callback fn will not be parented to this new span, resulting in disjointed or flattened trace hierarchies.
| await app.register(correlationId); | ||
| await app.register(logging); | ||
| await app.register(tracing); | ||
| await app.register(telemetry); // 🔹 Spans automáticos por requisição |
There was a problem hiding this comment.
Bug: Conflicting plugins overwriting req.withSpan helper
Both tracing and telemetry plugins attempt to define req.withSpan. Since telemetry is registered last, it overwrites the implementation from tracing, rendering the tracing plugin ineffective and causing inconsistent behavior with expected span naming or logic.
|
|
||
| async function buildServer() { | ||
| const app = Fastify({ logger: true }); | ||
| export async function buildServer() { |
There was a problem hiding this comment.
Bug: Environment variables loaded after static imports
dotenv.config() is called after static imports are evaluated. Modules that read process.env at the top level (like lib/supabase.ts initializing the client) will receive undefined values and crash on startup, as the environment variables haven't been loaded yet.
| await app.register(correlationId); | ||
| await app.register(logging); | ||
| await app.register(tracing); | ||
| await app.register(telemetry); // 🔹 Spans automáticos por requisição |
There was a problem hiding this comment.
Bug: Logger registered before telemetry middleware
The logging plugin is registered before telemetry. Since Fastify hooks execute in registration order, the logger's onRequest hook runs before the telemetry plugin starts the trace span, causing logs to be emitted without traceId or spanId correlation fields.
| parseOptions: { | ||
| httpOnly: true, | ||
| sameSite: "strict" | ||
| } |
There was a problem hiding this comment.
Bug: Strict SameSite cookie policy breaks cross-domain auth
Setting sameSite: "strict" prevents session cookies from being sent in cross-origin requests. Since the UI (Vercel) and API (Railway) reside on different domains, the browser will block the cookie, causing authentication to fail. Use None (with Secure) or Lax.
Encerramento técnico da Sprint 2, com logger unificado, tracing e integração OpenTelemetry.
Note
Introduce unified logging/tracing (Pino + OpenTelemetry) across shared/core and add a new Next.js UI dashboard with tests and build/deploy configs.
packages/shared: Addlogging.ts(Pino),errors.ts,tracing.ts,telemetry.ts; updateindexexports; mockable OpenAI client for tests; add OpenTelemetry deps.packages/core: AddinitCore()to initializesetupTelemetry("vibe-core"); adjust tests to mock telemetry/AI.packages/ui: Create Next.js app (Tailwind, Zustand) with dashboard pages/components (SummaryCard,PeriodSelector,PageLayout), services/schemas, tokens, tests; add Next/Tailwind/Vitest configs.packages/api: Addvitest.config.tswith aliases.tsconfig.base.jsonpaths/resolution, roottsconfig.jsonreferences; addturbo.jsontasks; rootvitest.config.ts.railway.json; enhance weekly report script/status mapping and generatereports/weekly-YYYY-MM-DD.md.Written by Cursor Bugbot for commit 1a0aac3. This will update automatically on new commits. Configure here.