-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathNullableLogger.cs
131 lines (110 loc) · 3.63 KB
/
NullableLogger.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#nullable enable
using System;
using System.Collections.Generic;
using HBS.Logging;
using JetBrains.Annotations;
using ModTek.Features.Logging;
namespace ModTek.Public;
[HarmonyPatch]
[PublicAPI]
public sealed class NullableLogger
{
// instantiation
[PublicAPI]
public static NullableLogger GetLogger(string name, LogLevel? defaultLogLevel = null)
{
lock (s_loggers)
{
if (!s_loggers.TryGetValue(name, out var logger))
{
logger = new(name, defaultLogLevel);
s_loggers[name] = logger;
}
return logger;
}
}
// useful "constants"
[PublicAPI]
public static LogLevel TraceLogLevel => (LogLevel)LogLevelExtension.TraceLogLevel;
// tracking
private static readonly SortedList<string, NullableLogger> s_loggers = new();
[HarmonyPatch(typeof(Logger.LogImpl), nameof(Logger.LogImpl.Level), MethodType.Setter)]
[HarmonyPostfix]
[HarmonyWrapSafe]
private static void LogImpl_set_Level_Postfix()
{
lock (s_loggers)
{
foreach (var modLogger in s_loggers.Values)
{
modLogger.RefreshLogLevel();
}
}
}
// instantiation
private readonly Logger.LogImpl _logImpl;
private NullableLogger(string name, LogLevel? defaultLogLevel)
{
_logImpl = (Logger.LogImpl)(
defaultLogLevel == null
? Logger.GetLogger(name)
: Logger.GetLogger(name, defaultLogLevel.Value)
);
RefreshLogLevel();
}
// logging
[PublicAPI] public ILog Log => _logImpl;
[PublicAPI] public ILevel? Trace { get; private set; }
[PublicAPI] public ILevel? Debug { get; private set; }
[PublicAPI] public ILevel? Info { get; private set; }
[PublicAPI] public ILevel? Warning { get; private set; }
[PublicAPI] public ILevel? Error { get; private set; }
private void RefreshLogLevel()
{
var lowerLevelEnabled = false;
Trace = SyncLevelLogger(ref lowerLevelEnabled, TraceLogLevel, Trace);
Debug = SyncLevelLogger(ref lowerLevelEnabled, LogLevel.Debug, Debug);
Info = SyncLevelLogger(ref lowerLevelEnabled, LogLevel.Log, Info);
Warning = SyncLevelLogger(ref lowerLevelEnabled, LogLevel.Warning, Warning);
Error = SyncLevelLogger(ref lowerLevelEnabled, LogLevel.Error, Error);
}
private ILevel? SyncLevelLogger(ref bool lowerLevelEnabled, LogLevel logLevel, ILevel? logger)
{
if (lowerLevelEnabled || _logImpl.IsEnabledFor(logLevel))
{
lowerLevelEnabled = true;
return logger ?? new LevelLogger(logLevel, _logImpl.Name);
}
return null;
}
// logging
[PublicAPI]
public interface ILevel
{
[PublicAPI] void Log(Exception e);
[PublicAPI] void Log(string message);
[PublicAPI] void Log(string message, Exception e);
}
private sealed class LevelLogger : ILevel
{
private readonly LogLevel _level;
private readonly string _loggerName;
internal LevelLogger(LogLevel level, string loggerName)
{
_level = level;
_loggerName = loggerName;
}
public void Log(Exception e)
{
LoggingFeature.LogAtLevel(_loggerName, _level, null, e, null);
}
public void Log(string message)
{
LoggingFeature.LogAtLevel(_loggerName, _level, message, null, null);
}
public void Log(string message, Exception e)
{
LoggingFeature.LogAtLevel(_loggerName, _level, message, e, null);
}
}
}