1
- using System ;
2
- using System . Collections . Generic ;
3
- using System . Net . Http ;
4
- using System . Runtime . Serialization ;
5
- using System . Text ;
6
- using System . Threading . Tasks ;
7
- using ClientExample ;
1
+ using ClientExample ;
8
2
using PostSharp . Aspects ;
9
3
using PostSharp . Patterns . Diagnostics ;
10
4
using PostSharp . Patterns . Formatters ;
11
5
using PostSharp . Serialization ;
6
+ using System ;
7
+ using System . Collections . Generic ;
8
+ using System . Net . Http ;
9
+ using System . Threading . Tasks ;
12
10
using static PostSharp . Patterns . Diagnostics . SemanticMessageBuilder ;
13
11
14
12
// The following attribute intercepts all calls to the specified methods of HttpClient.
19
17
20
18
namespace ClientExample
21
19
{
22
- [ PSerializable ]
23
- internal class InstrumentOutgoingRequestsAspect : MethodInterceptionAspect
20
+ [ PSerializable ]
21
+ internal class InstrumentOutgoingRequestsAspect : MethodInterceptionAspect
22
+ {
23
+ private static readonly LogSource logSource = LogSource . Get ( ) ;
24
+
25
+ public override async Task OnInvokeAsync ( MethodInterceptionArgs args )
24
26
{
25
- private static readonly LogSource logSource = LogSource . Get ( ) ;
27
+ var http = ( HttpClient ) args . Instance ;
28
+ var verb = Trim ( args . Method . Name , "Async" ) ;
26
29
27
- public override async Task OnInvokeAsync ( MethodInterceptionArgs args )
30
+ using ( var activity = logSource . Default . OpenActivity ( Semantic ( verb , ( "Url" , args . Arguments [ 0 ] ) ) ) )
31
+ {
32
+ try
28
33
{
29
- var http = ( HttpClient ) args . Instance ;
30
- var verb = Trim ( args . Method . Name , "Async" ) ;
34
+ // TODO: this implementation conflicts with System.Diagnostics.Activity and therefore Application Insights.
35
+
36
+
37
+ // Remove headers.
38
+ http . DefaultRequestHeaders . Remove ( "Request-Id" ) ;
39
+ http . DefaultRequestHeaders . Remove ( "Correlation-Context" ) ;
31
40
32
- using ( var activity = logSource . Default . OpenActivity ( Semantic ( verb , ( "Url" , args . Arguments [ 0 ] ) ) ) )
41
+
42
+ // Set Request-Id header.
43
+ http . DefaultRequestHeaders . Add ( "Request-Id" , activity . Context . SyntheticId ) ;
44
+
45
+
46
+ // Generate the Correlation-Context header.
47
+ UnsafeStringBuilder correlationContextBuilder = null ;
48
+ var propertyNames = new HashSet < string > ( ) ;
49
+ try
50
+ {
51
+ activity . Context . ForEachProperty ( ( LoggingProperty property , object value , ref object _ ) =>
33
52
{
34
- try
35
- {
36
- // TODO: this implementation conflicts with System.Diagnostics.Activity and therefore Application Insights.
37
-
38
-
39
- // Remove headers.
40
- http . DefaultRequestHeaders . Remove ( "Request-Id" ) ;
41
- http . DefaultRequestHeaders . Remove ( "Correlation-Context" ) ;
42
-
43
-
44
- // Set Request-Id header.
45
- http . DefaultRequestHeaders . Add ( "Request-Id" , activity . Context . SyntheticId ) ;
46
-
47
-
48
- // Generate the Correlation-Context header.
49
- UnsafeStringBuilder correlationContextBuilder = null ;
50
- var propertyNames = new HashSet < string > ( ) ;
51
- try
52
- {
53
- activity . Context . ForEachProperty ( ( LoggingProperty property , object value , ref object _ ) =>
54
- {
55
- if ( ! property . IsBaggage || ! propertyNames . Add ( property . Name ) ) return ;
56
-
57
- if ( correlationContextBuilder == null )
58
- {
59
- propertyNames = new HashSet < string > ( ) ;
60
- correlationContextBuilder = new UnsafeStringBuilder ( 1024 ) ;
61
- }
62
-
63
- if ( correlationContextBuilder . Length > 0 )
64
- {
65
- correlationContextBuilder . Append ( ", " ) ;
66
- }
67
-
68
- correlationContextBuilder . Append ( property . Name ) ;
69
- correlationContextBuilder . Append ( '=' ) ;
70
-
71
- var formatter =
72
- property . Formatter ?? LoggingServices . Formatters . Get ( value . GetType ( ) ) ;
73
-
74
- formatter . Write ( correlationContextBuilder , value ) ;
75
- } ) ;
76
-
77
- if ( correlationContextBuilder != null )
78
- {
79
- http . DefaultRequestHeaders . Add ( "Correlation-Context" , correlationContextBuilder . ToString ( ) ) ;
80
- }
81
- }
82
- finally
83
- {
84
- correlationContextBuilder ? . Dispose ( ) ;
85
- }
86
-
87
-
88
- var t = base . OnInvokeAsync ( args ) ;
89
-
90
- // We need to call Suspend/Resume because we're calling LogActivity from an aspect and
91
- // aspects are not automatically enhanced.
92
- // In other code, this is done automatically.
93
- if ( ! t . IsCompleted )
94
- {
95
- activity . Suspend ( ) ;
96
- try
97
- {
98
- await t ;
99
- }
100
- finally
101
- {
102
- activity . Resume ( ) ;
103
- }
104
- }
105
-
106
-
107
- var response = ( HttpResponseMessage ) args . ReturnValue ;
108
-
109
-
110
- if ( response . IsSuccessStatusCode )
111
- {
112
- activity . SetOutcome ( LogLevel . Info , Semantic ( "Succeeded" , ( "StatusCode" , response . StatusCode ) ) ) ;
113
- }
114
- else
115
- {
116
- activity . SetOutcome ( LogLevel . Warning , Semantic ( "Failed" , ( "StatusCode" , response . StatusCode ) ) ) ;
117
- }
118
- }
119
- catch ( Exception e )
120
- {
121
- activity . SetException ( e ) ;
122
- throw ;
123
- }
124
- finally
125
- {
126
- http . DefaultRequestHeaders . Remove ( "Request-Id" ) ;
127
- }
53
+ if ( ! property . IsBaggage || ! propertyNames . Add ( property . Name ) ) return ;
54
+
55
+ if ( correlationContextBuilder == null )
56
+ {
57
+ propertyNames = new HashSet < string > ( ) ;
58
+ correlationContextBuilder = new UnsafeStringBuilder ( 1024 ) ;
59
+ }
60
+
61
+ if ( correlationContextBuilder . Length > 0 )
62
+ {
63
+ correlationContextBuilder . Append ( ", " ) ;
64
+ }
65
+
66
+ correlationContextBuilder . Append ( property . Name ) ;
67
+ correlationContextBuilder . Append ( '=' ) ;
68
+
69
+ var formatter =
70
+ property . Formatter ?? LoggingServices . Formatters . Get ( value . GetType ( ) ) ;
71
+
72
+ formatter . Write ( correlationContextBuilder , value ) ;
73
+ } ) ;
74
+
75
+ if ( correlationContextBuilder != null )
76
+ {
77
+ http . DefaultRequestHeaders . Add ( "Correlation-Context" , correlationContextBuilder . ToString ( ) ) ;
128
78
}
129
- }
79
+ }
80
+ finally
81
+ {
82
+ correlationContextBuilder ? . Dispose ( ) ;
83
+ }
84
+
85
+
86
+ var t = base . OnInvokeAsync ( args ) ;
87
+
88
+ // We need to call Suspend/Resume because we're calling LogActivity from an aspect and
89
+ // aspects are not automatically enhanced.
90
+ // In other code, this is done automatically.
91
+ if ( ! t . IsCompleted )
92
+ {
93
+ activity . Suspend ( ) ;
94
+ try
95
+ {
96
+ await t ;
97
+ }
98
+ finally
99
+ {
100
+ activity . Resume ( ) ;
101
+ }
102
+ }
103
+
130
104
131
- private static string Trim ( string s , string suffix )
132
- => s . EndsWith ( suffix ) ? s . Substring ( 0 , s . Length - suffix . Length ) : s ;
105
+ var response = ( HttpResponseMessage ) args . ReturnValue ;
106
+
107
+
108
+ if ( response . IsSuccessStatusCode )
109
+ {
110
+ activity . SetOutcome ( LogLevel . Info , Semantic ( "Succeeded" , ( "StatusCode" , response . StatusCode ) ) ) ;
111
+ }
112
+ else
113
+ {
114
+ activity . SetOutcome ( LogLevel . Warning , Semantic ( "Failed" , ( "StatusCode" , response . StatusCode ) ) ) ;
115
+ }
116
+ }
117
+ catch ( Exception e )
118
+ {
119
+ activity . SetException ( e ) ;
120
+ throw ;
121
+ }
122
+ finally
123
+ {
124
+ http . DefaultRequestHeaders . Remove ( "Request-Id" ) ;
125
+ }
126
+ }
133
127
}
128
+
129
+ private static string Trim ( string s , string suffix )
130
+ => s . EndsWith ( suffix ) ? s . Substring ( 0 , s . Length - suffix . Length ) : s ;
131
+ }
134
132
}
0 commit comments