< Summary

Line coverage
1%
Covered lines: 3
Uncovered lines: 219
Coverable lines: 222
Total lines: 367
Line coverage: 1.3%
Branch coverage
1%
Covered branches: 1
Total branches: 100
Branch coverage: 1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs

#LineLine coverage
 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
 4using System.Diagnostics;
 5using System.Diagnostics.CodeAnalysis;
 6using System.Diagnostics.Tracing;
 7using System.Security.Authentication;
 8using System.Threading;
 9
 10namespace System.Net.Security
 11{
 12    [EventSource(Name = "System.Net.Security")]
 13    internal sealed partial class NetSecurityTelemetry : EventSource
 14    {
 15        private const string ActivitySourceName = "Experimental.System.Net.Security";
 16        private const string ActivityName = ActivitySourceName + ".TlsHandshake";
 17
 118        private static readonly ActivitySource s_activitySource = new ActivitySource(ActivitySourceName);
 19
 20        private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"
 121        public static readonly NetSecurityTelemetry Log = new NetSecurityTelemetry();
 22
 23        private IncrementingPollingCounter? _tlsHandshakeRateCounter;
 24        private PollingCounter? _totalTlsHandshakesCounter;
 25        private PollingCounter? _currentTlsHandshakesCounter;
 26        private PollingCounter? _failedTlsHandshakesCounter;
 27        private PollingCounter? _sessionsOpenCounter;
 28        private PollingCounter? _sessionsOpenTls10Counter;
 29        private PollingCounter? _sessionsOpenTls11Counter;
 30        private PollingCounter? _sessionsOpenTls12Counter;
 31        private PollingCounter? _sessionsOpenTls13Counter;
 32        private EventCounter? _handshakeDurationCounter;
 33        private EventCounter? _handshakeDurationTls10Counter;
 34        private EventCounter? _handshakeDurationTls11Counter;
 35        private EventCounter? _handshakeDurationTls12Counter;
 36        private EventCounter? _handshakeDurationTls13Counter;
 37
 38        private long _finishedTlsHandshakes; // Successfully and failed
 39        private long _startedTlsHandshakes;
 40        private long _failedTlsHandshakes;
 41        private long _sessionsOpen;
 42        private long _sessionsOpenTls10;
 43        private long _sessionsOpenTls11;
 44        private long _sessionsOpenTls12;
 45        private long _sessionsOpenTls13;
 46
 3147        public static bool AnyTelemetryEnabled() => Log.IsEnabled() || s_activitySource.HasListeners();
 48
 49        protected override void OnEventCommand(EventCommandEventArgs command)
 050        {
 051            if (command.Command == EventCommand.Enable)
 052            {
 053                _tlsHandshakeRateCounter ??= new IncrementingPollingCounter("tls-handshake-rate", this, () => Interlocke
 054                {
 055                    DisplayName = "TLS handshakes completed",
 056                    DisplayRateTimeScale = TimeSpan.FromSeconds(1)
 057                };
 58
 059                _totalTlsHandshakesCounter ??= new PollingCounter("total-tls-handshakes", this, () => Interlocked.Read(r
 060                {
 061                    DisplayName = "Total TLS handshakes completed"
 062                };
 63
 064                _currentTlsHandshakesCounter ??= new PollingCounter("current-tls-handshakes", this, () => -Interlocked.R
 065                {
 066                    DisplayName = "Current TLS handshakes"
 067                };
 68
 069                _failedTlsHandshakesCounter ??= new PollingCounter("failed-tls-handshakes", this, () => Interlocked.Read
 070                {
 071                    DisplayName = "Total TLS handshakes failed"
 072                };
 73
 074                _sessionsOpenCounter ??= new PollingCounter("all-tls-sessions-open", this, () => Interlocked.Read(ref _s
 075                {
 076                    DisplayName = "All TLS Sessions Active"
 077                };
 78
 079                _sessionsOpenTls10Counter ??= new PollingCounter("tls10-sessions-open", this, () => Interlocked.Read(ref
 080                {
 081                    DisplayName = "TLS 1.0 Sessions Active"
 082                };
 83
 084                _sessionsOpenTls11Counter ??= new PollingCounter("tls11-sessions-open", this, () => Interlocked.Read(ref
 085                {
 086                    DisplayName = "TLS 1.1 Sessions Active"
 087                };
 88
 089                _sessionsOpenTls12Counter ??= new PollingCounter("tls12-sessions-open", this, () => Interlocked.Read(ref
 090                {
 091                    DisplayName = "TLS 1.2 Sessions Active"
 092                };
 93
 094                _sessionsOpenTls13Counter ??= new PollingCounter("tls13-sessions-open", this, () => Interlocked.Read(ref
 095                {
 096                    DisplayName = "TLS 1.3 Sessions Active"
 097                };
 98
 099                _handshakeDurationCounter ??= new EventCounter("all-tls-handshake-duration", this)
 0100                {
 0101                    DisplayName = "TLS Handshake Duration",
 0102                    DisplayUnits = "ms"
 0103                };
 104
 0105                _handshakeDurationTls10Counter ??= new EventCounter("tls10-handshake-duration", this)
 0106                {
 0107                    DisplayName = "TLS 1.0 Handshake Duration",
 0108                    DisplayUnits = "ms"
 0109                };
 110
 0111                _handshakeDurationTls11Counter ??= new EventCounter("tls11-handshake-duration", this)
 0112                {
 0113                    DisplayName = "TLS 1.1 Handshake Duration",
 0114                    DisplayUnits = "ms"
 0115                };
 116
 0117                _handshakeDurationTls12Counter ??= new EventCounter("tls12-handshake-duration", this)
 0118                {
 0119                    DisplayName = "TLS 1.2 Handshake Duration",
 0120                    DisplayUnits = "ms"
 0121                };
 122
 0123                _handshakeDurationTls13Counter ??= new EventCounter("tls13-handshake-duration", this)
 0124                {
 0125                    DisplayName = "TLS 1.3 Handshake Duration",
 0126                    DisplayUnits = "ms"
 0127                };
 0128            }
 0129        }
 130
 131
 132        [Event(1, Level = EventLevel.Informational)]
 133        public void HandshakeStart(bool isServer, string targetHost)
 0134        {
 0135            Interlocked.Increment(ref _startedTlsHandshakes);
 136
 0137            if (IsEnabled(EventLevel.Informational, EventKeywords.None))
 0138            {
 0139                WriteEvent(eventId: 1, isServer, targetHost);
 0140            }
 0141        }
 142
 143        [Event(2, Level = EventLevel.Informational)]
 144        private void HandshakeStop(SslProtocols protocol)
 0145        {
 0146            if (IsEnabled(EventLevel.Informational, EventKeywords.None))
 0147            {
 0148                Debug.Assert(sizeof(SslProtocols) == 4);
 0149                WriteEvent(eventId: 2, (int)protocol);
 0150            }
 0151        }
 152
 153        [Event(3, Level = EventLevel.Error)]
 154        private void HandshakeFailed(bool isServer, double elapsedMilliseconds, string exceptionMessage)
 0155        {
 0156            WriteEvent(eventId: 3, isServer, elapsedMilliseconds, exceptionMessage);
 0157        }
 158
 159
 160        [NonEvent]
 161        public void HandshakeFailed(bool isServer, long startingTimestamp, string exceptionMessage)
 0162        {
 0163            Interlocked.Increment(ref _finishedTlsHandshakes);
 0164            Interlocked.Increment(ref _failedTlsHandshakes);
 165
 0166            if (IsEnabled(EventLevel.Error, EventKeywords.None))
 0167            {
 0168                HandshakeFailed(isServer, Stopwatch.GetElapsedTime(startingTimestamp).TotalMilliseconds, exceptionMessag
 0169            }
 170
 0171            HandshakeStop(SslProtocols.None);
 0172        }
 173
 174        [NonEvent]
 175        public void HandshakeCompleted(SslProtocols protocol, long startingTimestamp, bool connectionOpen)
 0176        {
 0177            Interlocked.Increment(ref _finishedTlsHandshakes);
 178
 0179            long dummy = 0;
 0180            ref long protocolSessionsOpen = ref dummy;
 0181            EventCounter? handshakeDurationCounter = null;
 182
 0183            Debug.Assert(Enum.GetValues<SslProtocols>()[^1] == SslProtocols.Tls13, "Make sure to add a counter for new S
 184
 0185            switch (protocol)
 186            {
 187#pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete
 188                case SslProtocols.Tls:
 0189                    protocolSessionsOpen = ref _sessionsOpenTls10;
 0190                    handshakeDurationCounter = _handshakeDurationTls10Counter;
 0191                    break;
 192
 193                case SslProtocols.Tls11:
 0194                    protocolSessionsOpen = ref _sessionsOpenTls11;
 0195                    handshakeDurationCounter = _handshakeDurationTls11Counter;
 0196                    break;
 197#pragma warning restore SYSLIB0039
 198
 199                case SslProtocols.Tls12:
 0200                    protocolSessionsOpen = ref _sessionsOpenTls12;
 0201                    handshakeDurationCounter = _handshakeDurationTls12Counter;
 0202                    break;
 203
 204                case SslProtocols.Tls13:
 0205                    protocolSessionsOpen = ref _sessionsOpenTls13;
 0206                    handshakeDurationCounter = _handshakeDurationTls13Counter;
 0207                    break;
 208            }
 209
 0210            if (connectionOpen)
 0211            {
 0212                Interlocked.Increment(ref protocolSessionsOpen);
 0213                Interlocked.Increment(ref _sessionsOpen);
 0214            }
 215
 0216            double duration = Stopwatch.GetElapsedTime(startingTimestamp).TotalMilliseconds;
 0217            handshakeDurationCounter?.WriteMetric(duration);
 0218            _handshakeDurationCounter?.WriteMetric(duration);
 219
 0220            HandshakeStop(protocol);
 0221        }
 222
 223        [NonEvent]
 224        public void ConnectionClosed(SslProtocols protocol)
 0225        {
 0226            long count = 0;
 227
 0228            switch (protocol)
 229            {
 230#pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete
 231                case SslProtocols.Tls:
 0232                    count = Interlocked.Decrement(ref _sessionsOpenTls10);
 0233                    break;
 234
 235                case SslProtocols.Tls11:
 0236                    count = Interlocked.Decrement(ref _sessionsOpenTls11);
 0237                    break;
 238#pragma warning restore SYSLIB0039
 239
 240                case SslProtocols.Tls12:
 0241                    count = Interlocked.Decrement(ref _sessionsOpenTls12);
 0242                    break;
 243
 244                case SslProtocols.Tls13:
 0245                    count = Interlocked.Decrement(ref _sessionsOpenTls13);
 0246                    break;
 247            }
 248
 0249            Debug.Assert(count >= 0);
 250
 0251            count = Interlocked.Decrement(ref _sessionsOpen);
 0252            Debug.Assert(count >= 0);
 0253        }
 254
 255
 256        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
 257                   Justification = EventSourceSuppressMessage)]
 258        [NonEvent]
 259        private unsafe void WriteEvent(int eventId, bool arg1, string? arg2)
 0260        {
 0261            arg2 ??= string.Empty;
 262
 0263            fixed (char* arg2Ptr = arg2)
 0264            {
 265                const int NumEventDatas = 2;
 0266                EventData* descrs = stackalloc EventData[NumEventDatas];
 267
 0268                descrs[0] = new EventData
 0269                {
 0270                    DataPointer = (IntPtr)(&arg1),
 0271                    Size = sizeof(int) // EventSource defines bool as a 32-bit type
 0272                };
 0273                descrs[1] = new EventData
 0274                {
 0275                    DataPointer = (IntPtr)(arg2Ptr),
 0276                    Size = (arg2.Length + 1) * sizeof(char)
 0277                };
 278
 0279                WriteEventCore(eventId, NumEventDatas, descrs);
 0280            }
 0281        }
 282
 283        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
 284                   Justification = EventSourceSuppressMessage)]
 285        [NonEvent]
 286        private unsafe void WriteEvent(int eventId, bool arg1, double arg2, string? arg3)
 0287        {
 0288            arg3 ??= string.Empty;
 289
 0290            fixed (char* arg3Ptr = arg3)
 0291            {
 292                const int NumEventDatas = 3;
 0293                EventData* descrs = stackalloc EventData[NumEventDatas];
 294
 0295                descrs[0] = new EventData
 0296                {
 0297                    DataPointer = (IntPtr)(&arg1),
 0298                    Size = sizeof(int) // EventSource defines bool as a 32-bit type
 0299                };
 0300                descrs[1] = new EventData
 0301                {
 0302                    DataPointer = (IntPtr)(&arg2),
 0303                    Size = sizeof(double)
 0304                };
 0305                descrs[2] = new EventData
 0306                {
 0307                    DataPointer = (IntPtr)(arg3Ptr),
 0308                    Size = (arg3.Length + 1) * sizeof(char)
 0309                };
 310
 0311                WriteEventCore(eventId, NumEventDatas, descrs);
 0312            }
 0313        }
 314
 315        [NonEvent]
 316        public static Activity? StartActivity(SslStream stream)
 0317        {
 0318            using Activity? activity = s_activitySource.StartActivity(ActivityName);
 0319            if (activity is not null)
 0320            {
 0321                activity.DisplayName = stream.IsServer ? "TLS server handshake" : $"TLS client handshake {stream.TargetH
 0322                if (activity.IsAllDataRequested && !stream.IsServer)
 0323                {
 0324                    activity.SetTag("server.address", stream.TargetHostName);
 0325                }
 0326            }
 0327            return activity;
 0328        }
 329
 330        [NonEvent]
 331        public static void StopActivity(Activity? activity, Exception? exception, SslStream stream)
 0332        {
 0333            if (activity?.IsAllDataRequested != true) return;
 334
 0335            SslProtocols protocol = stream.GetSslProtocolInternal();
 0336            (string? protocolName, string? protocolVersion) = GetNameAndVersionString(protocol);
 337
 0338            if (protocolName is not null)
 0339            {
 0340                Debug.Assert(protocolVersion is not null);
 0341                activity.SetTag("tls.protocol.name", protocolName);
 0342                activity.SetTag("tls.protocol.version", protocolVersion);
 0343            }
 344
 0345            if (exception is not null)
 0346            {
 0347                activity.SetStatus(ActivityStatusCode.Error);
 0348                activity.SetTag("error.type", exception.GetType().FullName);
 0349            }
 350
 0351            static (string?, string?) GetNameAndVersionString(SslProtocols protocol) => protocol switch
 0352            {
 0353#pragma warning disable 0618 // Ssl2, Ssl3 are deprecated.
 0354                SslProtocols.Ssl2 => ("ssl", "2"),
 0355                SslProtocols.Ssl3 => ("ssl", "3"),
 0356#pragma warning restore 0618
 0357#pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete.
 0358                SslProtocols.Tls => ("tls", "1"),
 0359                SslProtocols.Tls12 => ("tls", "1.2"),
 0360#pragma warning restore SYSLIB0039
 0361                SslProtocols.Tls13 => ("tls", "1.3"),
 0362                _ => (null, null)
 0363            };
 0364        }
 365    }
 366}
 367