A network logger can slow an application when log messages arrive faster than the network or remote server can handle them. The pending work builds up; a client sending over TCP may then wait instead of continuing at its usual pace. This is backpressure. section 7.2.2 section 7.3
A busy log server
Imagine a server receiving thousands of messages from many clients. If its throughput falls short, messages accumulate. As acknowledgements are delayed, TCP clients wait to send logs, tying up resources in the applications they serve. section 7.3
Choose a response according to what matters most:
- Buffer network logs to make the logger more resilient when the connection slows or drops. Buffering is the proposed remedy here, not a complete implementation. section 7.2.2
- Use UDP when keeping the application moving matters more than receiving every log message. The client need not wait for server acknowledgements, but server hiccups may lose packets. section 7.3
- Set a dial timeout as a safety net when the network does not behave as expected. In the UDP example, the timeout chiefly covers address resolution and sending. section 7.3
Listing 7.8 UDP-based logging
package main
import (
"log"
"net"
"time"
)
func main() {
timeout := 30 * time.Second #1
conn, err := net.DialTimeout("udp",
"localhost:1902", timeout) #2
if err != nil {
panic("Failed to connect to localhost:1902")
}
defer conn.Close()
f := log.Ldate | log.Lshortfile
logger := log.New(conn, "example ", f)
logger.Println("This is a regular message.")
logger.Panicln("This is a panic.")
}
The Go logging example uses net.DialTimeout with "udp" and passes the resulting connection to log.New. Compare that choice with a TCP network logger when deciding whether the application should wait or risk losing log messages. section 7.3





