nim-eth/eth/p2p/p2p_tracing.nim

115 lines
4.0 KiB
Nim

const tracingEnabled = defined(p2pdump)
when tracingEnabled:
import
macros, typetraits,
serialization, json_serialization/writer,
chronicles, chronicles_tail/configuration
export
# XXX: Nim visibility rules get in the way here.
# It would be nice if the users of this module don't have to
# import json_serializer, but this won't work at the moment,
# because the `encode` call inside `logMsgEvent` has its symbols
# mixed in from the module where `logMsgEvent` is called
# (instead of from this module, which will be more logical).
init, writeValue, getOutput
# TODO: File this as an issue
logStream p2pMessages[json[file(p2p_messages.json,truncate)]]
p2pMessages.useTailPlugin "p2p_tracing_ctail_plugin.nim"
template logRecord(eventName: static[string], args: varargs[untyped]) =
p2pMessages.log LogLevel.NONE, eventName, topics = "p2pdump", args
proc initTracing(baseProtocol: ProtocolInfo,
userProtocols: seq[ProtocolInfo]) =
once:
var w = init StringJsonWriter
proc addProtocol(p: ProtocolInfo) =
w.writeFieldName p.name
w.beginRecord()
for msg in p.messages:
w.writeField $msg.id, msg.name
w.endRecordField()
w.beginRecord()
addProtocol baseProtocol
for userProtocol in userProtocols:
addProtocol userProtocol
w.endRecord()
logRecord "p2p_protocols", data = JsonString(w.getOutput)
proc logMsgEventImpl(eventName: static[string],
peer: Peer,
protocol: ProtocolInfo,
msgName: string,
json: string) =
# this is kept as a separate proc to reduce the code bloat
logRecord eventName, port = int(peer.network.address.tcpPort),
peer = $peer.remote,
protocol = protocol.name,
msg = msgName,
data = JsonString(json)
proc logMsgEvent[Msg](eventName: static[string], peer: Peer, msg: Msg) =
mixin msgProtocol, protocolInfo, msgId
logMsgEventImpl(eventName, peer,
Msg.msgProtocol.protocolInfo,
Msg.type.name,
StringJsonWriter.encode(msg))
proc logSentMsgFields(peer: NimNode,
protocolInfo: NimNode,
msgName: string,
fields: openarray[NimNode]): NimNode =
## This generates the tracing code inserted in the message sending procs
## `fields` contains all the params that were serialized in the message
var tracer = ident("tracer")
result = quote do:
var `tracer` = init StringJsonWriter
beginRecord(`tracer`)
for f in fields:
result.add newCall(bindSym"writeField", tracer, newLit($f), f)
result.add quote do:
endRecord(`tracer`)
logMsgEventImpl("outgoing_msg", `peer`,
`protocolInfo`, `msgName`, getOutput(`tracer`))
template logSentMsg(peer: Peer, msg: auto) =
logMsgEvent("outgoing_msg", peer, msg)
template logReceivedMsg(peer: Peer, msg: auto) =
logMsgEvent("incoming_msg", peer, msg)
template logConnectedPeer(p: Peer) =
logRecord "peer_connected",
port = int(p.network.address.tcpPort),
peer = $p.remote
template logAcceptedPeer(p: Peer) =
logRecord "peer_accepted",
port = int(p.network.address.tcpPort),
peer = $p.remote
template logDisconnectedPeer(p: Peer) =
logRecord "peer_disconnected",
port = int(p.network.address.tcpPort),
peer = $p.remote
else:
template initTracing(baseProtocol: ProtocolInfo,
userProtocols: seq[ProtocolInfo])= discard
template logSentMsg(peer: Peer, msg: auto) = discard
template logReceivedMsg(peer: Peer, msg: auto) = discard
template logConnectedPeer(peer: Peer) = discard
template logAcceptedPeer(peer: Peer) = discard
template logDisconnectedPeer(peer: Peer) = discard