Configure Producing of Flow Spans
Block: span
Mermin groups captured packets into bidirectional flows and exports each flow as an OpenTelemetry span. The span block controls when flows are closed and when they emit records, plus Community ID hashing, trace ID correlation, and hostname resolution. Add a top-level span { } block in your configuration file; there are no CLI or environment overrides for span options.
The span block lets you configure:
Timeouts and record interval: when flows are closed (protocol-specific inactivity timeouts) and how often long-lived flows emit records (
max_record_interval)Community ID and trace correlation: five-tuple hashing for correlation across agents and how long the same Community ID keeps the same trace ID
Hostname resolution: whether to resolve IPs to hostnames for
client.addressandserver.addressand the lookup timeout
Flow semantics (how flows become OpenTelemetry spans and what attributes they carry) are in Semantic Conventions and Attribute Reference.
Configuration
A full configuration example can be found in the Default Configuration.
max_record_intervalattributeMaximum time an active flow can run without exporting a record. When this interval is reached, a record is emitted and the flow continues. Long-lived flows are therefore split into multiple spans.
Type: Duration
Default:
60sExample: Emit records more frequently for long-lived flows (e.g. streaming)
span { max_record_interval = "30s" }generic_timeoutattributeInactivity timeout for protocols that have no dedicated timeout: GRE, ESP, AH, and other IP protocols. After this period with no packets, the flow is closed. Flows with at least one packet are exported; flows with zero packets are dropped.
Type: Duration
Default:
30sExample: Shorter timeout for non-TCP/UDP/ICMP protocols
span { generic_timeout = "15s" }icmp_timeoutattributeInactivity timeout for ICMP (e.g. ping, traceroute).
Type: Duration
Default:
10sExample: Longer ICMP timeout for slow traceroutes
span { icmp_timeout = "20s" }tcp_timeoutattributeInactivity timeout for TCP flows that remain open (no FIN or RST observed). When this timeout elapses without traffic, the flow is considered inactive and will be closed. For each TCP flow,
tcp_timeoutapplies as long as no FIN or RST has been seen.Type: Duration
Default:
20sExample: Shorter TCP inactivity timeout
span { tcp_timeout = "10s" }tcp_fin_timeoutattributeAfter a FIN (graceful close) is observed on a TCP flow, the exporter waits for this timeout before exporting the flow. This allows late-arriving final ACKs to be captured. For each TCP flow, once a FIN is seen,
tcp_fin_timeoutdetermines when the flow is closed and exported.Type: Duration
Default:
5sExample: Shorter delay after FIN before exporting
span { tcp_fin_timeout = "2s" }tcp_rst_timeoutattributeWhen a TCP RST (reset) is observed — indicating an abrupt connection termination — the flow waits for the specified
tcp_rst_timeoutbefore being exported. This timeout is evaluated for each flow individually after an RST is detected, ensuring even abruptly closed connections are accounted for with a brief post-RST delay before export.Type: Duration
Default:
5sExample: Shorter delay after RST before exporting
span { tcp_rst_timeout = "2s" }udp_timeoutattributeInactivity timeout for UDP. UDP is connectionless; a longer value suits sporadic traffic.
Type: Duration
Default:
60sExample: Shorter UDP timeout when you only care about short-lived UDP flows
span { udp_timeout = "30s" }community_id_seedattributeSeed for Community ID hashing of the flow five-tuple. Use the same seed everywhere for correlation across agents and tools. The result is exported as
flow.community_id(Attribute Reference).Type: Integer (uint16)
Default:
0Example: Use a custom seed to align with another tool (e.g. Zeek) that uses a non-zero seed
span { community_id_seed = 1 }trace_id_timeoutattributeHow long the same Community ID keeps the same trace ID. Bounds memory while still allowing correlation across flow records for the same logical flow.
Type: Duration
Default:
24hExample: Shorter trace correlation window to reduce memory
span { trace_id_timeout = "1h" }enable_hostname_resolutionattributeWhen true,
client.addressandserver.addressmay be reverse-DNS hostnames instead of IPs (Attribute Reference).Type: Boolean
Default:
trueExample: Disable hostname resolution to avoid DNS lookups and use IPs only
span { enable_hostname_resolution = false }hostname_resolve_timeoutattributeTimeout for each reverse-DNS lookup. Results are cached.
Type: Duration
Default:
100msExample: Increase timeout for slow or high-latency DNS
span { hostname_resolve_timeout = "500ms" }
When is a Flow Span Exported
Understanding when spans are exported helps with tuning and capacity planning. A flow span is exported when any of these is true:
Max interval: The flow has been active for
max_record_intervalwithout emitting a record. A record is emitted and the flow continues (may emit again at the next interval).Protocol timeout: No packets for the protocol-specific timeout (generic, ICMP, TCP, or UDP). The flow is closed and removed from the flow table.
TCP close: A FIN or RST was seen and the corresponding
tcp_fin_timeoutortcp_rst_timeouthas elapsed. The flow is closed and exported.
Exported spans are sent to the targets configured in your export block (OTLP export, stdout export, etc.). Workers poll flow state on an interval defined in pipeline (flow_producer.flow_store_poll_interval). The flow table is backed by the eBPF FLOW_STATS map and in-memory state; its max capacity is set in pipeline (flow_capture.flow_stats_capacity).
Tuning
Shorter intervals and timeouts mean more exports and higher storage and OTLP export load; longer values reduce volume and improve aggregation at the cost of slower visibility.
For high-throughput or memory-constrained nodes, use longer or shorter timeouts accordingly. To reduce the number of flows tracked, use flow filters.
Troubleshooting and Pipeline cover backpressure, export tuning, and pipeline sizing.
Monitoring
Flow and eBPF map metrics are in Internal Metrics: mermin_flow_spans_active_total, mermin_flow_spans_created_total, and mermin_ebpf_map_size / mermin_ebpf_map_capacity with map="FLOW_STATS".
If the flow table or memory grows without bound, lower timeouts or max_record_interval, or reduce tracked flows with flow filters. If you need more headroom, increase the max capacity via flow_capture.flow_stats_capacity in pipeline.
Next Steps
Filter Flows Before Export: Reduce volume and focus on relevant traffic
Configure OTLP Export: Send flows to your backend
Review Complete Configurations: Production-ready examples
Tune the Pipeline: Optimize for high-throughput
Need Help?
Troubleshoot Flow Issues: Diagnose flow generation problems
GitHub Discussions: Ask about timeout tuning
Last updated