Skip to content

chore: structured logging for services and access guards (part 2 of 2)#313

Draft
NoahFreelove wants to merge 15 commits intomasterfrom
mark-logs-part-2
Draft

chore: structured logging for services and access guards (part 2 of 2)#313
NoahFreelove wants to merge 15 commits intomasterfrom
mark-logs-part-2

Conversation

@NoahFreelove
Copy link
Copy Markdown
Contributor

PR Description

Stacked PR 2 of 2. Builds on #312 (mark-logs-part-1). Do not merge before part 1.

This PR applies the logging infrastructure landed in part 1 to the rest of the app: service layer, access-control guards, messaging, and the sanitize helper's wave-2 call sites.

Overview:

  • Adds structured logging to: attempt.service, attempt-submission.service, lti-sync-scheduler, lti-grade-sync.service, question-response.service, openai-llm.service, report.service, api.service (gateway), both messaging.services
  • Adds structured logging to access-control guards: assignment.access.control.guard, assignment.attempt.access.control.guard, assignment.question.access.control.guard, chat.access.control.guard, admin.guard, roles.global.guard, files/guards/auth.guard
  • Applies the logger/sanitize.ts helper (from part 1) to api.service and attempt.service call sites
  • Extracts a stream-error formatter to avoid a nested-ternary lint violation
  • Winston-mock providers + updated assertions in messaging.service.spec (×2) and attempt.service.spec

Type of Issue:

  • Feature (feat)
  • Bug Fix (bug)
  • Chore (chore)
  • Documentation Update (doc)

Change Type:

  • Major
  • Minor: Large diff but mostly repetitive — same pattern from part 1 applied to many files.
  • Patch

Test Coverage

  • Unit tests updated (winston mocks for affected service specs)
  • Manual verification done (pre-commit yarn lint + yarn build + yarn test:staged all green)

Impact / Risk

  • No behavior change except added logging.
  • Guards now emit info/warn logs on allow/deny — verify this is fine for log-volume dashboards.
  • messaging.service error-callback wrapping (both apps) — now wraps user-supplied error callbacks so the service can log before delegating.

Rollback

  • Revert this PR only; part 1 can stay. The infra is harmless on its own.

Reviewer Focus

  • Pick one service (e.g. report.service.ts) and one guard (e.g. assignment.access.control.guard.ts) — the rest follow the same pattern.
  • apps/api-gateway/src/messaging/messaging.service.ts — error-callback wrapping is the only non-mechanical change.
  • The updated spec assertions in messaging.service.spec use expect.any(Function) where the wrapped callback is now a new function identity.

Adds apps/{api,api-gateway}/src/logger/sanitize.ts and applies it to the
web file-upload controller. Wave-2 callers (attempt.service, api.service)
will adopt the helper in a follow-up PR.
Matches the wave-1 middleware change that now routes 4xx responses to
warn and 5xx to error.
@NoahFreelove NoahFreelove marked this pull request as draft April 18, 2026 00:36
…field

NestJS's Logger treats the second arg to .error/.warn as a stack-trace
string. Passing a metadata object produced "stack":[{...}] in the JSON
log output, which breaks log-ingest pipelines that expect stack to be
a string. Inline the target/duration info into the message instead.
The try {} block wrapping bucket resolution had an empty body, so the
catch was unreachable and the user-controlled uploadType would have
been logged without sanitization if it ever fired. Drop the dead
block entirely.
…vents

PrismaService used @nestjs/common's Logger, whose
error(msg, stack?, context?) signature made nest-winston emit
"stack":[null] on every prisma_error log line (observed in staging).
Switch to the winston-provider injection pattern used elsewhere in the
logging work, and convert .log() -> .info() and positional-error calls
into structured metadata objects.

Specs that instantiated PrismaService directly (database, health, admin)
now provide a mock WINSTON_MODULE_PROVIDER; database.module.spec wraps
it in a @global() MockWinstonModule so DatabaseModule's @global provider
can resolve it.
Added in 72c6dd6 alongside the api-side helper but never imported
anywhere in the gateway. The api gateway's logger.middleware still
logs user-controlled fields unsanitized; plumbing this helper into
the gateway is a follow-up, not this PR's scope.
- Extract getGithubConfig helper in report.service.ts, replacing 5
  copy-paste "config or token missing" log+throw blocks.
- Mirror formatStreamError helper from api-gateway into api's
  messaging.service.ts, removing two nested-ternary blocks.
- Hoist duplicate safeMethod/safeEndpoint/requestId in api-gateway
  api.service.ts error handler (also drops non-null assertion by
  using forwardingDetails.endpoint directly, fixing a new lint warning).
- Cache Date.now()-requestStart in lti-grade-sync.service.ts to avoid
  double-computing the duration.

No behavior changes; 626 api tests + 53 api-gateway specs still pass.
Part-1 removed this file as dead code. Part-2 introduces genuine call
sites for it in apps/api-gateway/src/api/api.service.ts when sanitizing
method/endpoint/request-id/downstream_data before logging.
Base automatically changed from mark-logs-part-1 to master April 20, 2026 17:54
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