UDP
Synopsis
Creates a target that sends log data as individual UDP datagrams to a remote endpoint. Each event is sent immediately without batching, using a shared connection with mutex-protected writes.
Schema
- name: <string>
description: <string>
type: udp
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
timeout: <numeric>
max_retries: <numeric>
retry_delay: <numeric>
field_format: <string>
debug:
status: <boolean>
dont_send_logs: <boolean>
Configuration
| Field | Required | Default | Description |
|---|---|---|---|
name | Y | Target name | |
description | N | - | Optional description |
type | Y | Must be udp | |
pipelines | N | - | Optional post-processor pipelines |
status | N | true | Enable/disable the target |
Connection
| Field | Required | Default | Description |
|---|---|---|---|
address | Y | Remote server IP address or hostname | |
port | Y | Remote server port (1-65535) | |
timeout | N | 30 | Write deadline in seconds. 0 is read as unset and gives the default of 30, so a write without a deadline cannot be configured. A negative value is rejected at startup |
Retry
| Field | Required | Default | Description |
|---|---|---|---|
max_retries | N | 3 | Retries after a failed write (total attempts = max_retries + 1). 0 is read as unset and gives the default of 3 |
retry_delay | N | 1 | Starting point in seconds for the wait before a retry. 0 is read as unset and gives the default of 1 |
Normalization
| Field | Required | Default | Description |
|---|---|---|---|
field_format | N | - | Data normalization format. See applicable Normalization section |
Scheduling
See Scheduling and Pool Behavior for interval and cron fields shared by all targets.
Debug Options
| Field | Required | Default | Description |
|---|---|---|---|
debug.status | N | false | Enable debug logging |
debug.dont_send_logs | N | false | Process logs but don't send to target (testing) |
Details
The UDP target sends each event as an individual datagram immediately upon receipt -- there is no batching. Each worker establishes its own net.UDPConn connection at initialization for parallel writes.
UDP is a connectionless protocol with no built-in delivery guarantees. Datagrams exceeding the network MTU (typically 1500 bytes) may be fragmented or dropped silently. There is no TLS support; for encrypted delivery, use the TCP target with TLS enabled.
On send failure, the target retries up to max_retries times. Each wait is chosen at random up to a bound that starts from retry_delay, doubles with every attempt, and is capped at 30 seconds. Statistics are recorded once the write succeeds, which on this transport means the datagram was accepted by the local operating system, not that it arrived.
Examples
Basic
Forwarding logs to a remote UDP endpoint... | |
With Retries
Configuring retry behavior for unreliable networks... | |
With Field Normalization
Normalizing fields to Common Information Model before forwarding... | |
Troubleshooting
This section covers the errors you are most likely to see with the udp target, what causes each one, and how to fix it.
Where to look:
- Director logs. Target errors are tagged with the target name and carry
"Section":"SenderPool". The part afterReason:or after the last colon is the actual cause. - The target's connection status in the web interface. It shows the same reason as the log line, prefixed with
connection failed for <target name>:.
See Target Delivery Errors for how Director logs and retries target failures.
A quiet log does not mean delivery is working. Nothing acknowledges a datagram, so most failures on this transport are never reported. Read the first entry below before you conclude from the logs or the counters that records are arriving.
What the receiver needs
| Prerequisite | When it applies | Error when it is missing |
|---|---|---|
A process listening on address and port over UDP | Always | Usually nothing. Sometimes failed to write UDP packet: ... write: connection refused |
A route from the Director host to address | Always | failed to create UDP connection: ... connect: network is unreachable |
| An egress rule that permits UDP to that port | Always | Usually nothing, because the packets are simply dropped on the way |
Resolution of address, when the configuration is read and every time the target starts | address is a hostname | invalid address: lookup ...: no such host, later failed to resolve UDP address: lookup ...: no such host |
An IPv4 address or a hostname in address | Always | failed to resolve UDP address: address ...: too many colons in address for an IPv6 literal |
| Records small enough for a single datagram | Always | failed to write UDP packet: ... write: message too long |
| A receive buffer on the receiver large enough for the datagrams you send | Always | Nothing. The receiver truncates or drops them |
Most delivery failure here is invisible
Nothing acknowledges a datagram, so there is no failure to report when one is lost. A record is counted as sent once the operating system accepts the write. All of the following look identical in the logs and in the target's counters, which is to say they look like success:
- The receiver process is down, or listens on another port, and nothing sends an unreachable message back.
- A firewall, a security group, or a router drops the packets on the way.
addressis wrong but still routes somewhere.- The record is larger than the path MTU, so the datagram is fragmented, and a firewall that does not reassemble fragments drops it. About 1,472 bytes of payload fit an unfragmented datagram on a 1,500-byte MTU.
- The receiver's buffer is smaller than the datagram, so the record is truncated, or a burst overflows the buffer and the receiver drops the rest.
What to do: confirm delivery at the receiver, not at the sender. Capture traffic on that port on the receiving host, and compare the receiver's own counters with what the target reports. Where a failed send has to be visible at all, use the TCP target instead. It reports and retries failed writes, though it still has no acknowledgement from the receiving application, so confirm receipt at the receiver either way.
Records lost this way are never retried. They are counted as delivered, and they are not sent again.
"failed to write UDP packet" with "write: connection refused"
[Error] [director] [target-<target id>] [udp_forwarder] Sender worker 3 execute() failed for <payload location>: target broken: failed to send log record: failed to send UDP packet after 3 retries: failed to write UDP packet: write udp <director ip>:<port>-><receiver ip>:514: write: connection refused
Cause: nothing is listening on port, and the receiving host said so with an unreachable message. Treat this text as "nothing is listening", never as a passing blip. The refusal typically arrives after the datagram that caused it is already gone, so it is reported on a later write and then cleared. That is why the line appears now and then while nothing arrives at all. write: no route to host is the same pattern with the host unreachable rather than the port. On Windows the wording comes from the operating system, and typically reports the same condition as a connection forcibly closed by the remote host.
Fix: start the receiver, or correct port. Confirm the listener on the receiving host, and check the firewall rules for UDP on that port.
Most of the loss stays silent, as in the entry above. Only the occasional record that fails every attempt is reported, and its payload is then retried until fixed, redelivered about every 5 seconds.
"invalid address: lookup ... no such host"
[Error] [director] [target-<target id>] [udp_forwarder] ValidateConfig failed for target "udp_forwarder": invalid address: lookup collector.example.com: no such host
Cause: address is a hostname, and it could not be resolved when the configuration was read. A typo, a record missing from the DNS the Director host uses, or a resolver that did not answer at that moment. The name is resolved again every time the target starts, so the same cause appears later as failed to resolve UDP address: lookup ...: no such host in a Failed to reinitialize line.
Fix: correct the hostname, or set address to an IP address. Check the resolver configuration on the Director host. The configuration is checked again about every 30 seconds, so a resolver outage clears itself once the name resolves.
Nothing is sent while the configuration is rejected, and incoming data waits in the queue.
An IPv6 literal in address is accepted when the configuration is read, and then fails at every start with failed to resolve UDP address: address ...: too many colons in address. The target never delivers. Use a hostname that resolves to the IPv6 address, or an IPv4 address.
"failed to create UDP connection" with "network is unreachable"
[Error] [director] [target-<target id>] [udp_forwarder] Failed to reinitialize target "udp_forwarder" (attempt 2). Reason: failed to create UDP connection: dial udp <receiver ip>:514: connect: network is unreachable
Cause: the Director host has no route to address. An interface is down, a route or a VPN is missing, or the address belongs to a network this host cannot reach. Only the local routing table is consulted here, so this error never means the receiver is down or the port is closed. A powered-off receiver, or a port with nothing behind it, starts cleanly.
The same reason preceded by a worker number, as failed to create per-worker UDP connection: ..., has the same cause. Two other causes are typical on a loaded or locked-down host, and both appear as wrapped text after failed to create UDP connection:. The process can be out of file descriptors, or a local policy can be refusing the socket.
Fix: restore the route or the interface, and check from the Director host that the address is routable. Raise the open-file limit for the service when the text mentions open files.
Retried until fixed, backing off from 5 seconds to once a minute. Nothing is sent while the target cannot start, and incoming data waits in the queue. The connection status in the web interface carries the same reason.
"write: message too long"
[Error] [director] [target-<target id>] [udp_forwarder] Sender worker 2 execute() failed for <payload location>: target broken: failed to send log record: failed to send UDP packet after 3 retries: failed to write UDP packet: write udp <director ip>:<port>-><receiver ip>:514: write: message too long
Cause: one record does not fit in a single datagram. Every record is sent as one datagram, and a datagram carries at most 65,507 bytes of payload over IPv4. The same error appears well below that size when the record is larger than the interface MTU and the host is not allowed to fragment it.
Fix: shorten the record in the pipeline, by dropping or truncating the fields that make it large. Send large records with the TCP target instead, which is not bound by a datagram size.
This one does not clear itself. The record fails the same way on every delivery, so the payload is redelivered about every 5 seconds for as long as it sits at the head of the queue, and the rest of the target's traffic waits behind it. Nothing is dropped, and nothing moves either, until the record is made smaller.
Errors that appear during a restart or a configuration reload
[Error] [director] [target-<target id>] [udp_forwarder] Sender worker 1 execute() failed for <payload location>: target broken: failed to send log record: failed to send UDP packet: shutdown during retry (attempt 2): failed to write UDP packet: write udp <director ip>:<port>-><receiver ip>:514: write: connection refused
Cause: a shutdown or a configuration reload arrived while a record was waiting between retries. UDP connection not initialized and use of closed network connection in a similar line have the same origin. The socket was closed while a record was on its way to it.
Fix: none. These clear themselves once the target is running again, and the payload is redelivered, so nothing is lost. If they keep appearing outside a restart, the target is reinitializing repeatedly. Look for the reason in the Failed to reinitialize lines around them.
Zero does not mean "no deadline" or "no retries"
timeout, max_retries and retry_delay read 0 as "not set" and use their default instead:
| Setting | What 0 looks like it does | What it does |
|---|---|---|
timeout | Write with no deadline | 30 seconds |
max_retries | Send once, never retry | 3 retries, so 4 attempts |
retry_delay | Retry with no wait | Waits as though set to 1 |
Use 1 or more for all three. A write without a deadline cannot be configured, and neither can a single attempt per record. A negative timeout is different: it is rejected when the target starts, with timeout must be zero or greater for udp target, got -1, and nothing is delivered until it is corrected.
Retries are per record, and the worker holding that record waits through them. With max_retries: 5 and retry_delay: 2, one record that cannot be written can occupy its worker for about a minute, during which that worker sends nothing else.
interval and cron do not change when records leave this target. There is no batch to flush, so each record is written as it is processed.
The target looks healthy but nothing arrives
Check these in order.
debug.dont_send_logsis enabled. Records are processed and then discarded rather than sent, and the payload is marked delivered. Withdebug.statusalso enabled, startup logsLog sending is disabled for this target (udp_forwarder). Logs will be processed by the pipeline but will not be sent to the target.Withdebug.statusoff, nothing is logged at all.- The datagrams never arrive. Work through the causes listed under Most delivery failure here is invisible above, at the receiver rather than at the sender.
- The hostname now resolves to a different address.
addressis resolved when the target starts, and that result is used until it starts again. Save the target configuration again after a DNS change, or setaddressto an IP address deliberately. - The receiver cannot read what it receives. There is no encryption and no negotiation on this transport. A receiver that expects TLS, or a different syslog format, typically discards the datagrams without telling the sender. Use the TCP target for encrypted delivery.
field_formatdid not apply. When normalization cannot map a record, the record is sent without it and nothing is logged. Validate the mapping in a test pipeline before relying on it.
Counters do not settle any of this. The target's sent counter moves when the host accepts the datagram, so it counts records handed over, not records received.