Skip to content

Feature/phase3/monitoring logs#21

Merged
Buffden merged 3 commits into
mainfrom
feature/phase3/monitoring-logs
Mar 18, 2026
Merged

Feature/phase3/monitoring logs#21
Buffden merged 3 commits into
mainfrom
feature/phase3/monitoring-logs

Conversation

@Buffden

@Buffden Buffden commented Mar 17, 2026

Copy link
Copy Markdown
Owner

No description provided.

Buffden added 2 commits March 17, 2026 16:48
add request correlation + request/latency metrics filter
add explicit error counters in exception handler
configure actuator readiness/liveness groups and metrics exposure
enable JSON console logging configuration

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a Phase 3 observability baseline for the TinyURL Spring Boot service by enabling structured JSON logging with correlation IDs, adding Prometheus-ready metrics, hardening Actuator health grouping/exposure, and providing operational documentation for alerts and log aggregation.

Changes:

  • Add JSON console logging (Logstash encoder) and a request filter to propagate/log X-Correlation-Id.
  • Expose Prometheus/metrics endpoints and add custom request/error Micrometer metrics.
  • Add Phase 3 observability documentation: alert baselines and log aggregation/storage guidance.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tinyurl/src/main/resources/logback-spring.xml Adds JSON console logging with service field and MDC correlation_id.
