mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
222 lines
7.4 KiB
Go
222 lines
7.4 KiB
Go
package metrics
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
|
|
"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)
|
|
ptos = stats.Int64("quic-go/ptos", "number of times the PTO timer fired", stats.UnitDimensionless)
|
|
closes = stats.Int64("quic-go/close", "number of connections closed", 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")
|
|
keyCloseReason, _ = tag.NewKey("close_reason")
|
|
keyCloseRemote, _ = tag.NewKey("close_remote")
|
|
keyErrorCode, _ = tag.NewKey("error_code")
|
|
keyHandshakePhase, _ = tag.NewKey("handshake_phase")
|
|
)
|
|
|
|
// 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(),
|
|
}
|
|
PTOView = &view.View{
|
|
Measure: ptos,
|
|
TagKeys: []tag.Key{keyHandshakePhase},
|
|
Aggregation: view.Count(),
|
|
}
|
|
CloseView = &view.View{
|
|
Measure: closes,
|
|
TagKeys: []tag.Key{keyCloseReason, keyErrorCode},
|
|
Aggregation: view.Count(),
|
|
}
|
|
)
|
|
|
|
// DefaultViews collects all OpenCensus views for metric gathering purposes
|
|
var DefaultViews = []*view.View{
|
|
ConnectionsView,
|
|
LostPacketsView,
|
|
SentPacketsView,
|
|
CloseView,
|
|
}
|
|
|
|
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
|
|
|
|
handshakeComplete bool
|
|
}
|
|
|
|
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 utils.IsIPv4(udpAddr.IP) {
|
|
ipVersionTag = tag.Upsert(keyIPVersion, "IPv4")
|
|
} else {
|
|
ipVersionTag = tag.Upsert(keyIPVersion, "IPv6")
|
|
}
|
|
} else {
|
|
ipVersionTag = tag.Upsert(keyIPVersion, "unknown")
|
|
}
|
|
|
|
stats.RecordWithTags(
|
|
context.Background(),
|
|
[]tag.Mutator{perspectiveTag, ipVersionTag},
|
|
connections.M(1),
|
|
)
|
|
}
|
|
|
|
func (t *connTracer) ClosedConnection(r logging.CloseReason) {
|
|
var tags []tag.Mutator
|
|
if timeout, ok := r.Timeout(); ok {
|
|
tags = []tag.Mutator{
|
|
tag.Upsert(keyCloseReason, timeoutReason(timeout).String()),
|
|
tag.Upsert(keyCloseRemote, "false"),
|
|
}
|
|
} else if _, ok := r.StatelessReset(); ok {
|
|
tags = []tag.Mutator{
|
|
tag.Upsert(keyCloseReason, "stateless_reset"),
|
|
tag.Upsert(keyCloseRemote, "true"),
|
|
}
|
|
} else if errorCode, remote, ok := r.ApplicationError(); ok {
|
|
tags = []tag.Mutator{
|
|
tag.Upsert(keyCloseReason, "application_error"),
|
|
tag.Upsert(keyErrorCode, errorCode.String()),
|
|
tag.Upsert(keyCloseRemote, fmt.Sprintf("%t", remote)),
|
|
}
|
|
} else if errorCode, remote, ok := r.TransportError(); ok {
|
|
tags = []tag.Mutator{
|
|
tag.Upsert(keyCloseReason, "transport_error"),
|
|
tag.Upsert(keyErrorCode, errorCode.String()),
|
|
tag.Upsert(keyCloseRemote, fmt.Sprintf("%t", remote)),
|
|
}
|
|
}
|
|
stats.RecordWithTags(context.Background(), tags, closes.M(1))
|
|
}
|
|
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) {
|
|
typ := logging.PacketTypeFromHeader(&hdr.Header)
|
|
if typ == logging.PacketType1RTT {
|
|
t.handshakeComplete = true
|
|
}
|
|
stats.RecordWithTags(
|
|
context.Background(),
|
|
[]tag.Mutator{
|
|
tag.Upsert(keyPacketType, packetType(typ).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) UpdatedCongestionState(logging.CongestionState) {}
|
|
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) {
|
|
if value == 0 {
|
|
return
|
|
}
|
|
phase := "during_handshake"
|
|
if t.handshakeComplete {
|
|
phase = "after_handshake"
|
|
}
|
|
stats.RecordWithTags(
|
|
context.Background(),
|
|
[]tag.Mutator{tag.Upsert(keyHandshakePhase, phase)},
|
|
ptos.M(1),
|
|
)
|
|
}
|
|
func (t *connTracer) UpdatedKeyFromTLS(logging.EncryptionLevel, logging.Perspective) {}
|
|
func (t *connTracer) UpdatedKey(logging.KeyPhase, bool) {}
|
|
func (t *connTracer) DroppedEncryptionLevel(logging.EncryptionLevel) {}
|
|
func (t *connTracer) DroppedKey(logging.KeyPhase) {}
|
|
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) Debug(string, string) {}
|
|
func (t *connTracer) Close() {}
|