I am writing an application in Golang that processes incoming HTTP requests from SNS. The application starts and returns different HTTP errors when I send bad requests, however, none of the requests are being written to stdout and none of my debugging log/fmt.Printf statements are being written to stdout. Below is an excerpt from my code:
func main() {
// Configure logging
//log.SetOutput(io.MultiWriter(os.Stdout))
//log.SetFlags(log.LstdFlags | log.Lshortfile | log.LUTC)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
// Register handler
http.HandleFunc("/sns", handleSNS)
addr := fmt.Sprintf(":%s", port)
fmt.Printf("Server starting on port %s\n", port)
os.Stdout.Sync()
if err := http.ListenAndServe(addr, nil); err != nil {
fmt.Printf("Failed to start server: %v\n", err)
os.Stdout.Sync()
os.Exit(1)
}
}
func handleSNS(w http.ResponseWriter, r *http.Request) {
fmt.Println("Received HTTP request at /sns")
os.Stdout.Sync()
if r.Method != http.MethodPost {
fmt.Println(os.Stdout, "Invalid method: %s", r.Method)
os.Stdout.Sync()
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Read the raw body for logging
body, err := io.ReadAll(r.Body)
if err != nil {
fmt.Println(os.Stdout, "Error reading request body: %v", err)
os.Stdout.Sync()
http.Error(w, "Error reading request", http.StatusBadRequest)
return
}
...
The application is running as a container on Kubernetes. I've tried a variety of things, e.g. flushing the logs, switching from log statements to fmt.Println and Printf statements, explicitly writing the os.Stdout, etc. The only log line printed to stdout is the "Server starting on port 8080", then nothing from then on. Anyone know what could be wrong and how to fix it? Thanks, Jeremy
I am writing an application in Golang that processes incoming HTTP requests from SNS. The application starts and returns different HTTP errors when I send bad requests, however, none of the requests are being written to stdout and none of my debugging log/fmt.Printf statements are being written to stdout. Below is an excerpt from my code:
func main() {
// Configure logging
//log.SetOutput(io.MultiWriter(os.Stdout))
//log.SetFlags(log.LstdFlags | log.Lshortfile | log.LUTC)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
// Register handler
http.HandleFunc("/sns", handleSNS)
addr := fmt.Sprintf(":%s", port)
fmt.Printf("Server starting on port %s\n", port)
os.Stdout.Sync()
if err := http.ListenAndServe(addr, nil); err != nil {
fmt.Printf("Failed to start server: %v\n", err)
os.Stdout.Sync()
os.Exit(1)
}
}
func handleSNS(w http.ResponseWriter, r *http.Request) {
fmt.Println("Received HTTP request at /sns")
os.Stdout.Sync()
if r.Method != http.MethodPost {
fmt.Println(os.Stdout, "Invalid method: %s", r.Method)
os.Stdout.Sync()
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Read the raw body for logging
body, err := io.ReadAll(r.Body)
if err != nil {
fmt.Println(os.Stdout, "Error reading request body: %v", err)
os.Stdout.Sync()
http.Error(w, "Error reading request", http.StatusBadRequest)
return
}
...
The application is running as a container on Kubernetes. I've tried a variety of things, e.g. flushing the logs, switching from log statements to fmt.Println and Printf statements, explicitly writing the os.Stdout, etc. The only log line printed to stdout is the "Server starting on port 8080", then nothing from then on. Anyone know what could be wrong and how to fix it? Thanks, Jeremy
Share Improve this question asked 2 days ago Jeremy CowanJeremy Cowan 7815 silver badges14 bronze badges 2 |1 Answer
Reset to default 0I know what is going on here..
The main issue is in how you're trying to write to stdout, especially in the handleSNS
function.
You have this small issue:
fmt.Println(os.Stdout, "Invalid method: %s", r.Method)
This is the tricky part - fmt.Println
doesn't work like we might think here. It's not like other languages where we can just tell it where to print. When you try to use it like this, it's basically ignoring your attempt to write to stdout.
try fixing with the following code:
func handleSNS(w http.ResponseWriter, r *http.Request) {
log.Printf("Received HTTP request at /sns") // Changed this
if r.Method != http.MethodPost {
log.Printf("Invalid method: %s", r.Method) // And this
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
log.Printf("Error reading request body: %v", err) // And this
http.Error(w, "Error reading request", http.StatusBadRequest)
return
}
}
log.Printf
is made for this kind of stuff - it's like Go's built-in way to handle logs properly, it automatically adds timestamps (which is super helpful for debugging!) and it handles the formatting for you
If you want to make absolutely sure your logs show up right away (sometimes they get stuck in a buffer), you can add this at the start of your main function:
output := bufio.NewWriterSize(os.Stdout, 0)
log.SetOutput(output)
Hope this helps!
os.Stdout.Sync
. I'm not sure about it's behaviour outside of Linux, but on linux it shouldn't be necessary. IIRC writing to stdout is blocking - at least in the runtime level, and given handlers can be called concurrently, it's better to let the runtime handle this. Other than that, you'd have to detail how you run your application, and perhaps consider digging deeper: run it through dlv, set a breakpoint on a call to thePrintln
calls and theos.Stdout.Sync
calls to see what's going on in the runtime – Elias Van Ootegem Commented 19 hours ago