-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Currently, the console logger in CreateDefaultBuilder() defaults to a multiline human-readable output. This doesn’t work well in container environments where folks use tools like fluentd or Azure Monitor to collect those logs.
Some limitations of the current formatter:
- Individual log are split across multiple log entries
- Structure is no longer preserved
- Stack traces are torn across multiple lines
- Logs have color codes embedded in them
What I would like to do is to switch the default ConsoleLoggerFormatter to output structured JSON logs instead of our current format when running in a container.
Old output:
warn: Microsoft.AspNetCore.Server.HttpSys.MessagePump[37]
Overriding address(es) ''. Binding to endpoints added to UrlPrefixes instead.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:7000/
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:7001/
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:7002/
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\Users\shirh\source\temp\web50
New output:
{"EventId":37,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.Server.HttpSys.MessagePump","Message":"Overriding address(es) \u0027\u0027. Binding to endpoints added to UrlPrefixes instead.","State":{"Message":"Overriding address(es) \u0027\u0027. Binding to endpoints added to UrlPrefixes instead.","{OriginalFormat}":"Overriding address(es) \u0027\u0027. Binding to endpoints added to UrlPrefixes instead."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://localhost:7000/","State":{"Message":"Now listening on: http://localhost:7000/","address":"http://localhost:7000/","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://localhost:7001/","State":{"Message":"Now listening on: http://localhost:7001/","address":"http://localhost:7001/","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://localhost:7002/","State":{"Message":"Now listening on: http://localhost:7002/","address":"http://localhost:7002/","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrl\u002BC to shut down.","State":{"Message":"Application started. Press Ctrl\u002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrl\u002BC to shut down."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Development","State":{"Message":"Hosting environment: Development","envName":"Development","{OriginalFormat}":"Hosting environment: {envName}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content root path: C:\\Users\\shirh\\source\\temp\\web50","State":{"Message":"Content root path: C:\\Users\\shirh\\source\\temp\\web50","contentRoot":"C:\\Users\\shirh\\source\\temp\\web50","{OriginalFormat}":"Content root path: {contentRoot}"}}
Proposal
Use the DOTNET_RUNNING_IN_CONTAINER environment variable to control which ConsoleFormatter we default to.
DOTNET_RUNNING_IN_CONTAINER |
ConsoleFormatter |
|---|---|
| True | JsonConsoleFormatter |
| False | SimpleConsoleFormatter |
Questions
Should we make this change to all images or just aspnet? Just aspnet is very hard because we have to decide whether to adopt the aspnet or not aspnet behavior for the SDK. Maybe this is easier than I think, but I can imagine SDK scenarios where people use aspnet. Maybe that is easy to scope out.
Unless folks opt-in to using ILogger there’s no way to make this change to all images. We can do this for all hosted (ASP.NET/worker) app models.
If you chose to Console.WriteLine directly, there’s not much we can (or should) do.
Would this behavior be better as opt-in?
Possibly? That’s why I was hoping to solicit feedback before making the change.
Why is this behavior important for ASP.NET Core in containers and not elsewhere?
I am surprised we are limiting the change to only containers when I'd expect this problem is similarly impactful for non-container scenarios.
Looking at the common deployment targets for hosted app models:
- Deploy on Windows with IIS
- There is no Console attached and console format isn’t applicable
- Deploy on Windows as a Windows Service
- There is no Console attached and console format isn’t applicable
- Deploy on Linux as a systemd service
- Use the systemd console formatter
- Deploy on Linux as a container
- Use the json formatter
Of the top four most common deployment targets, it seems like Linux containers are the only scenario where defaulting to json makes sense.
However, given that the change is mostly inconsequential on Windows, I could be convinced that this change needs to made more broadly.
What do you think of the scenario w/rt SDK containers? Do you think users will want to use the json formatter in that container?
There’s no impact here to other processes in a container. The change we’re discussing only impacts the output of hosted applications. If you do happen to build and run in an SDK container, then yes I expect the console logging from your hosted application to be JSON formatted.
Does this change the behavior during development?
Yes, I propose we gate this change solely on running in a container. The hosting environment (IWebHostEnvironment) has no impact.
