Skip to content
Snippets Groups Projects
Select Git revision
  • c934320f53e58387e701447dab23bea202c084e7
  • master default protected
  • gitkeep
  • dev protected
  • Issue/2309-docs
  • Hotfix/2097-fixTimeFormat
  • Issue/1910-MigrationtoNET6.0
  • Sprint/2022-01
  • Sprint/2021-05
  • Product/1188-LoggingExtended
  • Topic/1221-LogginExtendedNew
  • Sprint/2021-03
  • Product/1287-dotnet5Sharepoint
  • Topic/1334-dotnet5migration
  • Topic/1221-LoggingExtended
  • Sprint/2021-01
  • Product/407-net5migration
  • Topic/1226-loggingLibraryMigration
  • v2.2.2
  • v2.2.1
  • v2.2.0
  • v2.1.0
  • v2.0.0
  • v1.3.0
  • v1.2.0
  • v1.1.0
  • v1.0.1
  • v1.0.0
28 results

CoscineLogger.cs

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    CoscineLogger.cs 16.78 KiB
    using NLog;
    using System;
    using System.Diagnostics;
    using System.Text;
    using NLog.Targets;
    using Consul;
    using LogLevel = NLog.LogLevel;
    using System.Text.RegularExpressions;
    using NLog.Config;
    using Microsoft.Extensions.Logging;
    using NLog.LayoutRenderers;
    
    namespace Coscine.Logging
    {
    
        public class CoscineLogger
        {
            private readonly Microsoft.Extensions.Logging.ILogger _logger;
    
            private const LogType defaultLogType = LogType.Low;
    
            private static bool[] activeLoglevels = new bool[Enum.GetNames(typeof(LogType)).Length];
    
            // Keys for the database string
            private const string DbDataSourceKey = "coscine/global/db_data_source";
            private const string DbNameKey = "coscine/global/db_name";
            private const string DbUserIdKey = "coscine/global/db_user_id";
            private const string DbPasswordKey = "coscine/global/db_password";
    
            // path for the file logger
            private const string FileLoggerPath = "coscine/global/logging/fileloggerpath";
    
            // keys for the loglevels
            private const string LogLevelKeyDebug = "coscine/global/logging/levels/debug";
            private const string LogLevelKeyLow = "coscine/global/logging/levels/low";
            private const string LogLevelKeyMedium = "coscine/global/logging/levels/medium";
            private const string LogLevelKeyHigh = "coscine/global/logging/levels/high";
            private const string LogLevelKeyCritical = "coscine/global/logging/levels/critical";
            private const string LogLevelKeyAnalytics = "coscine/global/logging/levels/analytics";
            private const string LogLevelKeyReporting = "coscine/global/logging/levels/reporting";
    
    
            public CoscineLogger(Microsoft.Extensions.Logging.ILogger logger)
            {
                UpdateActiveLogs();
                _logger = logger;
            }
    
            public static void SetConfig()
            {
                LayoutRenderer.Register<LogLevelLayoutRenderer>("CoscineLogLevel");
    
                var config = new LoggingConfiguration();
    
    
                var targetFileLogger = new FileTarget
                {
                    Name = "fileTarget",
                    FileName = GetStringFromConsul(FileLoggerPath),
                    Layout = "${date:universalTime=true}|${mdlc:ClientTimeStamp}|${CoscineLogLevel}|${message}|${mdlc:User}|${mdlc:Uri}|${machinename}|${activityid}|${mdlc:Status}|${callsite}|${exception:format=message}${exception:format=stackTrace}"
                };
    
    
                var targetDatabase = new DatabaseTarget
                {
                    Name = "database",
                    ConnectionString = CoscineLogger.GetDbConnectionString(),
                    CommandText = @"insert into dbo.Log ( [ServerTimeStamp], [ClientTimeStamp], [LogLevel], [Message], [Stacktrace], [UserId], [URI], [Server], [CorrolationId], [Status], [Source]) 
                values (
                CAST( @serverTimeStamp AS DATETIME2),
                CASE WHEN @clientTimeStamp = '' THEN NULL ELSE CAST( @clientTimeStamp AS DATETIME2) END, 
                @level,
                @message, 
                @stacktrace, 
                CASE WHEN @userId = '' THEN NULL ELSE convert(uniqueidentifier, @userId) END, 
                @uri, 
                @server, 
                CASE WHEN @corrolationId = '' THEN NULL ELSE convert(uniqueidentifier, @corrolationId) END, 
                @status, 
                @source)"
    
                };
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@serverTimeStamp", new NLog.Layouts.SimpleLayout("${date:universalTime=true}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@clientTimeStamp", new NLog.Layouts.SimpleLayout("${mdlc:ClientTimeStamp}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@level", new NLog.Layouts.SimpleLayout("${CoscineLogLevel}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@message", new NLog.Layouts.SimpleLayout("${message}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@stackTrace", new NLog.Layouts.SimpleLayout("${exception:format=message}${exception:format=stackTrace}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@userId", new NLog.Layouts.SimpleLayout("${mdlc:User}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@uri", new NLog.Layouts.SimpleLayout("${mdlc:Uri}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@server", new NLog.Layouts.SimpleLayout("${machinename}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@corrolationId", new NLog.Layouts.SimpleLayout("${activityid}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@status", new NLog.Layouts.SimpleLayout("${mdlc:Status}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@source", new NLog.Layouts.SimpleLayout("${callsite}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@type", new NLog.Layouts.SimpleLayout("${exception:format=type}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@innerException", new NLog.Layouts.SimpleLayout("${exception:format=:innerFormat=ShortType,Message,Method:MaxInnerExceptionLevel=1:InnerExceptionSeparator=}")));
                targetDatabase.Parameters.Add(new DatabaseParameterInfo("@additionalInfo", new NLog.Layouts.SimpleLayout("${message}")));
    
                var targetConsole = new NLog.Targets.ConsoleTarget
                {
                    Name = "console",
                    Layout = "${date:universalTime=true}|${mdlc:ClientTimeStamp}|${CoscineLogLevel}|${message}|${mdlc:User}|${mdlc:Uri}|${machinename}|${activityid}|${mdlc:Status}|${callsite}|${exception:format=message}${exception:format=stackTrace}"
                };
    
    
                config.AddTarget("fileLogger", targetFileLogger);
                config.AddTarget("databaseLogger", targetDatabase);
                config.AddTarget("consoleLogger", targetConsole);
    
    
                var blockAllDebug = new LoggingRule("blockAllDebug");
                blockAllDebug.SetLoggingLevels(LogLevel.Debug, LogLevel.Debug);
                blockAllDebug.LoggerNamePattern = "*";
    
                var blockAllTrace = new LoggingRule("blockAllTrace");
                blockAllTrace.SetLoggingLevels(LogLevel.Trace, LogLevel.Trace);
                blockAllTrace.LoggerNamePattern = "*";
    
                var blockAllWarning = new LoggingRule("blockAllWarning");
                blockAllWarning.SetLoggingLevels(LogLevel.Warn, LogLevel.Warn);
                blockAllWarning.LoggerNamePattern = "*";
    
                var blockAllError = new LoggingRule("blockAllError");
                blockAllError.SetLoggingLevels(LogLevel.Error, LogLevel.Error);
                blockAllError.LoggerNamePattern = "*";
    
                var blockAllFatal = new LoggingRule("blockAllFatal");
                blockAllFatal.SetLoggingLevels(LogLevel.Fatal, LogLevel.Fatal);
                blockAllFatal.LoggerNamePattern = "*";
    
                var blockAllInformation = new LoggingRule("blockAllInformation");
                blockAllInformation.SetLoggingLevels(LogLevel.Info, LogLevel.Info);
                blockAllInformation.LoggerNamePattern = "*";
    
    
                var ruleFileLogger = new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, targetFileLogger);
                var ruleConsole = new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, targetConsole);
                var ruleDatabase = new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, targetDatabase);
    
                config.LoggingRules.Add(blockAllDebug);
                config.LoggingRules.Add(blockAllTrace);
                config.LoggingRules.Add(blockAllWarning);
                config.LoggingRules.Add(blockAllError);
                config.LoggingRules.Add(blockAllFatal);
                config.LoggingRules.Add(blockAllInformation);
    
                config.LoggingRules.Add(ruleFileLogger);
                config.LoggingRules.Add(ruleConsole);
                config.LoggingRules.Add(ruleDatabase);
    
                LogManager.Configuration = config;
    
                UpdateActiveLogs();
            }
    
    
            public void Log()
            {
                Log(defaultLogType, null, null, null);
            }
    
            public void Log(string message)
            {
                Log(defaultLogType, null, message, null);
            }
    
            public void Log(Exception exception)
            {
                Log(defaultLogType, null, null, exception);
            }
    
            public void Log(string message, Exception exception)
            {
                Log(defaultLogType, null, message, exception);
            }
    
            public void Log(Type context)
            {
                Log(defaultLogType, context, null, null);
            }
    
            public void Log(Type context, string message)
            {
                Log(defaultLogType, context, message, null);
            }
    
            public void Log(Type context, Exception exception)
            {
                Log(defaultLogType, context, null, exception);
            }
    
            public void Log(Type context, string message, Exception exception)
            {
                Log(defaultLogType, context, message, exception);
            }
    
            public void Log(LogType messageType)
            {
                Log(messageType, null, null, null);
            }
    
            public void Log(LogType messageType, Type context)
            {
                Log(messageType, context, null, null);
            }
    
            public void Log(LogType messageType, string message)
            {
                Log(messageType, null, message, null);
            }
    
            public void Log(LogType messageType, Exception exception)
            {
                Log(messageType, null, null, exception);
            }
    
            public void Log(LogType messageType, Type context, string message)
            {
                Log(messageType, context, message, null);
            }
    
            public void Log(LogType messageType, Type context, Exception exception)
            {
                Log(messageType, context, null, exception);
            }
    
            public void Log(LogType messageType, string message, Exception exception)
            {
                Log(messageType, null, message, exception);
            }
    
            public void Log(LogType messageType, Type context, string message, Exception exception)
            {
                UpdateActiveLogs();
    
                if (!activeLoglevels[(int)messageType])
                {
                    return;
                }
    
                Microsoft.Extensions.Logging.LogLevel logLevel;
    
                switch (messageType)
                {
                    case LogType.Debug:
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Debug;
                        break;
                    case LogType.Low:
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Trace;
                        break;
                    case LogType.Medium:
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Warning;
                        break;
                    case LogType.High:
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Error;
                        break;
                    case LogType.Critical:
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Critical;
                        break;
                    case LogType.Analytics:
                        SetAnalytics(true);
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Information;
                        break;
                    case LogType.Reporting:
                        SetReporting(true);
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Information;
                        break;
                    default:
                        messageType = LogType.Low;
                        logLevel = Microsoft.Extensions.Logging.LogLevel.Trace;
                        break;
                }
    
                _logger.Log(logLevel, exception, message);
    
            }
    
    
            public static void SetUserId(string userId = "00000000-0000-0000-0000-000000000000")
            {
                if (IsGuid(userId))
                {
                    MappedDiagnosticsLogicalContext.Set("User", userId);
                }
                else
                {
                    MappedDiagnosticsLogicalContext.Set("User", "");
                }
            }
    
            public static void SetUserId(Guid userId)
            {
                CoscineLogger.SetUserId(userId.ToString());
            }
    
            public static void SetAnalytics(bool active)
            {
                var value = active ? "true" : "false";
                MappedDiagnosticsLogicalContext.Set("Analytics", value);
            }
    
            public static void SetReporting(bool active)
            {
                var value = active ? "true" : "false";
                MappedDiagnosticsLogicalContext.Set("Reporting", value);
            }
    
            public static void SetUri(string uri = "")
            {
                MappedDiagnosticsLogicalContext.Set("Uri", uri);
            }
    
            public static void SetCorrolationId(string corrolationId = "00000000-0000-0000-0000-000000000000")
            {
                if (IsGuid(corrolationId))
                {
                    Trace.CorrelationManager.ActivityId = new Guid(corrolationId);
                }
                else
                {
                    Trace.CorrelationManager.ActivityId = new Guid("00000000-0000-0000-0000-000000000000");
                }
            }
    
            public static void SetCorrolationId()
            {
                Trace.CorrelationManager.ActivityId = Guid.NewGuid();
            }
    
            public static void SetCorrolationId(Guid corrolationId)
            {
                CoscineLogger.SetCorrolationId(corrolationId.ToString());
            }
    
            public static void SetStatus(string status = "")
            {
                MappedDiagnosticsLogicalContext.Set("Status", status);
            }
    
            public static void SetClientTimeStamp(string clientTimeStamp = "")
            {
                MappedDiagnosticsLogicalContext.Set("ClientTimeStamp", clientTimeStamp);
            }
    
            private static bool IsGuid(string guid)
            {
                var match = Regex.Match(guid, @"^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$",
                RegexOptions.IgnoreCase);
                return match.Success;
            }
    
            private static void UpdateActiveLogs()
            {
                activeLoglevels[(int)LogType.Debug] = !GetStringFromConsul(LogLevelKeyDebug, "0").Equals("0");
                activeLoglevels[(int)LogType.Low] = !GetStringFromConsul(LogLevelKeyLow, "0").Equals("0");
                activeLoglevels[(int)LogType.Medium] = !GetStringFromConsul(LogLevelKeyMedium, "0").Equals("0");
                activeLoglevels[(int)LogType.High] = !GetStringFromConsul(LogLevelKeyHigh, "1").Equals("0");
                activeLoglevels[(int)LogType.Critical] = !GetStringFromConsul(LogLevelKeyCritical, "1").Equals("0");
                activeLoglevels[(int)LogType.Analytics] = !GetStringFromConsul(LogLevelKeyAnalytics, "0").Equals("0");
                activeLoglevels[(int)LogType.Reporting] = !GetStringFromConsul(LogLevelKeyReporting, "0").Equals("0");
    
                var config = LogManager.Configuration;
                config.FindRuleByName("blockAllInformation").Final = !activeLoglevels[(int)LogType.Analytics] && !activeLoglevels[(int)LogType.Reporting];
                config.FindRuleByName("blockAllDebug").Final = !activeLoglevels[(int)LogType.Debug];
                config.FindRuleByName("blockAllTrace").Final = !activeLoglevels[(int)LogType.Low];
                config.FindRuleByName("blockAllWarning").Final = !activeLoglevels[(int)LogType.Medium];
                config.FindRuleByName("blockAllError").Final = !activeLoglevels[(int)LogType.High];
                config.FindRuleByName("blockAllFatal").Final = !activeLoglevels[(int)LogType.Critical];
    
                LogManager.Configuration = config;
                LogManager.ReconfigExistingLoggers();
            }
    
            public static bool LogLevelIsActivated(LogType logType)
            {
                return activeLoglevels[(int)logType];
            }
    
            private static string GetDbConnectionString()
            {
                var dbDataSource = GetStringFromConsul(DbDataSourceKey);
                var dbDatabase = GetStringFromConsul(DbNameKey);
                var dbUserId = GetStringFromConsul(DbUserIdKey);
                var dbPassword = GetStringFromConsul(DbPasswordKey);
                return $"Data Source={dbDataSource}; Database={dbDatabase}; User Id={dbUserId}; Password={dbPassword};";
            }
    
            private static string GetStringFromConsul(string key)
            {
                using (var client = new ConsulClient())
                {
                    var getPair = client.KV.Get(key);
    
                    getPair.Wait();
    
                    if (getPair.Result.Response?.Value != null)
                    {
                        var value = getPair.Result.Response.Value;
                        return Encoding.UTF8.GetString(value, 0, value.Length);
                    }
                    else
                    {
                        // TODO: Add logging that key has not been found
                        return null;
                    }
                }
            }
    
            private static string GetStringFromConsul(string key, string defaultValue)
            {
                var value = GetStringFromConsul(key);
                if(value == null)
                {
                    // TODO: Add logging that default value has been used
                    return defaultValue;
                }
                return value;
            }
        }
    }