| | 1 | | // Copyright (c) ZeroC, Inc. |
| | 2 | |
|
| | 3 | | using IceRpc.Transports; |
| | 4 | |
|
| | 5 | | namespace IceRpc.Internal; |
| | 6 | |
|
| | 7 | | /// <summary>Provides a log decorator for protocol connections.</summary> |
| | 8 | | internal class MetricsProtocolConnectionDecorator : IProtocolConnection |
| | 9 | | { |
| | 10 | | private readonly bool _connectStarted; |
| | 11 | | private readonly IProtocolConnection _decoratee; |
| | 12 | | private bool _isConnected; |
| | 13 | | private bool _isShutdown; |
| | 14 | | private readonly Metrics _metrics; |
| | 15 | |
|
| | 16 | | public async Task<(TransportConnectionInformation ConnectionInformation, Task ShutdownRequested)> ConnectAsync( |
| | 17 | | CancellationToken cancellationToken) |
| 280 | 18 | | { |
| 280 | 19 | | if (!_connectStarted) |
| 164 | 20 | | { |
| 164 | 21 | | _metrics.ConnectStart(); |
| 164 | 22 | | } |
| | 23 | | try |
| 280 | 24 | | { |
| 280 | 25 | | (TransportConnectionInformation connectionInformation, Task shutdownRequested) = |
| 280 | 26 | | await _decoratee.ConnectAsync(cancellationToken).ConfigureAwait(false); |
| 229 | 27 | | _metrics.ConnectSuccess(); |
| 229 | 28 | | _isConnected = true; |
| 229 | 29 | | return (connectionInformation, shutdownRequested); |
| | 30 | | } |
| 51 | 31 | | catch |
| 51 | 32 | | { |
| 51 | 33 | | _metrics.ConnectionFailure(); |
| 51 | 34 | | throw; |
| | 35 | | } |
| | 36 | | finally |
| 280 | 37 | | { |
| 280 | 38 | | _metrics.ConnectStop(); |
| 280 | 39 | | } |
| 229 | 40 | | } |
| | 41 | |
|
| | 42 | | public async ValueTask DisposeAsync() |
| 280 | 43 | | { |
| 280 | 44 | | await _decoratee.DisposeAsync().ConfigureAwait(false); |
| 280 | 45 | | if (_isConnected) |
| 229 | 46 | | { |
| 229 | 47 | | if (!_isShutdown) |
| 149 | 48 | | { |
| | 49 | | // shutdown failed or didn't call shutdown at all. |
| 149 | 50 | | _metrics.ConnectionFailure(); |
| 149 | 51 | | } |
| 229 | 52 | | _metrics.ConnectionDisconnected(); |
| 229 | 53 | | } |
| 280 | 54 | | } |
| | 55 | |
|
| | 56 | | public Task<IncomingResponse> InvokeAsync(OutgoingRequest request, CancellationToken cancellationToken) => |
| 160 | 57 | | _decoratee.InvokeAsync(request, cancellationToken); |
| | 58 | |
|
| | 59 | | public async Task ShutdownAsync(CancellationToken cancellationToken) |
| 101 | 60 | | { |
| 101 | 61 | | await _decoratee.ShutdownAsync(cancellationToken).ConfigureAwait(false); |
| 80 | 62 | | _isShutdown = true; |
| 80 | 63 | | } |
| | 64 | |
|
| | 65 | | /// <summary>A protocol connection decorator to log connection metrics.</summary> |
| | 66 | | /// <param name="decoratee">The protocol connection decoratee.</param> |
| | 67 | | /// <param name="metrics">The metrics object used to log the metrics.</param> |
| | 68 | | /// <param name="connectStarted">Whether or not the ConnectStart events has be already logged. For server connection |
| | 69 | | /// the event is logged from a separate <see cref="Server.IConnector"/> decorator.</param> |
| 280 | 70 | | internal MetricsProtocolConnectionDecorator( |
| 280 | 71 | | IProtocolConnection decoratee, |
| 280 | 72 | | Metrics metrics, |
| 280 | 73 | | bool connectStarted) |
| 280 | 74 | | { |
| 280 | 75 | | _connectStarted = connectStarted; |
| 280 | 76 | | _decoratee = decoratee; |
| 280 | 77 | | _metrics = metrics; |
| 280 | 78 | | } |
| | 79 | | } |