APM Agent language and version:
apm-agent-go v1.5.0
Question:
I am using net/http and github.com/gorilla/websocket for websocket development, but I find that as long as I upgrade websocket, I cannot collect data and link information of the API interface on APM.
So you want to trace from ReadRequest to WriteMessage? e.g. you might have a connection session that goes like this:
Client connects
Client sends message, waits for response
2.1. Server receives message
2.2. Server does some work...
2.3. Server sends response
Repeat step 2
Client disconnects
If that's the case then you could trace it using apm.StartTransaction, like this:
func echo(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer c.Close()
for {
if err := handleMessage(c); err != nil {
break
}
}
}
func handleMessage(c *websocket.Conn) error {
mt, message, err := c.ReadMessage()
if err != nil {
break
}
tx := apm.DefaultTracer.StartTransaction("echo", "request")
defer tx.End()
// Do some work...
return c.WriteMessage(mt, message)
}
If you want distributed tracing, originating from the WebSocket client, that's more difficult. You can't rely on the HTTP headers because those are for the original HTTP request, and not related to each individual message sent to the WebSocket. Instead you would have to add the trace context to the messages you send over the WebSocket.
@axw I also thought about this solution, and it can be solved, but the problem is that I can't find a place where apm.DefaultTracer can set the context. In this way, how can I ensure that it can be connected to other tracing (HTTP, MySQL ...) in the request?
--
I might make other HTTP, SQL calls in the handleMessage method.
You will need to create a new context object when you start a transaction (receive a message), and add the transaction to it using apm.ContextWithTransaction. Like this:
func handleMessage(c *websocket.Conn) error {
mt, message, err := c.ReadMessage()
if err != nil {
break
}
tx := apm.DefaultTracer.StartTransaction("echo", "request")
defer tx.End()
// Create a new context for the transaction
ctx := apm.ContextWithTransaction(context.Background(), tx)
// Do some work...
rows, err := db.QueryContext(ctx, "SELECT ...")
// Do some more work...
return c.WriteMessage(mt, message)
}
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant
logo are trademarks of the
Apache Software Foundation
in the United States and/or other countries.