Text Output Mode
Relevant source files
The following files were used as context for generating this wiki page:
Text output mode is the default capture mode for eCapture, which displays captured plaintext data directly to the console or log files in human-readable format. Unlike pcap mode (4.2) which saves packets for Wireshark, or keylog mode (4.3) which only captures TLS keys, text mode provides real-time visibility into decrypted communication content with minimal configuration.
For remote/GUI integration using protobuf format, see Protobuf and External Integration. For general event processing architecture, see Event Processing Pipeline.
Overview
Text mode operates as a streaming output mechanism that:
- Default behavior: Activates when no
-mflag is specified or explicitly set with-m text - Real-time display: Events are processed and displayed as they occur
- Protocol-aware formatting: Automatically detects and formats HTTP/1.x, HTTP/2, and other protocols
- Flexible output: Supports both console output and file logging
- Metadata enrichment: Includes process context (PID, command name, network tuple) with each event
Starting from version v0.7.0, text mode no longer captures TLS master keys; use keylog mode (4.3) for key extraction.
Sources: README.md:249-253, CHANGELOG.md:697-723
Configuration
Command Line Flags
Text mode is controlled through several flags passed to capture modules (tls, gotls, gnutls, etc.):
| Flag | Type | Default | Description |
|---|---|---|---|
-m text | string | (default) | Explicitly set text output mode |
--hex | boolean | false | Output payload in hexadecimal dump format |
--logaddr | string | "" | Network address for log forwarding |
-w / --output | string | "" | Write output to specified file instead of stdout |
--truncate | uint64 | 0 | Truncate event payloads to specified size (bytes) |
Logger Configuration
The text output system uses two writer implementations:
- CollectorWriter: Uses
zerologfor structured console/file logging (default for text mode) - ProtobufWriter: Marshals events to protobuf format for WebSocket transmission
Sources: pkg/event_processor/processor.go:42-49, user/event/ievent.go:54-70
Output Format
Standard Text Format
Each captured event is formatted with metadata and payload:
UUID:<PID>_<TID>_<Comm>_<FD>_<DataType>_<Tuple>, Name:<ParserType>, Type:<TypeID>, Length:<Bytes>
PID:<PID>, Comm:<CommandName>, Src:<SrcIP>:<SrcPort>, Dest:<DstIP>:<DstPort>,
<Formatted Payload>Example output from OpenSSL capture:
2024-09-15T11:50:31Z ??? UUID:233479_233479_curl_5_1_39.156.66.10:443, Name:HTTPRequest, Type:1, Length:73
GET / HTTP/1.1
Host: baidu.com
Accept: */*
User-Agent: curl/7.81.0Hexadecimal Mode
When --hex flag is enabled, payloads are displayed as hexadecimal dump instead of formatted text:
// Hexadecimal dump format (example)
00000000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a |GET / HTTP/1.1..|
00000010 48 6f 73 74 3a 20 62 61 69 64 75 2e 63 6f 6d 0d |Host: baidu.com.|Sources: pkg/event_processor/iworker.go:192-194, README_CN.md:103-126
Event Flow Architecture
Data Pipeline
Flow description:
- eBPF Events: Captured by uprobes/kprobes and sent through
PERF_EVENT_ARRAYmaps - Module Decode: Module-specific decoder (e.g., OpenSSL, GoTLS) parses raw eBPF event into
IEventStruct - Event Dispatch:
EventProcessorreceives events and routes them to UUID-specific workers - Worker Accumulation: Each
eventWorkerbuffers events inpayloaduntil a display trigger occurs - Display Trigger: 100ms ticker fires when no new data arrives
- Parser Selection: System detects protocol (HTTP/HTTP2/Default) and applies appropriate formatter
- Output: Formatted data written to console or file via
CollectorWriter
Sources: pkg/event_processor/processor.go:65-89, pkg/event_processor/iworker.go:262-306
Parser Selection and Formatting
Parser Detection Flow
Parser Types
| Parser | Detection Method | Output Format | ParserType ID |
|---|---|---|---|
HTTPRequest | http.ReadRequest() success | HTTP request headers + body | 1 |
HTTPResponse | http.ReadResponse() success | HTTP response headers + body | 3 |
HTTP2Request | HTTP/2 frame preface detection | HTTP/2 frame-by-frame display | 2 |
HTTP2Response | HTTP/2 frame detection | HTTP/2 frame-by-frame display | 4 |
DefaultParser | Fallback if all fail | Raw text or hex dump | 0 |
Sources: pkg/event_processor/iparser.go:85-115, pkg/event_processor/http_request.go:83-92, pkg/event_processor/http_response.go:94-102
CollectorWriter Implementation
Text Output Path
The CollectorWriter wraps a zerolog.Logger instance and implements the standard io.Writer interface, enabling seamless integration with the event processing pipeline:
// CollectorWriter struct (conceptual)
type CollectorWriter struct {
logger *zerolog.Logger
}
func (e CollectorWriter) Write(p []byte) (n int, err error) {
return e.logger.Write(p)
}Output format includes:
- Timestamp (RFC3339 format)
- Log level (INFO/WARN/ERROR)
- Event UUID
- Parser name
- Formatted payload
Sources: user/event/ievent.go:54-70, pkg/event_processor/iworker.go:198-212
Worker Lifecycle and Display Triggers
Event Worker State Machine
Display Trigger Logic
The eventWorker uses a 100ms ticker to detect idle periods:
| Condition | Action |
|---|---|
tickerCount > 10 (1 second) | Trigger Display() |
After Display() | Reset payload buffer and parser |
LifeCycleStateDefault mode | Delete worker and exit |
LifeCycleStateSock mode | Continue running, start new ticker |
Truncation behavior:
If truncateSize is configured and payload.Len() >= truncateSize, the worker:
- Truncates payload to specified size:
payload.Truncate(tsize) - Logs truncation message
- Stops accepting new events for that UUID
Sources: pkg/event_processor/iworker.go:262-306, pkg/event_processor/iworker.go:236-245
Configuration Examples
Basic Text Mode (Console Output)
# OpenSSL module, text mode, console output
sudo ecapture tls
# GoTLS module, text mode with hex dump
sudo ecapture gotls --elfpath=/path/to/go_binary --hex
# Target specific PID
sudo ecapture tls --pid=1234File Output
# Write to file instead of console
sudo ecapture tls -w output.log
# With truncation to limit memory usage
sudo ecapture tls -w output.log --truncate=4096Filtered Output
# Capture only specific process
sudo ecapture tls --pid=5678 -w tls_capture.log
# Capture specific user's traffic
sudo ecapture tls --uid=1000Sources: README.md:72-149, README_CN.md:74-126
HTTP/HTTP2 Formatting Examples
HTTP/1.x Request Display
2024-09-15T11:50:31Z ??? UUID:233479_233479_curl_5_1_39.156.66.10:443, Name:HTTPRequest, Type:1, Length:73
GET / HTTP/1.1
Host: baidu.com
Accept: */*
User-Agent: curl/7.81.0HTTP/1.x Response Display
2024-09-15T11:50:32Z ??? UUID:233479_233479_curl_5_0_39.156.66.10:443, Name:HTTPResponse, Type:3, Length:357
HTTP/1.1 302 Moved Temporarily
Content-Length: 161
Connection: keep-alive
Content-Type: text/html
Date: Sun, 15 Sep 2024 11:50:30 GMT
Location: http://www.baidu.com/
Server: bfe/1.0.8.18
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
</body></html>HTTP/2 Request Display
2024-09-15T11:51:53Z ??? UUID:233851_233851_curl_5_1_172.16.71.1:51837, Name:HTTP2Request, Type:2, Length:304
Frame Type => SETTINGS
Frame Type => WINDOW_UPDATE
Frame Type => HEADERS
header field ":method" = "GET"
header field ":path" = "/"
header field ":scheme" = "https"
header field ":authority" = "google.com"
header field "user-agent" = "curl/7.81.0"
header field "accept" = "*/*"Sources: README.md:102-148, README_CN.md:103-126
Protocol-Specific Formatting
HTTP Request Formatter
The HTTPRequest parser processes HTTP/1.x requests:
- Detection: Calls
http.ReadRequest()on first chunk - Accumulation: Buffers subsequent chunks until complete
- Decompression: Handles
Content-Encoding: gzipautomatically - Output: Uses
httputil.DumpRequest()for formatted display
Key functions:
HTTPRequest.detect(): Validates HTTP request syntax pkg/event_processor/http_request.go:83-92HTTPRequest.Display(): Formats and decompresses body pkg/event_processor/http_request.go:105-157
HTTP Response Formatter
The HTTPResponse parser handles server responses:
- Detection: Calls
http.ReadResponse()on payload - Body handling: Reads full response body with
io.ReadAll() - Compression: Detects and decompresses gzip-encoded bodies
- Special cases: Handles chunked transfer encoding and truncated bodies
Key functions:
HTTPResponse.detect(): Validates response structure pkg/event_processor/http_response.go:94-102HTTPResponse.Display(): Formats headers and body pkg/event_processor/http_response.go:115-175
Default Parser
When no specialized parser matches, DefaultParser provides:
- Raw byte output for binary data
- C-string to Go string conversion for text
- Hexadecimal dump for non-printable characters
Detection logic pkg/event_processor/iparser.go:157-160:
// Display decision based on first byte
if b[0] < 32 || b[0] > 126 {
return []byte(hex.Dump(b)) // Non-printable: hex dump
}
return []byte(CToGoString(b)) // Printable: textSources: pkg/event_processor/http_request.go:105-157, pkg/event_processor/http_response.go:115-175, pkg/event_processor/iparser.go:117-166
Memory Management and Truncation
Truncation Mechanism
To prevent memory exhaustion from large payloads, text mode supports truncation:
// Truncation check before writing events
tsize := int(processor.truncateSize)
if tsize > 0 && payload.Len() >= tsize {
payload.Truncate(tsize)
Log(fmt.Sprintf("Events truncated, size: %d bytes\n", tsize))
return // Stop accepting more events
}Configuration:
- Set via
--truncate=<bytes>flag - Default: 0 (no truncation)
- When triggered: Worker stops accumulating and displays truncated content
Memory Efficiency Improvements
Version 1.1.0 introduced memory optimizations:
- Redesigned truncation logic to reduce memory cost in text mode
- Per-worker buffering instead of global accumulation
- Early truncation prevents oversized payloads from being allocated
Sources: pkg/event_processor/iworker.go:236-245, CHANGELOG.md:163-164
Metadata and Context Enrichment
UUID Format
Each event includes a UUID that encodes connection context:
Standard format:
<PID>_<TID>_<Comm>_<FD>_<DataType>_<SrcIP:SrcPort-DstIP:DstPort>Socket lifecycle format (for connection-bound workers):
sock:<PID>_<TID>_<Comm>_<FD>_<DataType>_<SrcIP:SrcPort-DstIP:DstPort>_<SocketPtr>The UUID parser extracts:
uuidOutput: Display format (without socket pointer)DestroyUUID: Socket pointer for lifecycle managementewLifeCycleState: Worker lifecycle mode
Sources: pkg/event_processor/iworker.go:100-123, user/event/ievent.go:39
Event Base Structure
Every event includes common metadata fields:
| Field | Type | Description |
|---|---|---|
PID | uint32 | Process ID |
PName | string | Command name |
SrcIP | string | Source IP address |
SrcPort | uint16 | Source port |
DstIP | string | Destination IP address |
DstPort | uint16 | Destination port |
Timestamp | uint64 | Kernel timestamp (nanoseconds) |
This metadata is displayed in the formatted output header.
Sources: pkg/event_processor/iworker.go:200-212
Integration with Other Modules
Module-Specific Text Output
Each capture module (OpenSSL, GoTLS, GnuTLS, etc.) generates events that flow through the text output pipeline:
| Module | Event Types | Text Mode Support |
|---|---|---|
| OpenSSL (3.1.1) | SSLDataEvent | Full HTTP/HTTP2 parsing |
| GoTLS (3.1.3) | SSLDataEvent | Full HTTP/HTTP2 parsing |
| GnuTLS (3.1.4) | SSLDataEvent | Full HTTP/HTTP2 parsing |
| Bash (3.2.1) | BashEvent | Command-line text display |
| MySQL (3.2.2) | MySQLEvent | SQL query text display |
| Postgres (3.2.2) | PostgresEvent | SQL query text display |
All modules share the same EventProcessor and output formatting pipeline.
Sources: README.md:152-161
Comparison with Other Output Modes
| Feature | Text Mode | Pcap Mode (4.2) | Keylog Mode (4.3) |
|---|---|---|---|
| Real-time display | ✓ Console/log output | × Buffered to file | × File only |
| Protocol parsing | ✓ HTTP/HTTP2 formatted | × Raw packets | × Keys only |
| Master key capture | × (since v0.7.0) | ✓ DSB block in pcapng | ✓ SSLKEYLOGFILE format |
| Wireshark compatible | × | ✓ Native support | ✓ Via keylog file |
| Memory usage | Low (streaming) | Higher (packet buffering) | Minimal (keys only) |
| Use case | Live monitoring | Forensic analysis | Offline decryption |
Sources: CHANGELOG.md:697-723
Error Handling and Logging
Event Processing Errors
When parsers encounter errors during formatting:
- HTTP/HTTP2 parse errors: Logged but do not stop processing
- Truncation errors: Logged with truncation size
- Write errors: Logged but events continue to flow
- EOF errors: Ignored (normal for incomplete streams)
Example error messages:
eventWorker: write events failed, unknow eventWorker status: 2
ew.parser uuid: sock:1234_1234_curl_5_1... type 1 write payload 2048 bytes, error:unexpected EOFWorker Error Handling
The eventWorker.Run() loop handles errors gracefully:
- Incoming channel full: Drops event, logs error
- Outgoing channel full: Logs error, continues processing
- Parser errors: Logged but not fatal, falls back to hex dump
Sources: pkg/event_processor/iworker.go:154-172, pkg/event_processor/iworker.go:254-257
Performance Considerations
Throughput and Latency
Text mode characteristics:
- Latency: 100ms baseline (ticker interval) + parsing time
- Throughput: Limited by console/file I/O, not CPU-bound
- CPU usage: Parser overhead for HTTP/HTTP2 detection and formatting
- Memory: Configurable via
--truncateflag
Optimization Strategies
- Use truncation for high-volume captures to prevent memory growth
- Write to file instead of console for better throughput
- Filter by PID/UID to reduce event volume
- Use hex mode to skip protocol parsing overhead
Sources: CHANGELOG.md:163-164, pkg/event_processor/iworker.go:236-245