Skip to content

Commit 9be92a9

Browse files
committed
Refactor to improve formating of Context
Signed-off-by: Kyle Julian <[email protected]>
1 parent 15b667f commit 9be92a9

File tree

1 file changed

+107
-46
lines changed

1 file changed

+107
-46
lines changed

src/OpenFeature/LoggingHook.cs

+107-46
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Collections.Immutable;
43
using System.Text;
54
using System.Threading;
65
using System.Threading.Tasks;
76
using Microsoft.Extensions.Logging;
8-
using OpenFeature.Error;
97
using OpenFeature.Model;
108

119
namespace OpenFeature
@@ -30,18 +28,26 @@ public LoggingHook(ILogger logger, bool includeContext = false)
3028
/// <inheritdoc/>
3129
public override ValueTask<EvaluationContext> BeforeAsync<T>(HookContext<T> context, IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default)
3230
{
33-
var domain = context.ClientMetadata.Name ?? string.Empty;
34-
var providerName = context.ProviderMetadata.Name ?? string.Empty;
35-
var defaultValue = context.DefaultValue?.ToString() ?? string.Empty;
36-
3731
if (this._includeContext)
3832
{
39-
var evaluationContextLog = new ExecutionContentLog(context.EvaluationContext);
40-
this.HookBeforeStageExecuted(domain, providerName, context.FlagKey, defaultValue, evaluationContextLog);
33+
var beforeLogContent = new LoggingHookContent(
34+
context.ClientMetadata.Name,
35+
context.ProviderMetadata.Name,
36+
context.FlagKey,
37+
context.DefaultValue?.ToString(),
38+
context.EvaluationContext);
39+
40+
this.HookBeforeStageExecuted(beforeLogContent);
4141
}
4242
else
4343
{
44-
this.HookBeforeStageExecuted(domain, providerName, context.FlagKey, defaultValue);
44+
var beforeLogContent = new LoggingHookContent(
45+
context.ClientMetadata.Name,
46+
context.ProviderMetadata.Name,
47+
context.FlagKey,
48+
context.DefaultValue?.ToString());
49+
50+
this.HookBeforeStageExecuted(beforeLogContent);
4551
}
4652

4753
return base.BeforeAsync(context, hints, cancellationToken);
@@ -50,24 +56,26 @@ public override ValueTask<EvaluationContext> BeforeAsync<T>(HookContext<T> conte
5056
/// <inheritdoc/>
5157
public override ValueTask ErrorAsync<T>(HookContext<T> context, Exception error, IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default)
5258
{
53-
var domain = context.ClientMetadata.Name ?? string.Empty;
54-
var providerName = context.ProviderMetadata.Name ?? string.Empty;
55-
var defaultValue = context.DefaultValue?.ToString() ?? string.Empty;
56-
57-
if (error.GetType() == typeof(FeatureProviderException))
58-
{
59-
var featureError = (FeatureProviderException)error;
60-
featureError.ErrorType;
61-
}
62-
6359
if (this._includeContext)
6460
{
65-
var evaluationContextLog = new ExecutionContentLog(context.EvaluationContext);
66-
this.HookErrorStageExecuted(domain, providerName, context.FlagKey, defaultValue, evaluationContextLog);
61+
var beforeLogContent = new LoggingHookContent(
62+
context.ClientMetadata.Name,
63+
context.ProviderMetadata.Name,
64+
context.FlagKey,
65+
context.DefaultValue?.ToString(),
66+
context.EvaluationContext);
67+
68+
this.HookErrorStageExecuted(beforeLogContent);
6769
}
6870
else
6971
{
70-
this.HookErrorStageExecuted(domain, providerName, context.FlagKey, defaultValue);
72+
var beforeLogContent = new LoggingHookContent(
73+
context.ClientMetadata.Name,
74+
context.ProviderMetadata.Name,
75+
context.FlagKey,
76+
context.DefaultValue?.ToString());
77+
78+
this.HookErrorStageExecuted(beforeLogContent);
7179
}
7280

7381
return base.ErrorAsync(context, error, hints, cancellationToken);
@@ -76,21 +84,26 @@ public override ValueTask ErrorAsync<T>(HookContext<T> context, Exception error,
7684
/// <inheritdoc/>
7785
public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDetails<T> details, IReadOnlyDictionary<string, object>? hints = null, CancellationToken cancellationToken = default)
7886
{
79-
var domain = context.ClientMetadata.Name ?? string.Empty;
80-
var providerName = context.ProviderMetadata.Name ?? string.Empty;
81-
var defaultValue = context.DefaultValue?.ToString() ?? string.Empty;
82-
var reason = details.Reason ?? string.Empty;
83-
var variant = details.Variant ?? string.Empty;
84-
var value = details.Value?.ToString() ?? string.Empty;
85-
8687
if (this._includeContext)
8788
{
88-
var evaluationContextLog = new ExecutionContentLog(context.EvaluationContext);
89-
this.HookAfterStageExecuted(domain, providerName, context.FlagKey, defaultValue, evaluationContextLog);
89+
var beforeLogContent = new LoggingHookContent(
90+
context.ClientMetadata.Name,
91+
context.ProviderMetadata.Name,
92+
context.FlagKey,
93+
context.DefaultValue?.ToString(),
94+
context.EvaluationContext);
95+
96+
this.HookAfterStageExecuted(beforeLogContent);
9097
}
9198
else
9299
{
93-
this.HookAfterStageExecuted(domain, providerName, context.FlagKey, defaultValue);
100+
var beforeLogContent = new LoggingHookContent(
101+
context.ClientMetadata.Name,
102+
context.ProviderMetadata.Name,
103+
context.FlagKey,
104+
context.DefaultValue?.ToString());
105+
106+
this.HookAfterStageExecuted(beforeLogContent);
94107
}
95108

96109
return base.AfterAsync(context, details, hints, cancellationToken);
@@ -99,29 +112,38 @@ public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDe
99112
[LoggerMessage(
100113
EventId = 0,
101114
Level = LogLevel.Debug,
102-
Message = "[Before] Domain {Domain} with Provider {ProviderName} {FlagKey} defaults with {DefaultValue} {EvaluationContextLog}")]
103-
partial void HookBeforeStageExecuted(string domain, string providerName, string flagKey, string defaultValue, ExecutionContentLog? evaluationContextLog = null);
115+
Message = "Before Flag Evaluation {Content}")]
116+
partial void HookBeforeStageExecuted(LoggingHookContent content);
104117

105118
[LoggerMessage(
106119
EventId = 0,
107120
Level = LogLevel.Error,
108-
Message = "[Error] Domain {Domain} with Provider {ProviderName} {FlagKey} defaults with {DefaultValue} {Variant} {Variant} {EvaluationContextLog}")]
109-
partial void HookErrorStageExecuted(string domain, string providerName, string flagKey, string defaultValue, ExecutionContentLog? evaluationContextLog = null);
121+
Message = "Error during Flag Evaluation {Content}")]
122+
partial void HookErrorStageExecuted(LoggingHookContent content);
110123

