Standard Log Format
May 28, 2021
We have all been there, debugging across different services, each with their own logging format. The additional overhead of querying and parsing each different format reduces our visibility and slows us down when finding the root cause.
Here is an example standard log format:
{"version": "1","level": 10,"timestamp": "2021-04-04T12:49:27.3831583+00:00","traceId": "924c1365-c014-4bd9-88f7-efe9a3d06242","spanId": "e5d222c5-49d5-4371-898f-61948e52779a","message": "Request failed POST /login","context": {"method": "POST","path": "/login"},"exception": {"type": "AuthenticationException","message": "Invalid credentials","stacktrace": "at SomeMethod in SomeClass:1:13 \n at SomeOtherMethod in SomeOtherClass:2:24","context": {"username": "teddy"}}}
version
to track changes to the formatlevel
is the indicate the severityexample scale
level ordinal debug 10 info 20 warn 30 error 40 fatal 50 Numeric type enables range query
SELECT * FROM logWHERE level >= 40
timestamp
for ordering eventstraceId
for correlating logs for a request across servicesThis is created once at the origin of the request and passed to downstream services
- e.g. generate the
traceId
when a user clicks a button and triggers a request on the UI
- e.g. generate the
Useful for getting a big picture across services
SELECT * FROM logWHERE traceId = '924c1365-c014-4bd9-88f7-efe9a3d06242'
spanId
for correlating logs for a request in the same service- Created at start of request to a service
- Useful for zoning on the logs of a single service
- Necessary if logs for all applications are delivered to the same sink
- e.g. a single request enqueues multiple jobs, all of which will have the same
traceId
- e.g. a single request enqueues multiple jobs, all of which will have the same
message
andcontext
is the message and extra context data attached to the log depending on languageexception
is a subset of the exception object- Only relevant for the
error
andfatal
log levels type
is the class or name of the error depending on languagemessage
andcontext
is the message and extra context data attached to the exceptionstacktrace
will be the stack trace specific to the language
- Only relevant for the
Examples
Microsoft.Extensions.Logging
Information
logger.LogInformation("message {param} {complexParam}", "something", new {One = 1,Two = 2});Expected log
{// ..."message": "message something { One: 1, Two: 2}","context": {"param": "something","complexParam": {"One": 1,"Two": 2}}}
Error
class AuthenticationException extends Exception {public AuthenticationException(string username) : base("Invalid credentials") {Data.add("username", username);}}var ex = new AuthenticationException("teddy");logger.LogError(ex, "message {param} {complexParam}", "something", new {One = 1,Two = 2});Expected log
{// ..."message": "message something { One: 1, Two: 2}","context": {"param": "something","complexParam": {"One": 1,"Two": 2}},"exception": {"type": "AuthenticationException","message": "Invalid credentials","context": {"username": "teddy"},"stacktrace": " at StandardLog.TestBench.AspNetCore.Controllers.WeatherForecastController.Post() in /home/tt/projects/standard-log/dotnet/StandardLog.TestBench.AspNetCore/Controllers/WeatherForecastController.cs:line 63\n at Microsoft.Extensions.Internal.ObjectMethodExecutor.\u003C\u003Ec__DisplayClass33_0.\u003CWrapVoidMethod\u003Eb__0(Object target, Object[] parameters)\n"}}