
A customer reports that an order failed yesterday afternoon.
An engineer finds the corresponding application error:
Unhandled exception while processing request.
The timestamp is there, but little else is useful. The log does not identify the operation, application version, customer workflow, downstream service or request that triggered the exception. By the time engineering begins investigating, the application is behaving normally again.
The team now has to reconstruct yesterday's production state from fragments.
Was there a database problem? Did the payment provider fail? Was the error introduced by that morning's deployment? Did one particular request cause it, or were dozens of customers affected?
The application produced a log.
It did not produce enough information to maintain the application efficiently.
That distinction matters because logging is sometimes treated as an operational checkbox: errors are written somewhere, therefore logging is “done.” Good logging has a more practical purpose.
It should reduce the amount of uncertainty an engineer has to remove before they can understand and correct a production problem.
AWS describes application logs as a historical record that can support troubleshooting, performance analysis and security investigation, while also noting that application owners should capture enough detail to analyse and resolve problems. AWS: Logging and Monitoring for Application Owners
For Levelworks, that connects logging directly to Observable and Explainable & Debuggable App Health. Better logs make application behaviour visible, but more importantly, they leave enough evidence for someone to understand that behaviour later.
One of the biggest maintenance costs around production defects is not fixing the code.
It is figuring out what actually happened.
A bug reported in development may be relatively easy to reproduce because engineers control the environment, input data and application version. Production incidents are different.
A failure may depend on:
If logs preserve enough of that context, engineers can investigate the actual event.
Without it, they often have to recreate conditions they may never be able to reproduce perfectly.
Compare:
ERROR: Failed to process invoice
with:
level=ERROR
service=billing
operation=generate_invoice
invoice_id=inv_48291
tenant_id=t_184
app_version=7.3.2
error_code=DB_TIMEOUT
dependency=primary-db
duration_ms=5124
trace_id=8f72...
The second log still does not provide the diagnosis automatically.
It narrows the search dramatically.
That is what good logging should do: shorten the distance between “something failed” and “we know where to investigate.”
[Internal Link: “How to Find the Root Cause of Application Errors Faster”]
Logging quality is not only about what information you record. Format matters too.
Consider a production environment where each developer writes messages differently:
User login failed for account 392
AUTH_ERROR - login problem: user=392
Could not authenticate [392]
A human can recognise that these messages are related.
Software has a harder time treating them consistently.
Structured logging turns important values into defined fields rather than burying them inside free-form text.
Google Cloud distinguishes structured logs, such as JSON objects with named fields, from unstructured text logs. Structured fields can be queried and indexed directly, making them substantially easier to filter and analyse. Google Cloud: Structured Logging
A useful authentication record might contain:
{
"severity": "WARN",
"event": "authentication_failed",
"service": "identity",
"reason": "expired_token",
"app_version": "4.8.1",
"trace_id": "..."
}
Now engineers can ask precise questions:
Those are maintenance questions, not logging questions.
Structure simply makes the logs capable of answering them.
A useful log entry needs more than an error message.
AWS recommends thinking in terms of the when, where, who, what and which of an event, with the exact attributes depending on the application's architecture and requirements. AWS: Application Log Event Attributes
For many production applications, useful context includes some combination of:
Context
Why it helps maintenance
Timestamp
Establishes when behaviour occurred and allows correlation with releases or other events
Service/component
Identifies where the event originated
Operation/event name
Makes similar events searchable
Environment
Distinguishes production from staging or other environments
Application version
Helps connect regressions with releases
Request/trace ID
Connects related activity across services
Error code/category
Allows failures to be grouped and trended
Dependency
Identifies external or internal systems involved
Duration
Helps investigate slow operations
Relevant entity ID
Allows investigation of a transaction without logging sensitive content
Not every entry needs every field.
The useful test is whether the context gives an engineer enough information to reconstruct the important parts of the event.
Logging becomes harder as applications become distributed.
A single checkout request might pass through an API gateway, authentication service, order service, inventory service, payment provider and message queue.
Each component may write perfectly good logs.
The maintenance problem is connecting them.
Suppose the order service records:
Payment request failed
and the payment service records:
Provider timeout
Without shared context, an engineer may have to correlate the two using timestamps and educated guesses.
A request or trace identifier solves much of that problem.
AWS recommends generating correlation IDs and passing them through dependent services so logs from the same request can be filtered together. AWS: Logging for Application Performance
OpenTelemetry goes further by allowing logs to contain the same trace and span identifiers used by distributed traces. That creates a direct connection between detailed log events and the request journey that produced them. OpenTelemetry Logging Specification
This is particularly valuable during maintenance because a problem that appears in one component may have originated somewhere else entirely.
[Internal Link: “Logs, Metrics and Traces: The Foundations of Application Observability”]
Better logging does not mean logging more.
A common response to difficult troubleshooting is to increase log volume dramatically.
Soon the application is recording every function call, successful request and internal object state. Storage costs rise, searches become slower and useful events disappear inside millions of routine entries.
AWS explicitly warns against excessive logging because it can increase processing and storage costs, affect performance and make important events harder to identify. AWS: Logging Best Practices
A more maintainable approach is to log meaningful events and boundaries.
Those often include:
The question should be:
What event would future maintainers wish they could see if this workflow failed?
That produces better logs than instrumenting every possible line of code.
Consider an application producing these errors:
Could not reach payment provider
Gateway timeout
Payment API error
Stripe connection failed
Third-party payment request timed out
Those may all describe the same underlying type of failure.
If the wording varies, counting and comparing them becomes difficult.
A better logging design gives recurring failure types stable identifiers:
error_category=DEPENDENCY_TIMEOUT
dependency=payment_provider
The human-readable message can remain descriptive, but the structured category makes the event measurable.
This has an important maintenance benefit.
A single dependency timeout may need no engineering work.
A pattern showing the same timeout increasing steadily for three months could reveal a much larger issue.
Consistent event taxonomy turns individual logs into maintenance history.
Teams can ask:
Logging then becomes useful for deciding what needs fixing permanently, rather than merely investigating today's incident.
Some of the most useful logging questions involve change.
Did this error exist before yesterday's deployment?
Does it affect version 6.4 but not 6.3?
Did one configuration rollout create a new failure pattern?
If logs contain deployment or version context, these questions become much easier to answer.
Imagine error rate increases sharply after a new release.
Without application-version information, engineers may infer that the deployment is responsible because the timing matches.
With version information, they can compare failures directly across the old and new versions, which is particularly helpful during gradual or canary rollouts where multiple versions may be operating simultaneously.
This strengthens Seamlessly Updatable as well as Observable.
A release process is easier to maintain when production behaviour can be connected back to the software version that produced it.
Integrations are a frequent source of difficult maintenance because part of the behaviour occurs outside your system.
Suppose a customer says an order was not sent to a logistics provider.
Useful logs should help answer:
Without this evidence, teams often have to contact the provider before they even know whether the request left their own application.
Good integration logging establishes the boundary between what your application knows and what the external system did.
This supports the Integrable dimension of App Health because maintaining an integration is much easier when changes and failures can be inspected from your side.
Logs also play a quieter role in maintainability.
They capture evidence about how the application behaves after the people who built a feature have forgotten the implementation details—or left the organisation entirely.
Suppose an experienced engineer knows that a particular warning is harmless unless it appears alongside another error.
That knowledge is useful, but fragile.
A stronger logging model captures meaningful event categories and consistent context so another engineer does not need the original author's memory simply to interpret normal production behaviour.
Logging therefore complements documentation.
Documentation explains how the system is intended to work.
Logs show what it actually did.
When the two are strong, a new maintainer can understand both the design and its runtime behaviour.
This connection is why logging can strengthen Well Documented and Supported, even though the log stream itself is not documentation.
[Internal Link: “Why Good Documentation Makes an App Cheaper to Maintain”]
Customer support often sees application problems before engineering does.
Poor logging forces support to collect technical information indirectly:
Those details remain useful, but stronger logging allows support and engineering to connect a reported problem to a concrete production event.
A support ticket containing an order ID, timestamp or transaction reference can lead to the relevant application record, trace or error event.
That reduces the repeated conversation where engineering responds:
“Can you ask the customer to try it again?”
For intermittent failures, the original event may be the best evidence the team will ever have.
Maintaining that evidence is part of maintaining the application.
Good logging should make important security events visible without turning the log store into a collection of sensitive data.
The OWASP Logging Cheat Sheet recommends application-level logging for relevant security events and stresses consistent event classification and protection of collected log data. It also notes that application logs can provide insight unavailable from infrastructure or web-server logs alone.
At the same time, logs should not casually contain:
AWS similarly recommends masking, sanitising, hashing or excluding sensitive fields rather than recording them directly.
This matters to maintainability because developers sometimes respond to difficult debugging by logging entire request or response objects.
That may solve today's investigation while creating tomorrow's security or compliance problem.
Useful logging captures diagnostic context, not every piece of available data.
Logging code can fail too.
Fields change names. An application refactor removes an important event. Timestamps become inconsistent, a deployment disables a log level, or a new service forgets to propagate the request identifier.
OWASP recommends testing logging mechanisms as part of application testing and security verification, including checking event classification, field consistency, logging failures and unwanted side effects.
That means production logging should be treated as part of the application's behaviour rather than an afterthought.
When engineers modify an important workflow, ask:
Do the logs still provide enough evidence to diagnose it?
When a new external service is introduced:
Can requests to that service be correlated with the user operation that triggered them?
When an error is fixed:
Would we recognise immediately if it started recurring?
These are maintenance questions worth including in review and testing.
Keeping every production log forever is rarely practical.
Keeping them for too little time creates another problem.
Suppose customers receive monthly statements and a defect is discovered only when one statement is wrong. If detailed operational logs are deleted after seven days, the evidence required to investigate the original processing event may no longer exist.
Retention should therefore reflect:
NIST's longstanding Guide to Computer Security Log Management treats log management as an ongoing organisational process rather than simply generating log files, including the infrastructure and procedures needed to maintain useful log data.
The exact retention period is application-specific.
The principle is not: keep more logs.
It is: retain useful evidence for as long as the organisation reasonably needs it.
Instead of evaluating logging by volume or tool coverage, choose an important workflow and imagine that it failed yesterday.
Then ask:
Question
What good logging should provide
Which operation failed?
Consistent event/operation name
When did it happen?
Reliable timestamp
Where did it fail?
Service or component
Which software produced it?
Application/release version
Which transaction was affected?
Safe business or entity identifier
What kind of failure occurred?
Structured error category
Which dependency was involved?
Dependency name and result
Can related events be connected?
Request, correlation or trace ID
Was this isolated or recurring?
Searchable structured fields
Can another engineer understand it?
Consistent terminology and useful context
If several of those questions cannot be answered without reproducing the bug, logging is probably making maintenance harder than it needs to be.
Better logging does not prevent defects.
It changes how expensive they are to understand.
A maintainable application leaves behind enough evidence that engineers can investigate production behaviour without depending entirely on reproduction, memory or guesswork.
That means using consistent structured events, preserving relevant context, correlating activity across services, connecting behaviour to releases and logging enough information around important workflows and integrations to reconstruct what happened.
At Levelworks, this is why Observable and Explainable & Debuggable are distinct but closely related App Health Aspects.
The first makes the application's behaviour visible.
The second determines whether that visibility is useful enough to explain what went wrong.
Good logging connects the two.
The objective is not to create more data.
It is to make the next maintenance problem easier to understand than the last one.