< Summary

Information
Class: Ice.Internal.LoggerAdminLoggerI.Job
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/LoggerAdminLoggerI.cs
Tag: 71_18251537082
Line coverage
100%
Covered lines: 4
Uncovered lines: 0
Coverable lines: 4
Total lines: 206
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage
100%
Covered methods: 1
Total methods: 1
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)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    {
 18        var logMessage = new Ice.LogMessage(Ice.LogMessageType.PrintMessage, now(), "", message);
 19        _localLogger.print(message);
 20        log(logMessage);
 21    }
 22
 23    public void trace(string category, string message)
 24    {
 25        var logMessage = new Ice.LogMessage(Ice.LogMessageType.TraceMessage, now(), category, message);
 26        _localLogger.trace(category, message);
 27        log(logMessage);
 28    }
 29
 30    public void warning(string message)
 31    {
 32        var logMessage = new Ice.LogMessage(Ice.LogMessageType.WarningMessage, now(), "", message);
 33        _localLogger.warning(message);
 34        log(logMessage);
 35    }
 36
 37    public void error(string message)
 38    {
 39        var logMessage = new Ice.LogMessage(Ice.LogMessageType.ErrorMessage, now(), "", message);
 40        _localLogger.error(message);
 41        log(logMessage);
 42    }
 43
 44    public string getPrefix() => _localLogger.getPrefix();
 45
 46    public Ice.Logger cloneWithPrefix(string prefix) => _localLogger.cloneWithPrefix(prefix);
 47
 48    public Ice.Object getFacet() => _loggerAdmin;
 49
 50    public void destroy()
 51    {
 52        Thread thread = null;
 53        lock (_mutex)
 54        {
 55            if (_sendLogThread != null)
 56            {
 57                thread = _sendLogThread;
 58                _sendLogThread = null;
 59                _destroyed = true;
 60                Monitor.PulseAll(_mutex);
 61            }
 62
 63            if (_localLogger is FileLoggerI fileLogger)
 64            {
 65                fileLogger.destroy();
 66            }
 67        }
 68
 69        thread?.Join();
 70
 71        _loggerAdmin.destroy();
 72    }
 73
 74    internal LoggerAdminLoggerI(Ice.Properties props, Ice.Logger localLogger)
 75    {
 76        if (localLogger is LoggerAdminLoggerI wrapper)
 77        {
 78            _localLogger = wrapper.getLocalLogger();
 79        }
 80        else
 81        {
 82            _localLogger = localLogger;
 83        }
 84
 85        _loggerAdmin = new LoggerAdminI(props, this);
 86    }
 87
 88    internal Ice.Logger getLocalLogger() => _localLogger;
 89
 90    internal void log(Ice.LogMessage logMessage)
 91    {
 92        List<Ice.RemoteLoggerPrx> remoteLoggers = _loggerAdmin.log(logMessage);
 93
 94        if (remoteLoggers != null)
 95        {
 96            Debug.Assert(remoteLoggers.Count > 0);
 97
 98            lock (_mutex)
 99            {
 100                if (_sendLogThread == null)
 101                {
 102                    _sendLogThread = new Thread(new ThreadStart(run));
 103                    _sendLogThread.Name = "Ice.SendLogThread";
 104                    _sendLogThread.IsBackground = true;
 105                    _sendLogThread.Start();
 106                }
 107
 108                _jobQueue.Enqueue(new Job(remoteLoggers, logMessage));
 109                Monitor.PulseAll(_mutex);
 110            }
 111        }
 112    }
 113
 114    private static long now()
 115    {
 116        TimeSpan t = DateTime.UtcNow - _unixEpoch;
 117        return Convert.ToInt64(t.TotalMilliseconds * 1000);
 118    }
 119
 120    private void run()
 121    {
 122        if (_loggerAdmin.getTraceLevel() > 1)
 123        {
 124            _localLogger.trace(_traceCategory, "send log thread started");
 125        }
 126
 127        while (true)
 128        {
 129            Job job = null;
 130            lock (_mutex)
 131            {
 132                while (!_destroyed && _jobQueue.Count == 0)
 133                {
 134                    Monitor.Wait(_mutex);
 135                }
 136
 137                if (_destroyed)
 138                {
 139                    break; // for(;;)
 140                }
 141
 142                Debug.Assert(_jobQueue.Count > 0);
 143                job = _jobQueue.Dequeue();
 144            }
 145
 146            foreach (RemoteLoggerPrx p in job.remoteLoggers)
 147            {
 148                if (_loggerAdmin.getTraceLevel() > 1)
 149                {
 150                    _localLogger.trace(_traceCategory, $"sending log message to '{p}'");
 151                }
 152
 153                //
 154                // p is a proxy associated with the _sendLogCommunicator
 155                //
 156                _ = performLogAsync(p, job.logMessage);
 157            }
 158        }
 159
 160        if (_loggerAdmin.getTraceLevel() > 1)
 161        {
 162            _localLogger.trace(_traceCategory, "send log thread completed");
 163        }
 164
 165        async Task performLogAsync(RemoteLoggerPrx logger, LogMessage logMessage)
 166        {
 167            try
 168            {
 169                await logger.logAsync(logMessage).ConfigureAwait(false);
 170                if (_loggerAdmin.getTraceLevel() > 1)
 171                {
 172                    _localLogger.trace(_traceCategory, $"log on '{logger}' completed successfully");
 173                }
 174            }
 175            catch (Ice.CommunicatorDestroyedException)
 176            {
 177                // expected if there are outstanding calls during communicator destruction
 178            }
 179            catch (Ice.LocalException ex)
 180            {
 181                _loggerAdmin.deadRemoteLogger(logger, _localLogger, ex, "log");
 182            }
 183        }
 184    }
 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
 198    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;
 203    private readonly Queue<Job> _jobQueue = new Queue<Job>();
 204    private const string _traceCategory = "Admin.Logger";
 205    private readonly object _mutex = new();
 206}