Skip to content

Chore: Enable Nullable, Analyzers, and Structured Observability #10

@webreidi

Description

@webreidi

Goal

Raise code quality bar and improve runtime diagnosability by enabling nullable reference types, adding analyzers, enforcing warnings-as-errors, and instrumenting structured logging + tracing for critical game flows.

Motivation

  • Earlier detection of null bugs & API misuse
  • Consistent style / code hygiene reduces PR review friction
  • Observability (logs + traces) accelerates debugging of gameplay issues, latency, hot paths

Quality Gate Enhancements

  1. Enable <Nullable>enable</Nullable> in every csproj
  2. Add <TreatWarningsAsErrors>true</TreatWarningsAsErrors> (optionally configurable via Directory.Build.props)
  3. Add Microsoft.CodeAnalysis.NetAnalyzers (latest stable) with rule level medium severity; include editorconfig baseline if noise high
  4. Add StyleCop.Analyzers (optional) or rely on .editorconfig for minimal style safety
  5. Configure CI (GitHub Actions future) to run dotnet build + filtered tests

Observability Additions

  • Structured logging (Microsoft.Extensions.Logging) in GameService: events for GameStarted, GuessSubmitted, GameCompleted with contextual properties (GameId, AttemptIndex, WordLength, Result)
  • Exception logging with reduced noise (log domain validation at Information or Debug, unexpected at Error)
  • OpenTelemetry instrumentation (if Aspire not already auto-wiring):
    • Add ActivitySource Codele.Gameplay
    • Span per guess evaluation with attributes: codele.game.id, codele.guess.length, codele.guess.result (win/continue)
  • Optional metrics (if instrumentation libs added later): counter codele.guesses.total, histogram codele.game.duration.seconds

Implementation Plan

  1. Create/modify Directory.Build.props to centrally enable Nullable + WarningsAsErrors; reference analyzers package
  2. Add .editorconfig with key rules (nullable, IDE, formatting)
  3. Update each project csproj to remove redundant settings; add analyzers package if not global
  4. Introduce Instrumentation static class exposing ActivitySource
  5. Inject ActivitySource into services (or use static) & wrap guess evaluation in activity
  6. Add structured logging statements (Ensure no PII / target word withheld until game completes; only log masked hash before completion)
  7. Add unit test asserting logger called for GameCompleted (can use a fake logger) – lightweight
  8. Update README with new quality gates + how to suppress intentionally (pragma + justification)

Acceptance Criteria

  • Build fails on new nullable warnings introduced intentionally
  • Activity exported (can be verified via debug logging or future OTLP exporter)
  • Logging shows contextual properties per guess in local run
  • README documents process

Out of Scope

  • Full metrics pipeline export
  • External log shipping config

Risk & Mitigation

  • Analyzer noise -> Keep initial rules moderate; create baseline suppression file if needed

Definition of Done

Merged PR with green tests, updated docs, analyzers active (visible in IDE), and logged gameplay events.

Estimated Effort

Small-Medium (3-4h depending on analyzer tuning).

Depends on: Issue #8 (for domain service centralization makes instrumentation cleaner).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions