Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit febaf6e

Browse files
stishkinstas
andauthored
make logger immutable (#1783)
Co-authored-by: stas <statis@microsoft.com>
1 parent 87eb606 commit febaf6e

File tree

4 files changed

+101
-52
lines changed

4 files changed

+101
-52
lines changed

src/ApiService/ApiService/Log.cs

Lines changed: 93 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ namespace Microsoft.OneFuzz.Service;
1010

1111
public interface ILog
1212
{
13-
void Log(Guid correlationId, String message, SeverityLevel level, IDictionary<string, string> tags, string? caller);
14-
void LogEvent(Guid correlationId, String evt, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller);
15-
void LogException(Guid correlationId, Exception ex, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller);
13+
void Log(Guid correlationId, String message, SeverityLevel level, IReadOnlyDictionary<string, string> tags, string? caller);
14+
void LogEvent(Guid correlationId, String evt, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller);
15+
void LogException(Guid correlationId, Exception ex, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller);
1616
void Flush();
1717
}
1818

@@ -22,24 +22,39 @@ class AppInsights : ILog
2222
new TelemetryClient(
2323
new TelemetryConfiguration(EnvironmentVariables.AppInsights.InstrumentationKey));
2424

25-
public void Log(Guid correlationId, String message, SeverityLevel level, IDictionary<string, string> tags, string? caller)
25+
public void Log(Guid correlationId, String message, SeverityLevel level, IReadOnlyDictionary<string, string> tags, string? caller)
2626
{
27-
tags["Correlation ID"] = correlationId.ToString();
28-
if (caller is not null) tags["CalledBy"] = caller;
29-
telemetryClient.TrackTrace(message, level, tags);
27+
Dictionary<string, string> copyTags = new(tags);
28+
copyTags["Correlation ID"] = correlationId.ToString();
29+
if (caller is not null) copyTags["CalledBy"] = caller;
30+
telemetryClient.TrackTrace(message, level, copyTags);
3031
}
31-
public void LogEvent(Guid correlationId, String evt, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller)
32+
public void LogEvent(Guid correlationId, String evt, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
3233
{
33-
tags["Correlation ID"] = correlationId.ToString();
34-
if (caller is not null) tags["CalledBy"] = caller;
35-
telemetryClient.TrackEvent(evt, properties: tags, metrics: metrics);
34+
Dictionary<string, string> copyTags = new(tags);
35+
copyTags["Correlation ID"] = correlationId.ToString();
36+
if (caller is not null) copyTags["CalledBy"] = caller;
37+
38+
Dictionary<string, double>? copyMetrics = null;
39+
if (metrics is not null)
40+
{
41+
copyMetrics = new(metrics);
42+
}
43+
44+
telemetryClient.TrackEvent(evt, properties: copyTags, metrics: copyMetrics);
3645
}
37-
public void LogException(Guid correlationId, Exception ex, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller)
46+
public void LogException(Guid correlationId, Exception ex, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
3847
{
39-
tags["Correlation ID"] = correlationId.ToString();
48+
Dictionary<string, string> copyTags = new(tags);
49+
copyTags["Correlation ID"] = correlationId.ToString();
50+
if (caller is not null) copyTags["CalledBy"] = caller;
4051

41-
if (caller is not null) tags["CalledBy"] = caller;
42-
telemetryClient.TrackException(ex, tags, metrics);
52+
Dictionary<string, double>? copyMetrics = null;
53+
if (metrics is not null)
54+
{
55+
copyMetrics = new(metrics);
56+
}
57+
telemetryClient.TrackException(ex, copyTags, copyMetrics);
4358
}
4459

4560
public void Flush()
@@ -52,7 +67,7 @@ public void Flush()
5267
class Console : ILog
5368
{
5469

55-
private string DictToString<T>(IDictionary<string, T>? d)
70+
private string DictToString<T>(IReadOnlyDictionary<string, T>? d)
5671
{
5772
if (d is null)
5873
{
@@ -64,41 +79,41 @@ private string DictToString<T>(IDictionary<string, T>? d)
6479
}
6580
}
6681

67-
private void LogTags(Guid correlationId, string? caller, IDictionary<string, string> tags)
82+
private void LogTags(Guid correlationId, IReadOnlyDictionary<string, string> tags)
6883
{
6984
var ts = DictToString(tags);
7085
if (!string.IsNullOrEmpty(ts))
7186
{
72-
System.Console.WriteLine($"[{correlationId}:{caller}] Tags:{ts}");
87+
System.Console.WriteLine($"[{correlationId}] Tags:{ts}");
7388
}
7489
}
7590

76-
private void LogMetrics(Guid correlationId, string? caller, IDictionary<string, double>? metrics)
91+
private void LogMetrics(Guid correlationId, IReadOnlyDictionary<string, double>? metrics)
7792
{
7893
var ms = DictToString(metrics);
7994
if (!string.IsNullOrEmpty(ms))
8095
{
81-
System.Console.Out.WriteLine($"[{correlationId}:{caller}] Metrics:{DictToString(metrics)}");
96+
System.Console.Out.WriteLine($"[{correlationId}] Metrics:{DictToString(metrics)}");
8297
}
8398
}
8499

85-
public void Log(Guid correlationId, String message, SeverityLevel level, IDictionary<string, string> tags, string? caller)
100+
public void Log(Guid correlationId, String message, SeverityLevel level, IReadOnlyDictionary<string, string> tags, string? caller)
86101
{
87-
System.Console.Out.WriteLine($"[{correlationId}:{caller}][{level}] {message}");
88-
LogTags(correlationId, caller, tags);
102+
System.Console.Out.WriteLine($"[{correlationId}][{level}] {message}");
103+
LogTags(correlationId, tags);
89104
}
90105

91-
public void LogEvent(Guid correlationId, String evt, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller)
106+
public void LogEvent(Guid correlationId, String evt, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
92107
{
93-
System.Console.Out.WriteLine($"[{correlationId}:{caller}][Event] {evt}");
94-
LogTags(correlationId, caller, tags);
95-
LogMetrics(correlationId, caller, metrics);
108+
System.Console.Out.WriteLine($"[{correlationId}][Event] {evt}");
109+
LogTags(correlationId, tags);
110+
LogMetrics(correlationId, metrics);
96111
}
97-
public void LogException(Guid correlationId, Exception ex, IDictionary<string, string> tags, IDictionary<string, double>? metrics, string? caller)
112+
public void LogException(Guid correlationId, Exception ex, IReadOnlyDictionary<string, string> tags, IReadOnlyDictionary<string, double>? metrics, string? caller)
98113
{
99-
System.Console.Out.WriteLine($"[{correlationId}:{caller}][Exception] {ex}");
100-
LogTags(correlationId, caller, tags);
101-
LogMetrics(correlationId, caller, metrics);
114+
System.Console.Out.WriteLine($"[{correlationId}][Exception] {ex}");
115+
LogTags(correlationId, tags);
116+
LogMetrics(correlationId, metrics);
102117
}
103118
public void Flush()
104119
{
@@ -108,15 +123,17 @@ public void Flush()
108123

109124
public interface ILogTracer
110125
{
111-
IDictionary<string, string> Tags { get; }
126+
IReadOnlyDictionary<string, string> Tags { get; }
112127

113128
void Critical(string message);
114129
void Error(string message);
115-
void Event(string evt, IDictionary<string, double>? metrics);
116-
void Exception(Exception ex, IDictionary<string, double>? metrics);
130+
void Event(string evt, IReadOnlyDictionary<string, double>? metrics);
131+
void Exception(Exception ex, IReadOnlyDictionary<string, double>? metrics);
117132
void ForceFlush();
118133
void Info(string message);
119134
void Warning(string message);
135+
136+
ILogTracer AddTags((string, string)[]? tags);
120137
}
121138

122139
public class LogTracer : ILogTracer
@@ -129,15 +146,49 @@ public class LogTracer : ILogTracer
129146
private List<ILog> _loggers;
130147

131148
public Guid CorrelationId { get; }
132-
public IDictionary<string, string> Tags { get; }
149+
public IReadOnlyDictionary<string, string> Tags { get; }
150+
133151

134-
public LogTracer(Guid correlationId, List<ILog> loggers)
152+
private static List<KeyValuePair<string, string>> ConvertTags((string, string)[]? tags)
153+
{
154+
List<KeyValuePair<string, string>> converted = new List<KeyValuePair<string, string>>();
155+
if (tags is null)
156+
{
157+
return converted;
158+
}
159+
else
160+
{
161+
foreach (var (k, v) in tags)
162+
{
163+
converted.Add(new KeyValuePair<string, string>(k, v));
164+
}
165+
return converted;
166+
}
167+
}
168+
169+
public LogTracer(Guid correlationId, (string, string)[]? tags, List<ILog> loggers) : this(correlationId, new Dictionary<string, string>(ConvertTags(tags)), loggers) { }
170+
171+
172+
public LogTracer(Guid correlationId, IReadOnlyDictionary<string, string> tags, List<ILog> loggers)
135173
{
136174
CorrelationId = correlationId;
137-
Tags = new Dictionary<string, string>();
175+
Tags = tags;
138176
_loggers = loggers;
139177
}
140178

179+
public ILogTracer AddTags((string, string)[]? tags)
180+
{
181+
var newTags = new Dictionary<string, string>(Tags);
182+
if (tags is not null)
183+
{
184+
foreach (var (k, v) in tags)
185+
{
186+
newTags[k] = v;
187+
}
188+
}
189+
return new LogTracer(CorrelationId, newTags, _loggers);
190+
}
191+
141192
public void Info(string message)
142193
{
143194
var caller = GetCaller();
@@ -174,7 +225,7 @@ public void Critical(string message)
174225
}
175226
}
176227

177-
public void Event(string evt, IDictionary<string, double>? metrics)
228+
public void Event(string evt, IReadOnlyDictionary<string, double>? metrics)
178229
{
179230
var caller = GetCaller();
180231
foreach (var logger in _loggers)
@@ -183,7 +234,7 @@ public void Event(string evt, IDictionary<string, double>? metrics)
183234
}
184235
}
185236

186-
public void Exception(Exception ex, IDictionary<string, double>? metrics)
237+
public void Exception(Exception ex, IReadOnlyDictionary<string, double>? metrics)
187238
{
188239
var caller = GetCaller();
189240
foreach (var logger in _loggers)
@@ -203,7 +254,7 @@ public void ForceFlush()
203254

204255
public interface ILogTracerFactory
205256
{
206-
LogTracer MakeLogTracer(Guid correlationId);
257+
LogTracer MakeLogTracer(Guid correlationId, (string, string)[]? tags = null);
207258
}
208259

209260
public class LogTracerFactory : ILogTracerFactory
@@ -215,9 +266,9 @@ public LogTracerFactory(List<ILog> loggers)
215266
_loggers = loggers;
216267
}
217268

218-
public LogTracer MakeLogTracer(Guid correlationId)
269+
public LogTracer MakeLogTracer(Guid correlationId, (string, string)[]? tags = null)
219270
{
220-
return new(correlationId, _loggers);
271+
return new(correlationId, tags, _loggers);
221272
}
222273

223274
}

src/ApiService/ApiService/QueueProxyHeartbeat.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,11 @@ public async Task Run([QueueTrigger("myqueue-items", Connection = "AzureWebJobsS
2828
var hb = JsonSerializer.Deserialize<ProxyHeartbeat>(msg, EntityConverter.GetJsonSerializerOptions()).EnsureNotNull($"wrong data {msg}"); ;
2929
var newHb = hb with { TimeStamp = DateTimeOffset.UtcNow };
3030

31-
log.Tags["Proxy ID"] = newHb.ProxyId.ToString();
32-
33-
3431
var proxy = await _proxy.GetByProxyId(newHb.ProxyId);
3532

3633
if (proxy == null)
3734
{
38-
log.Warning($"invalid proxy id: {newHb.ProxyId}");
35+
log.AddTags(new[] { ("Proxy ID", newHb.ProxyId.ToString()) }).Warning($"invalid proxy id: {newHb.ProxyId}");
3936
return;
4037
}
4138
var newProxy = proxy with { heartbeat = newHb };

src/ApiService/ApiService/onefuzzlib/Events.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,11 @@ public void LogEvent(ILogTracer log, BaseEvent anEvent, EventType eventType)
6868
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
6969
options.Converters.Add(new RemoveUserInfo());
7070
var serializedEvent = JsonSerializer.Serialize(anEvent, options);
71-
log.Tags["Event Type"] = eventType.ToString();
72-
log.Info($"sending event: {eventType} - {serializedEvent}");
71+
log.AddTags(new[] { ("Event Type", eventType.ToString()) }).Info($"sending event: {eventType} - {serializedEvent}");
7372
}
7473
}
7574

7675

77-
7876
internal class RemoveUserInfo : JsonConverter<UserInfo>
7977
{
8078
public override UserInfo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)

src/ApiService/ApiService/onefuzzlib/WebhookOperations.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,12 @@ public async Task QueueWebhook(WebhookMessageLog webhookLog)
4343

4444
if (visibilityTimeout == null)
4545
{
46-
log.Tags["WebhookId"] = webhookLog.WebhookId.ToString();
47-
log.Tags["EventId"] = webhookLog.EventId.ToString();
48-
log.Error($"invalid WebhookMessage queue state, not queuing. {webhookLog.WebhookId}:{webhookLog.EventId} - {webhookLog.State}");
46+
log.AddTags(
47+
new[] {
48+
("WebhookId", webhookLog.WebhookId.ToString()),
49+
("EventId", webhookLog.EventId.ToString()) }
50+
).
51+
Error($"invalid WebhookMessage queue state, not queuing. {webhookLog.WebhookId}:{webhookLog.EventId} - {webhookLog.State}");
4952
}
5053
else
5154
{

0 commit comments

Comments
 (0)