< Summary

Information
Class: Ice.Internal.LoggerAdminLoggerI
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/LoggerAdminLoggerI.cs
Tag: 71_18251537082
Line coverage
88%
Covered lines: 77
Uncovered lines: 10
Coverable lines: 87
Total lines: 206
Line coverage: 88.5%
Branch coverage
82%
Covered branches: 23
Total branches: 28
Branch coverage: 82.1%
Method coverage
100%
Covered methods: 16
Total methods: 16
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
print(...)100%11100%
trace(...)100%11100%
warning(...)100%11100%
error(...)100%11100%
getPrefix()100%11100%
cloneWithPrefix(...)100%11100%
getFacet()100%11100%
destroy()100%66100%
.ctor(...)50%2.01287.5%
getLocalLogger()100%11100%
log(...)100%44100%
now()100%11100%
run()78.57%15.081482.35%
performLogAsync()50%2.86240%
.ctor(...)100%11100%
.cctor()100%11100%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/LoggerAdminLoggerI.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Diagnostics;
 4
 5namespace Ice.Internal;
 6
 7internal interface LoggerAdminLogger : Logger
 8{
 9    Ice.Object getFacet();
 10
 11    void destroy();
 12}
 13
 14internal sealed class LoggerAdminLoggerI : LoggerAdminLogger
 15{
 16    public void print(string message)
 17    {
 118        var logMessage = new Ice.LogMessage(Ice.LogMessageType.PrintMessage, now(), "", message);
 119        _localLogger.print(message);
 120        log(logMessage);
 121    }
 22
 23    public void trace(string category, string message)
 24    {
 125        var logMessage = new Ice.LogMessage(Ice.LogMessageType.TraceMessage, now(), category, message);
 126        _localLogger.trace(category, message);
 127        log(logMessage);
 128    }
 29
 30    public void warning(string message)
 31    {
 132        var logMessage = new Ice.LogMessage(Ice.LogMessageType.WarningMessage, now(), "", message);
 133        _localLogger.warning(message);
 134        log(logMessage);
 135    }
 36
 37    public void error(string message)
 38    {
 139        var logMessage = new Ice.LogMessage(Ice.LogMessageType.ErrorMessage, now(), "", message);
 140        _localLogger.error(message);
 141        log(logMessage);
 142    }
 43
 144    public string getPrefix() => _localLogger.getPrefix();
 45
 146    public Ice.Logger cloneWithPrefix(string prefix) => _localLogger.cloneWithPrefix(prefix);
 47
 148    public Ice.Object getFacet() => _loggerAdmin;
 49
 50    public void destroy()
 51    {
 152        Thread thread = null;
 153        lock (_mutex)
 54        {
 155            if (_sendLogThread != null)
 56            {
 157                thread = _sendLogThread;
 158                _sendLogThread = null;
 159                _destroyed = true;
 160                Monitor.PulseAll(_mutex);
 61            }
 62
 163            if (_localLogger is FileLoggerI fileLogger)
 64            {
 165                fileLogger.destroy();
 66            }
 167        }
 68
 169        thread?.Join();
 70
 171        _loggerAdmin.destroy();
 172    }
 73
 174    internal LoggerAdminLoggerI(Ice.Properties props, Ice.Logger localLogger)
 75    {
 176        if (localLogger is LoggerAdminLoggerI wrapper)
 77        {
 078            _localLogger = wrapper.getLocalLogger();
 79        }
 80        else
 81        {
 182            _localLogger = localLogger;
 83        }
 84
 185        _loggerAdmin = new LoggerAdminI(props, this);
 186    }
 87
 188    internal Ice.Logger getLocalLogger() => _localLogger;
 89
 90    internal void log(Ice.LogMessage logMessage)
 91    {
 192        List<Ice.RemoteLoggerPrx> remoteLoggers = _loggerAdmin.log(logMessage);
 93
 194        if (remoteLoggers != null)
 95        {
 96            Debug.Assert(remoteLoggers.Count > 0);
 97
 198            lock (_mutex)
 99            {
 1100                if (_sendLogThread == null)
 101                {
 1102                    _sendLogThread = new Thread(new ThreadStart(run));
 1103                    _sendLogThread.Name = "Ice.SendLogThread";
 1104                    _sendLogThread.IsBackground = true;
 1105                    _sendLogThread.Start();
 106                }
 107
 1108                _jobQueue.Enqueue(new Job(remoteLoggers, logMessage));
 1109                Monitor.PulseAll(_mutex);
 1110            }
 111        }
 1112    }
 113
 114    private static long now()
 115    {
 1116        TimeSpan t = DateTime.UtcNow - _unixEpoch;
 1117        return Convert.ToInt64(t.TotalMilliseconds * 1000);
 118    }
 119
 120    private void run()
 121    {
 1122        if (_loggerAdmin.getTraceLevel() > 1)
 123        {
 0124            _localLogger.trace(_traceCategory, "send log thread started");
 125        }
 126
 127        while (true)
 128        {
 1129            Job job = null;
 1130            lock (_mutex)
 131            {
 1132                while (!_destroyed && _jobQueue.Count == 0)
 133                {
 1134                    Monitor.Wait(_mutex);
 135                }
 136
 1137                if (_destroyed)
 138                {
 1139                    break; // for(;;)
 140                }
 141
 142                Debug.Assert(_jobQueue.Count > 0);
 1143                job = _jobQueue.Dequeue();
 1144            }
 145
 1146            foreach (RemoteLoggerPrx p in job.remoteLoggers)
 147            {
 1148                if (_loggerAdmin.getTraceLevel() > 1)
 149                {
 0150                    _localLogger.trace(_traceCategory, $"sending log message to '{p}'");
 151                }
 152
 153                //
 154                // p is a proxy associated with the _sendLogCommunicator
 155                //
 1156                _ = performLogAsync(p, job.logMessage);
 157            }
 158        }
 159
 1160        if (_loggerAdmin.getTraceLevel() > 1)
 161        {
 0162            _localLogger.trace(_traceCategory, "send log thread completed");
 163        }
 164
 165        async Task performLogAsync(RemoteLoggerPrx logger, LogMessage logMessage)
 166        {
 167            try
 168            {
 1169                await logger.logAsync(logMessage).ConfigureAwait(false);
 1170                if (_loggerAdmin.getTraceLevel() > 1)
 171                {
 0172                    _localLogger.trace(_traceCategory, $"log on '{logger}' completed successfully");
 173                }
 1174            }
 0175            catch (Ice.CommunicatorDestroyedException)
 176            {
 177                // expected if there are outstanding calls during communicator destruction
 0178            }
 0179            catch (Ice.LocalException ex)
 180            {
 0181                _loggerAdmin.deadRemoteLogger(logger, _localLogger, ex, "log");
 0182            }
 1183        }
 1184    }
 185
 186    private class Job
 187    {
 1188        internal Job(List<Ice.RemoteLoggerPrx> r, Ice.LogMessage l)
 189        {
 1190            remoteLoggers = r;
 1191            logMessage = l;
 1192        }
 193
 194        internal readonly List<Ice.RemoteLoggerPrx> remoteLoggers;
 195        internal readonly Ice.LogMessage logMessage;
 196    }
 197
 1198    private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
 199    private readonly Ice.Logger _localLogger;
 200    private readonly LoggerAdminI _loggerAdmin;
 201    private bool _destroyed;
 202    private Thread _sendLogThread;
 1203    private readonly Queue<Job> _jobQueue = new Queue<Job>();
 204    private const string _traceCategory = "Admin.Logger";
 1205    private readonly object _mutex = new();
 206}