| | | 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 object _protocolVersionTag; |
| | | 14 | | private readonly object _schemeTag; |
| | | 15 | | private readonly object _hostTag; |
| | | 16 | | private readonly object _portTag; |
| | | 17 | | private readonly object? _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 = DiagnosticsHelper.GetBoxedInt32(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", _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 | | |
| | 0 | 49 | | private static KeyValuePair<string, object?> GetStateTag(bool idle) => new KeyValuePair<string, object?>("http.c |
| | | 50 | | |
| | | 51 | | public void ConnectionEstablished() |
| | 0 | 52 | | { |
| | 0 | 53 | | if (_openConnectionsEnabled) |
| | 0 | 54 | | { |
| | 0 | 55 | | _currentlyIdle = true; |
| | 0 | 56 | | TagList tags = GetTags(); |
| | 0 | 57 | | tags.Add(GetStateTag(idle: true)); |
| | 0 | 58 | | _metrics.OpenConnections.Add(1, tags); |
| | 0 | 59 | | } |
| | 0 | 60 | | } |
| | | 61 | | |
| | | 62 | | public void ConnectionClosed(long durationMs) |
| | 0 | 63 | | { |
| | 0 | 64 | | TagList tags = GetTags(); |
| | | 65 | | |
| | 0 | 66 | | if (_metrics.ConnectionDuration.Enabled) |
| | 0 | 67 | | { |
| | 0 | 68 | | _metrics.ConnectionDuration.Record(durationMs / 1000d, tags); |
| | 0 | 69 | | } |
| | | 70 | | |
| | 0 | 71 | | if (_openConnectionsEnabled) |
| | 0 | 72 | | { |
| | 0 | 73 | | tags.Add(GetStateTag(idle: _currentlyIdle)); |
| | 0 | 74 | | _metrics.OpenConnections.Add(-1, tags); |
| | 0 | 75 | | } |
| | 0 | 76 | | } |
| | | 77 | | |
| | | 78 | | public void IdleStateChanged(bool idle) |
| | 0 | 79 | | { |
| | 0 | 80 | | if (_openConnectionsEnabled && _currentlyIdle != idle) |
| | 0 | 81 | | { |
| | 0 | 82 | | _currentlyIdle = idle; |
| | 0 | 83 | | TagList tags = GetTags(); |
| | 0 | 84 | | tags.Add(GetStateTag(idle: !idle)); |
| | 0 | 85 | | _metrics.OpenConnections.Add(-1, tags); |
| | 0 | 86 | | tags[tags.Count - 1] = GetStateTag(idle: idle); |
| | 0 | 87 | | _metrics.OpenConnections.Add(1, tags); |
| | 0 | 88 | | } |
| | 0 | 89 | | } |
| | | 90 | | } |
| | | 91 | | } |