mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-17 12:28:07 +00:00
make logger immutable (#1783)
Co-authored-by: stas <statis@microsoft.com>
This commit is contained in:
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 };
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user