Prompt
How do I collect logs from containers and parse multiline stack traces?
Latest observation
A good container logging setup usually has two parts:
- Collect logs from stdout/stderr
- Make multiline errors/stack traces stay together
1) Collect logs from containers
Best practice
Have your app write logs to stdout/stderr, not to files inside the container. Then use your platform/runtime to collect them.
Common collection options
Docker
- Docker captures container stdout/stderr.
- You can view logs with:
docker logs <container>
- Or use a logging driver:
json-file(default)journaldsyslogfluentdgelfawslogs
Example:
docker run --log-driver=fluentd myapp
Kubernetes
- Kubernetes captures stdout/stderr from each container.
- Node-level agents or collectors can read container logs from files like:
/var/log/containers/*.log
- Typical collectors:
- Fluent Bit
- Fluentd
- Vector
- Filebeat
- Promtail
2) Parse multiline stack traces
Multiline logs are tricky because log shippers often treat each line as a separate event. You need to combine lines before parsing.
What to do
Configure your log collector to detect the start of a new log entry and treat following indented lines as continuations.
Example patterns for stack traces
Java stack trace
Usually starts with a timestamp or log level, then continuation lines begin with whitespace:
2026-10-03 12:00:01 ERROR Failed request
java.lang.RuntimeException: boom
at com.example.Service.doThing(Service.java:42)
at com.example.Controller.handle(Controller.java:18)
Python traceback
Starts with Traceback and continues until the exception line:
Traceback (most recent call last):
File "app.py", line 10, in <module>
main()
ValueError: invalid input
Recommended approaches by tool
Fluent Bit
Use multiline.parser to group stack traces.
Example:
[MULTILINE_PARSER]
Name java
Type regex
Flush_Timeout 1000
Rule "start_state" "/^\d{4}-\d{2}-\d{2}/" "cont"
Rule "cont" "/^\s+at\s+/" "cont"
Then apply it to your input.
Filebeat
Use multiline settings:
multiline.pattern: '^\d{4}-\d{2}-\d{2}'
multiline.negate: true
multiline.match: after
This means: lines not starting with a timestamp are appended to the previous line.
Logstash
Use the multiline codec:
input {
beats {
port => 5044
codec => multiline {
pattern => "^\d{4}-\d{2}-\d{2}"
negate => true
what => "previous"
}
}
}
Vector
Use multiline transform with start/continuation rules.
Practical advice
1. Prefer structured logs
If possible, emit JSON logs with fields like:
timestamplevelmessageservicetrace_idstack_trace
This makes parsing much easier.
Example JSON:
{
"timestamp": "2026-10-03T12:00:01Z",
"level": "error",
"message": "Failed request",
"stack_trace": "java.lang.RuntimeException: boom\n at ..."
}
2. Use one event per exception
If your app/logger supports it, log stack traces as a single event rather than line by line.
3. Define a reliable start pattern
Multiline grouping depends on recognizing the first line. Use something stable, such as:
- timestamp
- log level prefix
- JSON object start
{
4. Test with real logs
Before deploying, test with:
- regular logs
- Java/Python/Go stack traces
- partial/failed traces
- very long traces
Example strategy
If your logs look like this:
2026-10-03 12:00:01 INFO Starting server
2026-10-03 12:00:02 ERROR Request failed
Traceback (most recent call last):
File "app.py", line 10, in <module>
main()
ValueError: invalid input
2026-10-03 12:00:03 INFO Ready
You would configure your shipper so:
- lines starting with a timestamp begin a new record
- all lines until the next timestamp are appended
If you tell me your stack, I can give exact config
If you’re using any of these, I can provide a ready-to-copy config:
- Docker + Fluent Bit
- Kubernetes + Fluent Bit
- Filebeat
- Logstash
- Vector
- Promtail/Loki
If you want, I can show a working Kubernetes + Fluent Bit example for Java stack traces.