# GraphQL-aware request logs in structured JSON

Every router request, logged with operation name, type, hash, and per-stage timing. Output to stdout for containers or to a file for high load. Custom fields from headers, request context, or expressions.

JSON output. No bespoke parsers. Ready for ELK, Splunk, or any SIEM.

## The problem

### HTTP logs do not understand GraphQL

Method and path are not enough when one URL handles every operation. Debugging, auditing, and compliance need richer context.

### Generic HTTP logs miss the operation

Standard request logs record method and path. They never know that one request was the Products query and another was the Checkout mutation.

### High-traffic logging needs files

stdout works in a container; it does not work when log volume exceeds what your runtime can stream. Production needs a file output path it can rotate.

### Compliance needs custom context

Security and compliance reviews ask for client identification, tenant context, and per-stage timing, fields that generic logs do not carry.

## Our solution

### Structured logs with the right fields

Default fields cover the request basics. Custom context fields add the GraphQL details that matter: operation, timing, errors. Custom expression and header fields attach the business context that matters to you.

### Per-request logging, end to end

1. Access logs are emitted by the router for every request.
2. Default fields cover the basics: hostname, pid, request_id, trace_id, status, method, path, query, ip (redacted), user_agent, config_version, latency, and log_type.
3. Custom context fields add GraphQL-aware data: operation_name, operation_type, operation_hash, per-stage timing (parsing, planning, normalization, validation), error codes, and error service names.
4. Custom fields are populated from request headers or template expressions, so you can attach tenant IDs, client identifiers, or any business context.
5. Output goes to stdout for container deployments, or to a file for high-load scenarios.
6. Every line is structured JSON, ready for ingestion by ELK, Splunk, or any aggregator.

## Before & After

| Before Cosmo | With Cosmo |
| --- | --- |
| HTTP access logs without GraphQL operation name | Structured JSON with operation name, duration, and status per request |
| High-traffic logging without a rotation-friendly sink | File output with configurable path and permissions |
| Compliance needs client or tenant context in every line | Custom fields from headers or router context expressions |
| Separate logging middleware in every subgraph | Router-level access logs for the full federated request |

## How access logs work in Cosmo Router

### Capture

The router records access events for every request. Default fields include trace_id, status, latency, method, path, query, user_agent, and config_version.

### Enrich

Custom context fields add GraphQL-aware data: operation_name, operation_type, operation_hash, and per-stage timing (parsing, planning, normalization, validation). Expression fields require Cosmo Router 0.186.0+.

### Output

Choose stdout for container deployments or a file for high-load scenarios. File output requires Cosmo Router 0.118.0+. Subgraph access logs require 0.146.0+.

### Ingest

Every line is structured JSON, ready for ELK, Splunk, a SIEM, or any log aggregator. No custom parsers required.

## Output, fields, and ingestion

### Output mode

stdout for containers and Kubernetes. File output for high-load production. File access requires Cosmo Router 0.118.0+.

### Custom fields

Pull values from request headers, context fields, or template expressions. Expression fields require Cosmo Router 0.186.0+.

### Subgraph logs

Subgraph access logs are emitted as their own stream and can carry their own custom fields. Requires Cosmo Router 0.146.0 or later.

### File permissions

File permission defaults to 0640. The mode is configurable per file output.

## Enable structured access logs

Turn on access logs in router YAML. Ship JSON lines to stdout or a file your log stack already ingests.
