json.Decoding a TCP connection and logging the original data at the same time in Go

I'm using a json.Decoder to decode a net.Conn into a custom struct. I would like to also log the original JSON string sent on the net.Conn without modifying it.

I am looking for an efficient way to achieve this. I currently have the following code:

reader := bufio.NewReader(conn)   // conn is a net.Conn
dec := json.NewDecoder(reader)

for {   

    // How can I also log the original data before decoding it into the struct?

    var dst customStruct
    if err = dec.Decode(&dst); err == io.EOF {
        break
    } else if err != nil {
        log.Errorf("failed to decode message: %s", err)
        break
    }

    // do something with dst...

}
    

Upvotes: 0

Views: 667

Answers (2)

Flimcy
Flimcy

Reputation: 26

Use iotest.NewReadLogger to log the data as the data is read:

prefix := fmt.Sprintf("%p:", conn)
reader := bufio.NewReader(iotest.NewReadLogger(prefix, conn)) 
dec := json.NewDecoder(reader)

for {   

    var dst customStruct
    if err = dec.Decode(&dst); err == io.EOF {
        break
    } else if err != nil {
        log.Errorf("failed to decode message: %s", err)
        break
    }

    // do something with dst...

}
    

If the read logger output does not match your taste, then copy the implementation and adjust as needed. The implementation is very simple.

Upvotes: 1

poWar
poWar

Reputation: 825

You can use ioutil.ReadAll() and then print and decode from the bytes. But since you are reading all of the bytes without using a buffer, you should ideally put this behind a debug flag check.

bs,err := ioutil.ReadAll()
if err != nil {
    panic(err)
}

log.Printf("output: %s", string(bs))

var dst customStruct
if err := json.Unmarshal(bs, &dst); err != nil {
    panic(err)
}

Upvotes: 0

Related Questions