File size: 6,073 Bytes
7b715bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
Copyright 2011 Google Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using Google.Apis.Util;
using System;
using System.Globalization;

namespace Google.Apis.Logging
{
    /// <summary>
    /// An abstract base logger, upon which real loggers may be built.
    /// </summary>
    public abstract class BaseLogger : ILogger
    {
        // Does not match gRPC datetime log format, which is "MMdd HH:mm:ss.ffffff"
        private const string DateTimeFormatString = "yyyy-MM-dd HH:mm:ss.ffffff";

        /// <summary>
        /// Construct a <see cref="BaseLogger"/>. 
        /// </summary>
        /// <param name="minimumLogLevel">Logging will be enabled at this level and all higher levels.</param>
        /// <param name="clock">The <see cref="IClock"/> to use to timestamp log entries.</param>
        /// <param name="forType">The type from which entries are being logged. May be <c>null</c>.</param>
        protected BaseLogger(LogLevel minimumLogLevel, IClock clock, Type forType)
        {
            MinimumLogLevel = minimumLogLevel;
            IsDebugEnabled = minimumLogLevel <= LogLevel.Debug;
            IsInfoEnabled = minimumLogLevel <= LogLevel.Info;
            IsWarningEnabled = minimumLogLevel <= LogLevel.Warning;
            IsErrorEnabled = minimumLogLevel <= LogLevel.Error;
            Clock = clock ?? SystemClock.Default;
            LoggerForType = forType;
            if (forType != null)
            {
                var namespaceStr = forType.Namespace ?? "";
                if (namespaceStr.Length > 0)
                {
                    namespaceStr += ".";
                }
                _loggerForTypeString = namespaceStr + forType.Name + " ";
            }
            else
            {
                _loggerForTypeString = "";
            }
        }

        private readonly string _loggerForTypeString;

        /// <summary>
        /// The <see cref="IClock"/> being used to timestamp log entries. 
        /// </summary>
        public IClock Clock { get; }

        /// <summary>
        /// The type from which entries are being logged. May be <c>null</c>.
        /// </summary>
        public Type LoggerForType { get; }

        /// <summary>
        /// Logging is enabled at this level and all higher levels.
        /// </summary>
        public LogLevel MinimumLogLevel { get; }

        /// <summary>
        /// Is Debug level logging enabled?
        /// </summary>
        public bool IsDebugEnabled { get; }

        /// <summary>
        /// Is info level logging enabled?
        /// </summary>
        public bool IsInfoEnabled { get; }

        /// <summary>
        /// Is warning level logging enabled?
        /// </summary>
        public bool IsWarningEnabled { get; }

        /// <summary>
        /// Is error level logging enabled?
        /// </summary>
        public bool IsErrorEnabled { get; }

        /// <summary>
        /// Build a new logger of the derived concrete type, for use to log from the specified type.
        /// </summary>
        /// <param name="type">The type from which entries are being logged.</param>
        /// <returns>A new <see cref="ILogger"/> instance, logging from the specified type.</returns>
        protected abstract ILogger BuildNewLogger(Type type);

        /// <inheritdoc/>
        public ILogger ForType<T>() => ForType(typeof(T));

        /// <inheritdoc/>
        public ILogger ForType(Type type) => type == LoggerForType ? this : BuildNewLogger(type);

        /// <summary>
        /// Perform the actual logging.
        /// </summary>
        /// <param name="logLevel">The <see cref="LogLevel"/> of this log entry.</param>
        /// <param name="formattedMessage">The fully formatted log message, ready for logging.</param>
        protected abstract void Log(LogLevel logLevel, string formattedMessage);

        private string FormatLogEntry(string severityString, string message, params object[] formatArgs)
        {
            var msg = string.Format(message, formatArgs);
            var when = Clock.UtcNow.ToString(DateTimeFormatString, CultureInfo.InvariantCulture);
            // Matches gRPC log format
            return $"{severityString}{when} {_loggerForTypeString}{msg}";
        }

        /// <inheritdoc/>
        public void Debug(string message, params object[] formatArgs)
        {
            if (IsDebugEnabled)
            {
                Log(LogLevel.Debug, FormatLogEntry("D", message, formatArgs));
            }
        }

        /// <inheritdoc/>
        public void Info(string message, params object[] formatArgs)
        {
            if (IsInfoEnabled)
            {
                Log(LogLevel.Info, FormatLogEntry("I", message, formatArgs));
            }
        }

        /// <inheritdoc/>
        public void Warning(string message, params object[] formatArgs)
        {
            if (IsWarningEnabled)
            {
                Log(LogLevel.Warning, FormatLogEntry("W", message, formatArgs));
            }
        }

        /// <inheritdoc/>
        public void Error(Exception exception, string message, params object[] formatArgs)
        {
            if (IsErrorEnabled)
            {
                Log(LogLevel.Error, $"{FormatLogEntry("E", message, formatArgs)} {exception}");
            }
        }

        /// <inheritdoc/>
        public void Error(string message, params object[] formatArgs)
        {
            if (IsErrorEnabled)
            {
                Log(LogLevel.Error, FormatLogEntry("E", message, formatArgs));
            }
        }

    }
}