| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System.Collections.Generic; |
| | | 5 | | using System.Diagnostics; |
| | | 6 | | |
| | | 7 | | namespace System.Net.Http.Metrics |
| | | 8 | | { |
| | | 9 | | internal sealed class ConnectionMetrics |
| | | 10 | | { |
| | | 11 | | private readonly SocketsHttpHandlerMetrics _metrics; |
| | | 12 | | private readonly bool _openConnectionsEnabled; |
| | | 13 | | private readonly string _protocolVersionTag; |
| | | 14 | | private readonly string _schemeTag; |
| | | 15 | | private readonly string _hostTag; |
| | | 16 | | private readonly int _portTag; |
| | | 17 | | private readonly string? _peerAddressTag; |
| | | 18 | | private bool _currentlyIdle; |
| | | 19 | | |
| | 0 | 20 | | public ConnectionMetrics(SocketsHttpHandlerMetrics metrics, string protocolVersion, string scheme, string host, |
| | 0 | 21 | | { |
| | 0 | 22 | | _metrics = metrics; |
| | 0 | 23 | | _openConnectionsEnabled = _metrics.OpenConnections.Enabled; |
| | 0 | 24 | | _protocolVersionTag = protocolVersion; |
| | 0 | 25 | | _schemeTag = scheme; |
| | 0 | 26 | | _hostTag = host; |
| | 0 | 27 | | _portTag = port; |
| | 0 | 28 | | _peerAddressTag = peerAddress; |
| | 0 | 29 | | } |
| | | 30 | | |
| | | 31 | | // TagList is a huge struct, so we avoid storing it in a field to reduce the amount we allocate on the heap. |
| | | 32 | | private TagList GetTags() |
| | 0 | 33 | | { |
| | 0 | 34 | | TagList tags = default; |
| | | 35 | | |
| | 0 | 36 | | tags.Add("network.protocol.version", _protocolVersionTag); |
| | 0 | 37 | | tags.Add("url.scheme", _schemeTag); |
| | 0 | 38 | | tags.Add("server.address", _hostTag); |
| | 0 | 39 | | tags.Add("server.port", DiagnosticsHelper.GetBoxedInt32(_portTag)); |
| | | 40 | | |
| | 0 | 41 | | if (_peerAddressTag is not null) |
| | 0 | 42 | | { |
| | 0 | 43 | | tags.Add("network.peer.address", _peerAddressTag); |
| | 0 | 44 | | } |
| | | 45 | | |
| | 0 | 46 | | return tags; |
| | 0 | 47 | | } |
| | | 48 | | |
| | | 49 | | private OpenConnectionsTagKey CreateTagKey(bool idle) => |
| | 0 | 50 | | new OpenConnectionsTagKey(_protocolVersionTag, _schemeTag, _hostTag, _portTag, idle, _peerAddressTag); |
| | | 51 | | |
| | | 52 | | public void ConnectionEstablished() |
| | 0 | 53 | | { |
| | 0 | 54 | | if (_openConnectionsEnabled) |
| | 0 | 55 | | { |
| | 0 | 56 | | lock (this) |
| | 0 | 57 | | { |
| | 0 | 58 | | _currentlyIdle = true; |
| | 0 | 59 | | _metrics.OpenConnectionsTracker.Increment(CreateTagKey(idle: true)); |
| | 0 | 60 | | } |
| | 0 | 61 | | } |
| | 0 | 62 | | } |
| | | 63 | | |
| | | 64 | | public void ConnectionClosed(long durationMs) |
| | 0 | 65 | | { |
| | 0 | 66 | | if (_metrics.ConnectionDuration.Enabled) |
| | 0 | 67 | | { |
| | 0 | 68 | | _metrics.ConnectionDuration.Record(durationMs / 1000d, GetTags()); |
| | 0 | 69 | | } |
| | | 70 | | |
| | 0 | 71 | | if (_openConnectionsEnabled) |
| | 0 | 72 | | { |
| | 0 | 73 | | lock (this) |
| | 0 | 74 | | { |
| | 0 | 75 | | _metrics.OpenConnectionsTracker.Decrement(CreateTagKey(idle: _currentlyIdle)); |
| | 0 | 76 | | } |
| | 0 | 77 | | } |
| | 0 | 78 | | } |
| | | 79 | | |
| | | 80 | | public void IdleStateChanged(bool idle) |
| | 0 | 81 | | { |
| | 0 | 82 | | if (_openConnectionsEnabled && _currentlyIdle != idle) |
| | 0 | 83 | | { |
| | 0 | 84 | | lock (this) |
| | 0 | 85 | | { |
| | 0 | 86 | | _currentlyIdle = idle; |
| | 0 | 87 | | _metrics.OpenConnectionsTracker.Decrement(CreateTagKey(idle: !idle)); |
| | 0 | 88 | | _metrics.OpenConnectionsTracker.Increment(CreateTagKey(idle: idle)); |
| | 0 | 89 | | } |
| | 0 | 90 | | } |
| | 0 | 91 | | } |
| | | 92 | | } |
| | | 93 | | } |
| | | 94 | | |