Opens in a new tab
Observability · Lesson 4 of 12

Useful logs keep one job in view

In brief

Three errors at the same time may belong to three different jobs. Stable fields let you follow the right export without collecting its private contents.

4 min read

IntermediateLessonAbout reading levels
Is this the right starting point?
Before you read
Know the basic purpose of logs and be able to write or adapt a simple field-based search over synthetic events.
What you will take away
Design structured log fields and a query that follow one operation across attempts while preserving time, scope and correlation gaps without logging sensitive contents.
Sources
A blue thread passes through three pale paper fragments on a cream tabletop; a magnifying glass rests over the rightmost piece among loose paper and terracotta fragments.
On this page5 sections

Three errors appear at 14:04. Only one belongs to the customer's missing export. Sorting the lines brings them together on the screen, but it does not bring you any closer to knowing which one matters.

The fictional Dispatch service handles incoming requests and background report jobs. Its message 14:04 error request failed leaves out the connections an investigation needs: which job, which step, where it happened and whether another attempt later succeeded. Give those details stable names, and the search becomes much less of a guessing game. None requires putting the customer's document in the log.

Follow the job, not the neighboring lines

Here is the same kind of failure as a record with named fields, giving it structure rather than leaving one undifferentiated message:

{
  "timestamp": "2026-01-01T14:04:00Z",
  "event": "export_write_failed",
  "service": "dispatch-worker",
  "region": "A",
  "job_id": "example-job-7",
  "trace_id": "example-trace-7",
  "error_type": "storage_timeout",
  "attempt": 2
}

The identifiers are illustrative, not a real trace payload. export_write_failed names the step. Service and region tell us where it happened. Searching for example-job-7 follows this export; grouping by storage_timeout finds similar failures across jobs. We can ask both questions without learning a new English sentence for every event.

Look closely at attempt: 2. It means a second attempt at the work, not necessarily a second customer's failed export. Another attempt might succeed. Record completion separately, so the final error line is not mistaken for the ending of the job.

The failure happened at 14:04. The record arrived at 14:09.

Suppose the worker emits its failure while the logging connection is down. Five minutes later, the collection system receives the record. The worker's event time and the collector's receipt time describe different things. Neither should silently replace the other.

A timestamp needs a timezone and an understood source clock. Preserve both times where available, under names that distinguish them. Receipt time can explain a sudden burst of records; event time can help reconstruct the work. The five-minute gap is not evidence that the failed write spent five minutes executing.

Remove one identifier and watch what becomes uncertain

Make three synthetic events carrying the same job ID: acceptance at 14:03, worker start at 14:03:02 and write failure at 14:04. Slip an unrelated successful job between them. Searching for the first identifier should return its three events without the unrelated success.

Now remove the ID from the worker-start event. The query still connects acceptance and failure, but not that particular start. Its nearby timestamp is a clue, not enough to restore the missing connection. The exercise has identified a field the instrumentation needs to carry.

Add a completion event with the original job ID. We can now support a sequence of acceptance, a failed attempt and eventual completion. The unidentified start remains unresolved. Some of the story can be established while one part stays unknown; the log need not pretend otherwise.

A dashboard link should take the operation, region and interval into the log search with you. A global search could find a similar timeout in another environment and quietly answer a different question. The next screen is useful when it continues the investigation you were already doing.

A job ID usually helps more than a copy of the export contents. Keep customer documents, authorization headers and secret tokens out of logs. Identifiers need suitable access controls and retention too: they can reveal sensitive information. Removing one field does not automatically make a record anonymous.

Give another reader the schema, sample events and query. Can they follow the job to its recorded failure and completion without a private lesson in your log-message grammar? Their answer tells you whether the fields are doing the work intended.

There is one final boundary to cross. A log reports what the code emitted; it does not by itself establish that the customer can download the report. Check that outcome where the customer uses it. Now you have a route to that check, rather than three errors sitting next to one another.

Sources

The OpenTelemetry logs data model documents timestamps and trace correlation. The events here are original synthetic examples.

Sources & context

Sources linked in this article. Read alongside the author’s analysis; a citation does not independently verify a publisher’s claims.

Report an error or outdated detail

Keep reading

Where to go next