A CDN can expose hundreds of log fields, but more fields do not automatically create better observability. The useful set is the smallest schema that lets a team identify a request, understand its HTTP outcome, explain the CDN’s decision, measure where time was spent, and connect the event to other systems. Everything else should earn its storage, privacy, and query cost.
A field contract should be designed before dashboards. It defines names, types, units, allowed values, null behavior, and semantics. That contract prevents a “duration” field from meaning milliseconds in one provider and microseconds in another, or a “cache status” from combining hits, stale responses, and revalidations without distinction. Reliable analysis begins with reliable meaning.
1. Event time and request identity
Every record needs an event timestamp with an explicit timezone and precision. Teams should know whether it marks request arrival, response completion, or log emission. Request-start time is often best for aligning traffic, while response-completion time can be useful for end-to-end duration. If both are available, keep both and name them clearly.
A unique request ID is equally important. It should be stable enough to search across CDN logs, origin logs, traces, and support tickets. When a provider ID cannot be propagated to the origin, add or preserve a trace header at the edge. Also record a schema version and provider name so that parsers can handle changes deliberately rather than inferring format from the record shape.
2. Host, method, path, and route group
The raw HTTP method, authority or host, and path describe what the client requested. Query strings are more sensitive and high-cardinality, so many teams retain only approved parameters, a normalized representation, or a boolean indicating that a query was present. A route group such as /api/orders/:id is often more useful for dashboards than a raw path containing millions of identifiers.
Route normalization should be deterministic and owned by the application team. Generic regular expressions can accidentally combine distinct endpoints or expose identifiers. Store both the restricted raw value required for investigation and the normalized route required for aggregation, with separate access controls if necessary.
3. Protocol and connection context
HTTP version, transport protocol, TLS version, cipher family, connection reuse, and negotiated application protocol can explain failures that are invisible at the application layer. A problem limited to HTTP/3, a particular TLS version, or new connections may appear as a regional latency spike unless the log includes connection context.
Connection fields need careful interpretation because one transport connection can carry multiple requests. A per-request record may report attributes of a reused connection, not a new handshake. Document whether timing fields are zero, null, or omitted when no new DNS, TCP, or TLS operation occurred.
4. Status code and response classification
The client-facing status code is mandatory, but it should be accompanied by a result classification. A 502 generated by the CDN because the origin connection failed is operationally different from a 502 returned by the application. Fields such as edge result type, origin status, termination reason, and policy action help separate where the response was produced.
For metrics, group status codes into outcome classes that match service behavior rather than relying only on 2xx, 4xx, and 5xx. Some 404 responses are expected, some 429 responses indicate protective throttling, and some 3xx responses are part of normal routing. Service-level indicators should count only outcomes that represent user-visible failure for the specific route.
5. Cache status and cache key context
A cache result should distinguish at least hit, miss, bypass, expired or stale, revalidated, and error fallback where the provider exposes them. A single “cached: true” flag loses the operational difference between a fresh hit and a stale response served during origin trouble. Also retain object age, effective time to live, and whether the request was cacheable.
Cache-key context is valuable, but logging the full key can expose sensitive values. A safer design records a key version, a hash, selected variation dimensions, and the reason a request bypassed cache. Those fields let teams measure fragmentation and compare configuration changes without publishing every header or query component used in the key.
6. Timing fields with units
Total edge duration is useful but insufficient. When possible, separate queue time, cache lookup, origin connect, TLS setup, time to first byte, origin response, and response transfer. Providers use different boundaries, so field descriptions must say exactly when measurement starts and stops. Store durations as numeric values in one canonical unit, preferably with the unit encoded in the name or schema.
Percentiles should be calculated from appropriately filtered events. Mixing cache hits and origin misses can produce a number that describes neither path. Separate cache states, response sizes, status groups, regions, and route groups before concluding that an origin or CDN is slow. The origin latency troubleshooting guide shows a practical sequence.
7. Bytes and object characteristics
Request bytes, response header bytes, response body bytes, compressed bytes, and origin bytes support bandwidth analysis and cost attribution. They also help explain latency: a slow large transfer is different from a slow first byte. Record range-request behavior and content encoding because partial content, compression, and streaming can change how byte counts should be interpreted.
Content type, object extension, or a controlled asset class can make cache and performance reports understandable. Avoid deriving categories from raw paths at query time if the logic is important; enrich the record once with a versioned classifier so historical results remain reproducible.
8. Edge, origin, and routing dimensions
Point of presence, region, provider, distribution or service ID, selected origin, shield tier, and routing policy identify where the request traveled. These are essential in multi-region and multi-CDN systems. Keep stable identifiers in addition to display names, because human-readable labels can change.
Origin identity should be abstracted enough to survive infrastructure replacement. A logical pool such as catalog-primary-eu is more useful than a short-lived host. If the physical endpoint is needed for debugging, retain it in a restricted field while using the logical pool for metrics and ownership.
9. Client and geography fields
Country, region, network owner, device category, and user-agent family can reveal localized issues. They also increase privacy and cardinality risk. Prefer coarse geography where detailed location is not required, truncate or transform IP addresses, and avoid long-term retention of raw user-agent strings when a normalized family and major version are sufficient.
Client dimensions should never be assumed perfectly accurate. Proxies, VPNs, carrier networks, shared devices, and automated clients blur classification. Use these fields for operational segmentation, not as definitive identity.
10. Security and policy outcomes
Record the action, rule ID, policy family, and confidence or score only when they support an investigation or control. Do not place secrets, complete authentication tokens, or unnecessary cookie values into the log. A rule identifier is more durable than a copied rule description; the description can be joined from a controlled configuration inventory.
Security fields should be accessible to the teams that need them without making sensitive request data broadly searchable. Separate storage tiers or field-level controls can preserve operational value while reducing exposure.
Build a field contract, not a field dump
For every field, document purpose, source, type, unit, cardinality, sensitivity, retention, and an example. Mark whether it is required, optional, or provider-specific. Add automated tests that reject impossible values, unknown enums, timestamp drift, and silent type changes. Track null rate and distinct-value growth as data-quality metrics.
A strong starter schema often contains 25 to 40 well-defined fields rather than hundreds of loosely governed ones. It can expand when a real question requires more detail. This approach keeps ingestion predictable, dashboards consistent, and incident investigations trustworthy. The objective is not to preserve everything forever; it is to preserve the evidence needed to explain delivery behavior and make good operational decisions.