111124
[LoggerMessage(
112125
EventId = 0,
113126
Level = LogLevel.Debug,
114-
Message = "[After] Domain {Domain} with Provider {ProviderName} {FlagKey} defaults with {DefaultValue} {EvaluationContextLog}")]
115-
partial void HookAfterStageExecuted(string domain, string providerName, string flagKey, string defaultValue, ExecutionContentLog? evaluationContextLog = null);
127+
Message = "After Flag Evaluation {Content}")]
128+
partial void HookAfterStageExecuted(LoggingHookContent content);
116129

117-
internal class ExecutionContentLog
130+
internal class LoggingHookContent
118131
{
119-
private readonly IImmutableDictionary<string, Value> _values;
132+
private readonly string _domain;
133+
private readonly string _providerName;
134+
private readonly string _flagKey;
135+
private readonly string _defaultValue;
136+
private readonly EvaluationContext? _evaluationContext;
137+
120138
private string? _cachedToString;
121139

122-
public ExecutionContentLog(EvaluationContext evaluationContent)
140+
public LoggingHookContent(string? domain, string? providerName, string flagKey, string? defaultValue, EvaluationContext? evaluationContext = null)
123141
{
124-
this._values = evaluationContent.AsDictionary();
142+
this._domain = string.IsNullOrEmpty(domain) ? "missing" : domain;
143+
this._providerName = string.IsNullOrEmpty(providerName) ? "missing" : providerName;
144+
this._flagKey = flagKey;
145+
this._defaultValue = string.IsNullOrEmpty(defaultValue) ? "missing" : defaultValue;
146+
this._evaluationContext = evaluationContext;
125147
}
126148

127149
public override string ToString()
@@ -130,19 +152,58 @@ public override string ToString()
130152
{
131153
var stringBuilder = new StringBuilder();
132154

133-
foreach (var kvp in this._values)
155+
stringBuilder.Append("Domain:");
156+
stringBuilder.Append(_domain);
157+
stringBuilder.Append(Environment.NewLine);
158+
159+
stringBuilder.Append("ProviderName:");
160+
stringBuilder.Append(_providerName);
161+
stringBuilder.Append(Environment.NewLine);
162+
163+
stringBuilder.Append("FlagKey:");
164+
stringBuilder.Append(_flagKey);
165+
stringBuilder.Append(Environment.NewLine);
166+
167+
stringBuilder.Append("DefaultValue:");
168+
stringBuilder.Append(_defaultValue);
169+
stringBuilder.Append(Environment.NewLine);
170+
171+
if (this._evaluationContext != null)
134172
{
135-
stringBuilder.Append(kvp.Key);
136-
stringBuilder.Append(':');
137-
stringBuilder.Append(kvp.Value.ToString());
173+
stringBuilder.Append("Context:");
138174
stringBuilder.Append(Environment.NewLine);
175+
foreach (var kvp in this._evaluationContext.AsDictionary())
176+
{
177+
stringBuilder.Append('\t');
178+
stringBuilder.Append(kvp.Key);
179+
stringBuilder.Append(':');
180+
stringBuilder.Append(GetValueString(kvp.Value) ?? "missing");
181+
stringBuilder.Append(Environment.NewLine);
182+
}
139183
}
140184

141185
this._cachedToString = stringBuilder.ToString();
142186
}
143187

144188
return this._cachedToString;
145189
}
190+
191+
static string? GetValueString(Value value)
192+
{
193+
if (value.IsNull)
194+
return string.Empty;
195+
196+
if (value.IsString)
197+
return value.AsString;
198+
199+
if (value.IsBoolean)
200+
return value.AsBoolean.ToString();
201+
202+
if (value.IsDateTime)
203+
return value.AsDateTime?.ToString("O");
204+
205+
return value.ToString();
206+
}
146207
}
147208
}
148209
}

0 commit comments

Comments
 (0)