make logger immutable (#1783)

Co-authored-by: stas <statis@microsoft.com>
This commit is contained in:
Stas
2022-04-12 11:24:48 -07:00
committed by GitHub
parent 87eb606b35
commit febaf6e057
4 changed files with 103 additions and 54 deletions

View File

@ -10,9 +10,9 @@ namespace Microsoft.OneFuzz.Service;
public interface ILog public interface ILog
{ {
void Log(Guid correlationId, String message, SeverityLevel level, IDictionary<string, string> tags, string? caller); void Log(Guid correlationId, String message, SeverityLevel level, IReadOnlyDictionary<string, string> tags, string? caller);
void LogEvent(Guid correlationId, String evt, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller); void LogEvent(Guid correlationId, String evt, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller);
void LogException(Guid correlationId, Exception ex, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller); void LogException(Guid correlationId, Exception ex, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller);
void Flush(); void Flush();
} }
@ -22,24 +22,39 @@ class AppInsights : ILog
new TelemetryClient( new TelemetryClient(
new TelemetryConfiguration(EnvironmentVariables.AppInsights.InstrumentationKey)); new TelemetryConfiguration(EnvironmentVariables.AppInsights.InstrumentationKey));
public void Log(Guid correlationId, String message, SeverityLevel level, IDictionary<string, string> tags, string? caller) public void Log(Guid correlationId, String message, SeverityLevel level, IReadOnlyDictionary<string, string> tags, string? caller)
{ {
tags["Correlation ID"] = correlationId.ToString(); Dictionary<string, string> copyTags = new(tags);
if (caller is not null) tags["CalledBy"] = caller; copyTags["Correlation ID"] = correlationId.ToString();
telemetryClient.TrackTrace(message, level, tags); if (caller is not null) copyTags["CalledBy"] = caller;
telemetryClient.TrackTrace(message, level, copyTags);
} }
public void LogEvent(Guid correlationId, String evt, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller) public void LogEvent(Guid correlationId, String evt, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
{ {
tags["Correlation ID"] = correlationId.ToString(); Dictionary<string, string> copyTags = new(tags);
if (caller is not null) tags["CalledBy"] = caller; copyTags["Correlation ID"] = correlationId.ToString();
telemetryClient.TrackEvent(evt, properties: tags, metrics: metrics); if (caller is not null) copyTags["CalledBy"] = caller;
}
public void LogException(Guid correlationId, Exception ex, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller)
{
tags["Correlation ID"] = correlationId.ToString();
if (caller is not null) tags["CalledBy"] = caller; Dictionary<string, double>? copyMetrics = null;
telemetryClient.TrackException(ex, tags, metrics); if (metrics is not null)
{
copyMetrics = new(metrics);
}
telemetryClient.TrackEvent(evt, properties: copyTags, metrics: copyMetrics);
}
public void LogException(Guid correlationId, Exception ex, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
{
Dictionary<string, string> copyTags = new(tags);
copyTags["Correlation ID"] = correlationId.ToString();
if (caller is not null) copyTags["CalledBy"] = caller;
Dictionary<string, double>? copyMetrics = null;
if (metrics is not null)
{
copyMetrics = new(metrics);
}
telemetryClient.TrackException(ex, copyTags, copyMetrics);
} }
public void Flush() public void Flush()
@ -52,7 +67,7 @@ class AppInsights : ILog
class Console : ILog class Console : ILog
{ {
private string DictToString<T>(IDictionary<string, T>? d) private string DictToString<T>(IReadOnlyDictionary<string, T>? d)
{ {
if (d is null) if (d is null)
{ {
@ -64,41 +79,41 @@ class Console : ILog
} }
} }
private void LogTags(Guid correlationId, string? caller, IDictionary<string, string> tags) private void LogTags(Guid correlationId, IReadOnlyDictionary<string, string> tags)
{ {
var ts = DictToString(tags); var ts = DictToString(tags);
if (!string.IsNullOrEmpty(ts)) if (!string.IsNullOrEmpty(ts))
{ {
System.Console.WriteLine($"[{correlationId}:{caller}] Tags:{ts}"); System.Console.WriteLine($"[{correlationId}] Tags:{ts}");
} }
} }
private void LogMetrics(Guid correlationId, string? caller, IDictionary<string, double>? metrics) private void LogMetrics(Guid correlationId, IReadOnlyDictionary<string, double>? metrics)
{ {
var ms = DictToString(metrics); var ms = DictToString(metrics);
if (!string.IsNullOrEmpty(ms)) if (!string.IsNullOrEmpty(ms))
{ {
System.Console.Out.WriteLine($"[{correlationId}:{caller}] Metrics:{DictToString(metrics)}"); System.Console.Out.WriteLine($"[{correlationId}] Metrics:{DictToString(metrics)}");
} }
} }
public void Log(Guid correlationId, String message, SeverityLevel level, IDictionary<string, string> tags, string? caller) public void Log(Guid correlationId, String message, SeverityLevel level, IReadOnlyDictionary<string, string> tags, string? caller)
{ {
System.Console.Out.WriteLine($"[{correlationId}:{caller}][{level}] {message}"); System.Console.Out.WriteLine($"[{correlationId}][{level}] {message}");
LogTags(correlationId, caller, tags); LogTags(correlationId, tags);
} }
public void LogEvent(Guid correlationId, String evt, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller) public void LogEvent(Guid correlationId, String evt, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
{ {
System.Console.Out.WriteLine($"[{correlationId}:{caller}][Event] {evt}"); System.Console.Out.WriteLine($"[{correlationId}][Event] {evt}");
LogTags(correlationId, caller, tags); LogTags(correlationId, tags);
LogMetrics(correlationId, caller, metrics); LogMetrics(correlationId, metrics);
} }
public void LogException(Guid correlationId, Exception ex, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller) public void LogException(Guid correlationId, Exception ex, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
{ {
System.Console.Out.WriteLine($"[{correlationId}:{caller}][Exception] {ex}"); System.Console.Out.WriteLine($"[{correlationId}][Exception] {ex}");
LogTags(correlationId, caller, tags); LogTags(correlationId, tags);
LogMetrics(correlationId, caller, metrics); LogMetrics(correlationId, metrics);
} }
public void Flush() public void Flush()
{ {
@ -108,15 +123,17 @@ class Console : ILog
public interface ILogTracer public interface ILogTracer
{ {
IDictionary<string, string> Tags { get; } IReadOnlyDictionary<string, string> Tags { get; }
void Critical(string message); void Critical(string message);
void Error(string message); void Error(string message);
void Event(string evt, IDictionary<string, double>? metrics); void Event(string evt, IReadOnlyDictionary<string, double>? metrics);
void Exception(Exception ex, IDictionary<string, double>? metrics); void Exception(Exception ex, IReadOnlyDictionary<string, double>? metrics);
void ForceFlush(); void ForceFlush();
void Info(string message); void Info(string message);
void Warning(string message); void Warning(string message);
ILogTracer AddTags((string, string)[]? tags);
} }
public class LogTracer : ILogTracer public class LogTracer : ILogTracer
@ -129,15 +146,49 @@ public class LogTracer : ILogTracer
private List<ILog> _loggers; private List<ILog> _loggers;
public Guid CorrelationId { get; } public Guid CorrelationId { get; }
public IDictionary<string, string> Tags { get; } public IReadOnlyDictionary<string, string> Tags { get; }
public LogTracer(Guid correlationId, List<ILog> loggers)
private static List<KeyValuePair<string, string>> ConvertTags((string, string)[]? tags)
{
List<KeyValuePair<string, string>> converted = new List<KeyValuePair<string, string>>();
if (tags is null)
{
return converted;
}
else
{
foreach (var (k, v) in tags)
{
converted.Add(new KeyValuePair<string, string>(k, v));
}
return converted;
}
}
public LogTracer(Guid correlationId, (string, string)[]? tags, List<ILog> loggers) : this(correlationId, new Dictionary<string, string>(ConvertTags(tags)), loggers) { }
public LogTracer(Guid correlationId, IReadOnlyDictionary<string, string> tags, List<ILog> loggers)
{ {
CorrelationId = correlationId; CorrelationId = correlationId;
Tags = new Dictionary<string, string>(); Tags = tags;
_loggers = loggers; _loggers = loggers;
} }
public ILogTracer AddTags((string, string)[]? tags)
{
var newTags = new Dictionary<string, string>(Tags);
if (tags is not null)
{
foreach (var (k, v) in tags)
{
newTags[k] = v;
}
}
return new LogTracer(CorrelationId, newTags, _loggers);
}
public void Info(string message) public void Info(string message)
{ {
var caller = GetCaller(); var caller = GetCaller();
@ -174,7 +225,7 @@ public class LogTracer : ILogTracer
} }
} }
public void Event(string evt, IDictionary<string, double>? metrics) public void Event(string evt, IReadOnlyDictionary<string, double>? metrics)
{ {
var caller = GetCaller(); var caller = GetCaller();
foreach (var logger in _loggers) foreach (var logger in _loggers)
@ -183,7 +234,7 @@ public class LogTracer : ILogTracer
} }
} }
public void Exception(Exception ex, IDictionary<string, double>? metrics) public void Exception(Exception ex, IReadOnlyDictionary<string, double>? metrics)
{ {
var caller = GetCaller(); var caller = GetCaller();
foreach (var logger in _loggers) foreach (var logger in _loggers)
@ -203,7 +254,7 @@ public class LogTracer : ILogTracer
public interface ILogTracerFactory public interface ILogTracerFactory
{ {
LogTracer MakeLogTracer(Guid correlationId); LogTracer MakeLogTracer(Guid correlationId, (string, string)[]? tags = null);
} }
public class LogTracerFactory : ILogTracerFactory public class LogTracerFactory : ILogTracerFactory
@ -215,9 +266,9 @@ public class LogTracerFactory : ILogTracerFactory
_loggers = loggers; _loggers = loggers;
} }
public LogTracer MakeLogTracer(Guid correlationId) public LogTracer MakeLogTracer(Guid correlationId, (string, string)[]? tags = null)
{ {
return new(correlationId, _loggers); return new(correlationId, tags, _loggers);
} }
} }

View File

@ -28,14 +28,11 @@ public class QueueProxyHearbeat
var hb = JsonSerializer.Deserialize<ProxyHeartbeat>(msg, EntityConverter.GetJsonSerializerOptions()).EnsureNotNull($"wrong data {msg}"); ; var hb = JsonSerializer.Deserialize<ProxyHeartbeat>(msg, EntityConverter.GetJsonSerializerOptions()).EnsureNotNull($"wrong data {msg}"); ;
var newHb = hb with { TimeStamp = DateTimeOffset.UtcNow }; var newHb = hb with { TimeStamp = DateTimeOffset.UtcNow };
log.Tags["Proxy ID"] = newHb.ProxyId.ToString();
var proxy = await _proxy.GetByProxyId(newHb.ProxyId); var proxy = await _proxy.GetByProxyId(newHb.ProxyId);
if (proxy == null) if (proxy == null)
{ {
log.Warning($"invalid proxy id: {newHb.ProxyId}"); log.AddTags(new[] { ("Proxy ID", newHb.ProxyId.ToString()) }).Warning($"invalid proxy id: {newHb.ProxyId}");
return; return;
} }
var newProxy = proxy with { heartbeat = newHb }; var newProxy = proxy with { heartbeat = newHb };

View File

@ -68,13 +68,11 @@ namespace Microsoft.OneFuzz.Service
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.Converters.Add(new RemoveUserInfo()); options.Converters.Add(new RemoveUserInfo());
var serializedEvent = JsonSerializer.Serialize(anEvent, options); var serializedEvent = JsonSerializer.Serialize(anEvent, options);
log.Tags["Event Type"] = eventType.ToString(); log.AddTags(new[] { ("Event Type", eventType.ToString()) }).Info($"sending event: {eventType} - {serializedEvent}");
log.Info($"sending event: {eventType} - {serializedEvent}");
} }
} }
internal class RemoveUserInfo : JsonConverter<UserInfo> internal class RemoveUserInfo : JsonConverter<UserInfo>
{ {
public override UserInfo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override UserInfo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)

View File

@ -43,9 +43,12 @@ public class WebhookMessageLogOperations : Orm<WebhookMessageLog>, IWebhookMessa
if (visibilityTimeout == null) if (visibilityTimeout == null)
{ {
log.Tags["WebhookId"] = webhookLog.WebhookId.ToString(); log.AddTags(
log.Tags["EventId"] = webhookLog.EventId.ToString(); new[] {
log.Error($"invalid WebhookMessage queue state, not queuing. {webhookLog.WebhookId}:{webhookLog.EventId} - {webhookLog.State}"); ("WebhookId", webhookLog.WebhookId.ToString()),
("EventId", webhookLog.EventId.ToString()) }
).
Error($"invalid WebhookMessage queue state, not queuing. {webhookLog.WebhookId}:{webhookLog.EventId} - {webhookLog.State}");
} }
else else
{ {