tinyurl/src/main/resources/application.yaml Configures Actuator health groups and exposes metrics/prometheus endpoints; adds metrics tags/distributions.
tinyurl/src/main/java/com/tinyurl/observability/RequestObservabilityFilter.java Adds correlation-id propagation, request logging, and custom request metrics.
tinyurl/src/main/java/com/tinyurl/controller/GlobalExceptionHandler.java Adds an error counter metric emitted from exception handlers.
tinyurl/build.gradle.kts Adds Prometheus registry + logstash logback encoder dependencies.
docs/implementation/PHASE_3_OBSERVABILITY.md Links baseline reference docs for Phase 3.
docs/implementation/PHASE_3_LOG_STORAGE_MIGRATION_LOKI_PROMTAIL_GRAFANA.md Adds a Loki/Promtail/Grafana migration/runbook document.
docs/implementation/PHASE_3_LOG_AGGREGATION_BASELINE.md Adds minimal baseline requirements for structured log aggregation.
docs/implementation/PHASE_3_IMPLEMENTATION_EXPLANATION.md Documents what was implemented and suggested verification steps.
docs/implementation/PHASE_3_ALERT_BASELINE.md Adds starter alert definitions tied to the new metrics/endpoints.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to +23
show-components: always
show-details: always
web:
exposure:
include: health
include: health,metrics,prometheus
Comment on lines +55 to +58
String route = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
if (route == null || route.isBlank()) {
route = request.getRequestURI();
}
Comment on lines +51 to +89
filterChain.doFilter(request, response);
statusCode = response.getStatus();
} finally {
String method = request.getMethod();
String route = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
if (route == null || route.isBlank()) {
route = request.getRequestURI();
}

String status = Integer.toString(statusCode);
String statusClass = (statusCode / 100) + "xx";
String outcome = statusCode >= 400 ? "error" : "success";

double durationSeconds = (System.nanoTime() - startNanos) / 1_000_000_000.0;
Timer.builder("tinyurl.http.server.request.duration")
.tag("method", method)
.tag("route", route)
.tag("status", status)
.register(meterRegistry)
.record((long) (durationSeconds * 1_000_000_000L), java.util.concurrent.TimeUnit.NANOSECONDS);

Counter.builder("tinyurl.http.server.requests.total")
.tag("method", method)
.tag("route", route)
.tag("status_class", statusClass)
.tag("outcome", outcome)
.register(meterRegistry)
.increment();

log.info(
"http_request method={} route={} status={} duration_ms={} client_ip={} user_agent={}",
method,
route,
statusCode,
Math.round(durationSeconds * 1000),
request.getRemoteAddr(),
sanitize(request.getHeader("User-Agent"))
);

Comment on lines +64 to +66
double durationSeconds = (System.nanoTime() - startNanos) / 1_000_000_000.0;
Timer.builder("tinyurl.http.server.request.duration")
.tag("method", method)
Comment on lines 48 to +52
String code = ex.getMessage() == null ? "INVALID_REQUEST" : ex.getMessage();
HttpStatus status = "INVALID_EXPIRY".equals(code) || "INVALID_URL".equals(code)
? HttpStatus.BAD_REQUEST
: HttpStatus.INTERNAL_SERVER_ERROR;
incrementErrorMetric(status, code);
…r unmapped paths

- Fix duration precision with direct nanosecond computation instead of double conversion
- Ensure MDC cleanup runs even if metrics/logging fails (nested finally block)
- Normalize error codes to bounded set to prevent cardinality explosion
- Restrict health component details visibility to when_authorized (security)
- Restrict metrics/prometheus endpoints to dev profiles only (production uses application-prod.yaml)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Phase 3 “observability” capabilities to the TinyURL Spring Boot service by enabling structured JSON logging, correlation IDs, Prometheus/Micrometer metrics, and improved Actuator health grouping, along with rollout documentation.

Changes:

  • Enable JSON console logging (logstash encoder) and add a request filter to propagate/log X-Correlation-Id.
  • Expose and configure Actuator health groups + metrics/prometheus endpoints (with prod exposure restricted).
  • Add Micrometer counters/timers for request and error tracking, plus operational baselines/docs for alerts and log aggregation/storage.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tinyurl/src/main/resources/logback-spring.xml New Logback config to emit JSON logs and include correlation_id MDC field.
tinyurl/src/main/resources/application.yaml Configures health probes/groups and exposes metrics/prometheus endpoints by default; adds metrics tags and histograms.
tinyurl/src/main/resources/application-prod.yaml Restricts Actuator web exposure to health in production profile.
tinyurl/src/main/java/com/tinyurl/observability/RequestObservabilityFilter.java New filter for correlation ID propagation, request logging, and custom request metrics.
tinyurl/src/main/java/com/tinyurl/controller/GlobalExceptionHandler.java Adds an error metric counter incremented from exception handlers.
tinyurl/build.gradle.kts Adds Prometheus registry + logstash encoder dependency.
docs/implementation/PHASE_3_OBSERVABILITY.md Links additional Phase 3 baseline reference docs.
docs/implementation/PHASE_3_LOG_STORAGE_MIGRATION_LOKI_PROMTAIL_GRAFANA.md Adds a Loki/Promtail/Grafana migration plan and operational guidance.
docs/implementation/PHASE_3_LOG_AGGREGATION_BASELINE.md Defines required log fields, baseline pipeline, and alert/triage expectations.
docs/implementation/PHASE_3_IMPLEMENTATION_EXPLANATION.md Documents what was implemented and how to verify Phase 3 changes.
docs/implementation/PHASE_3_ALERT_BASELINE.md Adds starter alert definitions aligned to metrics/health endpoints.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +39 to +46
String correlationId = request.getHeader(CORRELATION_ID_HEADER);
if (correlationId == null || correlationId.isBlank()) {
correlationId = UUID.randomUUID().toString();
}

MDC.put(CORRELATION_ID_MDC_KEY, correlationId);
response.setHeader(CORRELATION_ID_HEADER, correlationId);

Comment on lines +66 to +79
Timer.builder("tinyurl.http.server.request.duration")
.tag("method", method)
.tag("route", route)
.tag("status", status)
.register(meterRegistry)
.record(durationNanos, java.util.concurrent.TimeUnit.NANOSECONDS);

Counter.builder("tinyurl.http.server.requests.total")
.tag("method", method)
.tag("route", route)
.tag("status_class", statusClass)
.tag("outcome", outcome)
.register(meterRegistry)
.increment();
if (value == null) {
return "unknown";
}
return value.replaceAll("[\r\n]", " ");
Comment thread tinyurl/build.gradle.kts
implementation("org.flywaydb:flyway-core")
implementation("org.flywaydb:flyway-database-postgresql")
implementation("io.micrometer:micrometer-registry-prometheus")
implementation("net.logstash.logback:logstash-logback-encoder:7.4")

1. Unit/integration tests:

- run tests for app context, service logic, and encoder tests
@Buffden Buffden merged commit 67577c4 into main Mar 18, 2026
7 checks passed
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.

2 participants