1
1
using System ;
2
2
using System . Collections . Generic ;
3
- using System . Collections . Immutable ;
4
3
using System . Text ;
5
4
using System . Threading ;
6
5
using System . Threading . Tasks ;
7
6
using Microsoft . Extensions . Logging ;
8
- using OpenFeature . Error ;
9
7
using OpenFeature . Model ;
10
8
11
9
namespace OpenFeature
@@ -30,18 +28,26 @@ public LoggingHook(ILogger logger, bool includeContext = false)
30
28
/// <inheritdoc/>
31
29
public override ValueTask < EvaluationContext > BeforeAsync < T > ( HookContext < T > context , IReadOnlyDictionary < string , object > ? hints = null , CancellationToken cancellationToken = default )
32
30
{
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
-
37
31
if ( this . _includeContext )
38
32
{
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 ) ;
41
41
}
42
42
else
43
43
{
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 ) ;
45
51
}
46
52
47
53
return base . BeforeAsync ( context , hints , cancellationToken ) ;
@@ -50,24 +56,26 @@ public override ValueTask<EvaluationContext> BeforeAsync<T>(HookContext<T> conte
50
56
/// <inheritdoc/>
51
57
public override ValueTask ErrorAsync < T > ( HookContext < T > context , Exception error , IReadOnlyDictionary < string , object > ? hints = null , CancellationToken cancellationToken = default )
52
58
{
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
-
63
59
if ( this . _includeContext )
64
60
{
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 ) ;
67
69
}
68
70
else
69
71
{
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 ) ;
71
79
}
72
80
73
81
return base . ErrorAsync ( context , error , hints , cancellationToken ) ;
@@ -76,21 +84,26 @@ public override ValueTask ErrorAsync<T>(HookContext<T> context, Exception error,
76
84
/// <inheritdoc/>
77
85
public override ValueTask AfterAsync < T > ( HookContext < T > context , FlagEvaluationDetails < T > details , IReadOnlyDictionary < string , object > ? hints = null , CancellationToken cancellationToken = default )
78
86
{
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
-
86
87
if ( this . _includeContext )
87
88
{
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 ) ;
90
97
}
91
98
else
92
99
{
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 ) ;
94
107
}
95
108
96
109
return base . AfterAsync ( context , details , hints , cancellationToken ) ;
@@ -99,29 +112,38 @@ public override ValueTask AfterAsync<T>(HookContext<T> context, FlagEvaluationDe
99
112
[ LoggerMessage (
100
113
EventId = 0 ,
101
114
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 ) ;
104
117
105
118
[ LoggerMessage (
106
119
EventId = 0 ,
107
120
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 ) ;
110
123
111
124
[ LoggerMessage (
112
125
EventId = 0 ,
113
126
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 ) ;
116
129
117
- internal class ExecutionContentLog
130
+ internal class LoggingHookContent
118
131
{
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
+
120
138
private string ? _cachedToString ;
121
139
122
- public ExecutionContentLog ( EvaluationContext evaluationContent )
140
+ public LoggingHookContent ( string ? domain , string ? providerName , string flagKey , string ? defaultValue , EvaluationContext ? evaluationContext = null )
123
141
{
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 ;
125
147
}
126
148
127
149
public override string ToString ( )
@@ -130,19 +152,58 @@ public override string ToString()
130
152
{
131
153
var stringBuilder = new StringBuilder ( ) ;
132
154
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 )
134
172
{
135
- stringBuilder . Append ( kvp . Key ) ;
136
- stringBuilder . Append ( ':' ) ;
137
- stringBuilder . Append ( kvp . Value . ToString ( ) ) ;
173
+ stringBuilder . Append ( "Context:" ) ;
138
174
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
+ }
139
183
}
140
184
141
185
this . _cachedToString = stringBuilder . ToString ( ) ;
142
186
}
143
187
144
188
return this . _cachedToString ;
145
189
}
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
+ }
146
207
}
147
208
}
148
209
}
0 commit comments