package metrics import ( "context" "net" "time" "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/logging" "go.opencensus.io/stats" "go.opencensus.io/stats/view" "go.opencensus.io/tag" ) // Measures var ( connections = stats.Int64("quic-go/connections", "number of QUIC connections", stats.UnitDimensionless) lostPackets = stats.Int64("quic-go/lost-packets", "number of packets declared lost", stats.UnitDimensionless) sentPackets = stats.Int64("quic-go/sent-packets", "number of packets sent", stats.UnitDimensionless) ) // Tags var ( keyPerspective, _ = tag.NewKey("perspective") keyIPVersion, _ = tag.NewKey("ip_version") keyEncryptionLevel, _ = tag.NewKey("encryption_level") keyPacketLossReason, _ = tag.NewKey("packet_loss_reason") keyPacketType, _ = tag.NewKey("packet_type") ) // Views var ( ConnectionsView = &view.View{ Measure: connections, TagKeys: []tag.Key{keyPerspective, keyIPVersion}, Aggregation: view.Count(), } LostPacketsView = &view.View{ Measure: lostPackets, TagKeys: []tag.Key{keyEncryptionLevel, keyPacketLossReason}, Aggregation: view.Count(), } SentPacketsView = &view.View{ Measure: sentPackets, TagKeys: []tag.Key{keyPacketType}, Aggregation: view.Count(), } ) // DefaultViews collects all OpenCensus views for metric gathering purposes var DefaultViews = []*view.View{ ConnectionsView, LostPacketsView, SentPacketsView, } type tracer struct{} var _ logging.Tracer = &tracer{} // NewTracer creates a new metrics tracer. func NewTracer() logging.Tracer { return &tracer{} } func (t *tracer) TracerForConnection(p logging.Perspective, _ logging.ConnectionID) logging.ConnectionTracer { return newConnTracer(t, p) } func (t *tracer) SentPacket(_ net.Addr, hdr *logging.Header, _ protocol.ByteCount, _ []logging.Frame) { stats.RecordWithTags( context.Background(), []tag.Mutator{ tag.Upsert(keyPacketType, packetType(logging.PacketTypeFromHeader(hdr)).String()), }, sentPackets.M(1), ) } func (t *tracer) DroppedPacket(net.Addr, logging.PacketType, logging.ByteCount, logging.PacketDropReason) { } type connTracer struct { perspective logging.Perspective tracer logging.Tracer } func newConnTracer(tracer logging.Tracer, perspective logging.Perspective) logging.ConnectionTracer { return &connTracer{ perspective: perspective, tracer: tracer, } } var _ logging.ConnectionTracer = &connTracer{} func (t *connTracer) StartedConnection(local, _ net.Addr, _ logging.VersionNumber, _, _ logging.ConnectionID) { perspectiveTag := tag.Upsert(keyPerspective, perspective(t.perspective).String()) var ipVersionTag tag.Mutator if udpAddr, ok := local.(*net.UDPAddr); ok { // If ip is not an IPv4 address, To4 returns nil. // Note that there might be some corner cases, where this is not correct. // See https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6. if udpAddr.IP.To4() == nil { ipVersionTag = tag.Upsert(keyIPVersion, "IPv6") } else { ipVersionTag = tag.Upsert(keyIPVersion, "IPv4") } } else { ipVersionTag = tag.Upsert(keyIPVersion, "unknown") } stats.RecordWithTags( context.Background(), []tag.Mutator{perspectiveTag, ipVersionTag}, connections.M(1), ) } func (t *connTracer) ClosedConnection(logging.CloseReason) {} func (t *connTracer) SentTransportParameters(*logging.TransportParameters) {} func (t *connTracer) ReceivedTransportParameters(*logging.TransportParameters) {} func (t *connTracer) SentPacket(hdr *logging.ExtendedHeader, _ logging.ByteCount, _ *logging.AckFrame, _ []logging.Frame) { stats.RecordWithTags( context.Background(), []tag.Mutator{ tag.Upsert(keyPacketType, packetType(logging.PacketTypeFromHeader(&hdr.Header)).String()), }, sentPackets.M(1), ) } func (t *connTracer) ReceivedVersionNegotiationPacket(*logging.Header, []logging.VersionNumber) {} func (t *connTracer) ReceivedRetry(*logging.Header) {} func (t *connTracer) ReceivedPacket(*logging.ExtendedHeader, logging.ByteCount, []logging.Frame) { } func (t *connTracer) BufferedPacket(logging.PacketType) {} func (t *connTracer) DroppedPacket(logging.PacketType, logging.ByteCount, logging.PacketDropReason) {} func (t *connTracer) UpdatedMetrics(*logging.RTTStats, logging.ByteCount, logging.ByteCount, int) {} func (t *connTracer) LostPacket(encLevel logging.EncryptionLevel, _ logging.PacketNumber, reason logging.PacketLossReason) { stats.RecordWithTags( context.Background(), []tag.Mutator{ tag.Upsert(keyEncryptionLevel, encryptionLevel(encLevel).String()), tag.Upsert(keyPacketLossReason, packetLossReason(reason).String()), }, lostPackets.M(1), ) } func (t *connTracer) UpdatedPTOCount(value uint32) {} func (t *connTracer) UpdatedKeyFromTLS(logging.EncryptionLevel, logging.Perspective) {} func (t *connTracer) UpdatedKey(logging.KeyPhase, bool) {} func (t *connTracer) DroppedEncryptionLevel(logging.EncryptionLevel) {} func (t *connTracer) SetLossTimer(logging.TimerType, logging.EncryptionLevel, time.Time) {} func (t *connTracer) LossTimerExpired(logging.TimerType, logging.EncryptionLevel) {} func (t *connTracer) LossTimerCanceled() {} func (t *connTracer) Close() {}