Skip to content

chore: concluir Sprint 2 — Observabilidade e Logs#5

Merged
gustavomarques00 merged 11 commits into
mainfrom
sprint/2-observabilidade-logs
Nov 20, 2025
Merged

chore: concluir Sprint 2 — Observabilidade e Logs#5
gustavomarques00 merged 11 commits into
mainfrom
sprint/2-observabilidade-logs

Conversation

@gustavomarques00
Copy link
Copy Markdown
Collaborator

@gustavomarques00 gustavomarques00 commented Nov 12, 2025

Encerramento técnico da Sprint 2, com logger unificado, tracing e integração OpenTelemetry.

  • Pino configurado com pretty/JSON mode
  • Plugins de observabilidade (logging, tracing, correlationId, errorHandler)
  • OpenTelemetry (NodeSDK + OTLP exporter)
  • Integração com Railway + CI/CD ativo

Note

Introduce unified logging/tracing (Pino + OpenTelemetry) across shared/core and add a new Next.js UI dashboard with tests and build/deploy configs.

  • Observability (Shared/Core)
    • packages/shared: Add logging.ts (Pino), errors.ts, tracing.ts, telemetry.ts; update index exports; mockable OpenAI client for tests; add OpenTelemetry deps.
    • packages/core: Add initCore() to initialize setupTelemetry("vibe-core"); adjust tests to mock telemetry/AI.
  • New UI Dashboard
    • packages/ui: Create Next.js app (Tailwind, Zustand) with dashboard pages/components (SummaryCard, PeriodSelector, PageLayout), services/schemas, tokens, tests; add Next/Tailwind/Vitest configs.
  • API/Tooling & Config
    • packages/api: Add vitest.config.ts with aliases.
    • Repo configs: update tsconfig.base.json paths/resolution, root tsconfig.json references; add turbo.json tasks; root vitest.config.ts.
    • CI/Deploy/Ops: add railway.json; enhance weekly report script/status mapping and generate reports/weekly-YYYY-MM-DD.md.
    • Lockfile/deps updated for OpenTelemetry, Pino, UI/testing stack.

Written by Cursor Bugbot for commit 1a0aac3. This will update automatically on new commits. Configure here.

Gustavo added 7 commits November 12, 2025 13:51
…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
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();
}
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web


export async function getHealthStatus(): Promise<HealthPayload> {
const tracer = trace.getTracer("vibe-api");
const span = tracer.startSpan("health:get-status");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

// Propaga contexto ativo
const ctx = trace.setSpan(context.active(), span);
req._otelContext = ctx;
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

const tracer = trace.getTracer("vibe-api");

app.addHook("onRequest", async (req: any) => {
const span = tracer.startSpan(`${req.method} ${req.url}`, undefined, ROOT_CONTEXT);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

name: 🌐 Deploy API to Railway
runs-on: ubuntu-latest
needs: [release]
if: github.ref == 'refs/heads/main' || startsWith(github.ref_name, 'sprint/')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

} finally {
span.end();
}
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

await app.register(correlationId);
await app.register(logging);
await app.register(tracing);
await app.register(telemetry); // 🔹 Spans automáticos por requisição
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web


async function buildServer() {
const app = Fastify({ logger: true });
export async function buildServer() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

await app.register(correlationId);
await app.register(logging);
await app.register(tracing);
await app.register(telemetry); // 🔹 Spans automáticos por requisição
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

parseOptions: {
httpOnly: true,
sameSite: "strict"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

@gustavomarques00 gustavomarques00 merged commit 309eef5 into main Nov 20, 2025
14 checks passed
@gustavomarques00 gustavomarques00 deleted the sprint/2-observabilidade-logs branch November 20, 2025 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant