A good way of logging network connection events

I have lots of Conn instances (from net.Dial(), etc.) and when logging, I need to see what’s going on with specific connections, so now I use something like this:

log.Printf("Handling connection %v", conn)

Which prints out a pointer-ish string such as &{{0xc420053030}}. I believe this happens because conn is an interface, right?

What I would like is to use something which would print out:

Handling connection 192.168.1.5:8412->10.20.30.4:5555

The exact format is not relevant, just something which would extract this information from the Conn instance - like something which attaches the String() method to conn. What would be the best way to do it?

Using a better logging package would be a good start. You could either write this yourself, or if you want to get back to work (what I suggest) use something like logrus - https://github.com/sirupsen/logrus

With it you should be able to write something like…

package main

import (
“net”

log "github.com/sirupsen/logrus"

)

package main

import (
  "net"

  log "github.com/sirupsen/logrus"
)

func main() {
  c, _ := net.Dial("tcp", "golang.org:http")
  // log.SetFormatter(&log.JSONFormatter{})
  log.WithFields(log.Fields{
    "conn": log.Fields{
      "local":  c.LocalAddr(),
      "remote": c.RemoteAddr(),
    },
  }).Info("A walrus appears")
}

And this would output something like

INFO[0000] A walrus appears                              conn=map[remote:172.217.7.145:80 local:10.0.1.7:64890]
func main() {
    ...
    log.Println("Handling connection", connStr(conn))
    ...
}

func connStr(c net.Conn) string {
    return fmt.Sprintf("%v->%v", c.LocalAddr(), c.RemoteAddr())
}

Or, wrap the connection in a type of your own and add an appropriate func String() string to it.

1 Like

It is not possible to define new methods on non-local types like net.IPConn. So it is not possible to implement fmt.Stringer like

// Does not compile!
func (conn *net.IPConn) String() string {
   return fmt.Sprintf("%s->%s", conn.LocalAddr(), conn.RemoteAddr())
}

But you can of coures build a helper function:

package main

import (
	"fmt"
	"log"
	"net"
)

func c2s(conn net.Conn) string {
	return fmt.Sprintf("%s->%s", conn.LocalAddr(), conn.RemoteAddr())
}

func main() {
	conn, err := net.Dial("tcp4", "www.lhorn.de:443")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("%v", c2s(conn))
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.