Something went wrong is a log message, but it leaves the next person with almost all the original work. Which operation failed? Was it a timeout or a rejected request? Can the event be connected to what the user saw?

A useful event gives the investigation a place to start. For an external API call, that usually means the operation, a correlation identifier, elapsed time, outcome and an error category.

1
2
3
4
5
6
7
8
9
try:
    result = evaluate_shipment(payload)
except TimeoutError:
    logger.warning(
        "shipment evaluation timed out request_id=%s provider=%s",
        request_id,
        provider_name,
    )
    raise

The code is illustrative. In a real service, structured fields are easier to query than values embedded in a sentence, if the logging setup supports them.

Give levels a consistent meaning

If every successful request produces a warning, a warning stops being useful. Decide which events represent normal operation, recoverable trouble and a failed operation that needs attention. Keep that meaning consistent across the service.

An exception stack is useful where the exception is handled and the context is known. Logging the same exception at every layer can turn one failure into a wall of repeated traces.

Leave out what the investigation does not need

Full request bodies are an expensive default. They can include tokens, personal information and long documents. An identifier or a count may answer the debugging question without recording the underlying content.

Similarly, a success event should not claim more than happened. “Request accepted” and “job completed” are different events if a worker performs the job later.

Before adding a log line, imagine the query that would find it. If the line cannot help connect a symptom to an operation, it may belong in a temporary local diagnostic rather than the permanent event stream.

Reference: Python logging HOWTO.