1
1
/*
2
2
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
- *
3
+ *
4
4
* Licensed under the Apache License, Version 2.0 (the "License").
5
5
* You may not use this file except in compliance with the License.
6
6
* A copy of the License is located at
7
- *
7
+ *
8
8
* http://aws.amazon.com/apache2.0
9
- *
9
+ *
10
10
* or in the "license" file accompanying this file. This file is distributed
11
11
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
12
* express or implied. See the License for the specific language governing
13
13
* permissions and limitations under the License.
14
14
*/
15
15
16
16
using System ;
17
- using System . Linq ;
18
17
using System . Runtime . ExceptionServices ;
19
18
using System . Text ;
20
- using AspectInjector . Broker ;
21
19
using AWS . Lambda . Powertools . Common ;
22
20
23
21
namespace AWS . Lambda . Powertools . Tracing . Internal ;
24
22
25
23
/// <summary>
26
- /// This aspect will automatically trace all function handlers .
27
- /// Scope.Global is singleton
24
+ /// Class TracingAspectHandler .
25
+ /// Implements the <see cref="IMethodAspectHandler" />
28
26
/// </summary>
29
- [ Aspect ( Scope . Global ) ]
30
- public class TracingAspect
27
+ /// <seealso cref="IMethodAspectHandler" />
28
+ internal class TracingAspectHandler : IMethodAspectHandler
31
29
{
32
30
/// <summary>
33
31
/// The Powertools for AWS Lambda (.NET) configurations
@@ -48,130 +46,120 @@ public class TracingAspect
48
46
/// If true, capture annotations
49
47
/// </summary>
50
48
private static bool _captureAnnotations = true ;
51
-
49
+
52
50
/// <summary>
53
51
/// If true, annotations have been captured
54
52
/// </summary>
55
53
private bool _isAnnotationsCaptured ;
56
-
54
+
57
55
/// <summary>
58
56
/// Tracing namespace
59
57
/// </summary>
60
- private string _namespace ;
61
-
58
+ private readonly string _namespace ;
59
+
62
60
/// <summary>
63
61
/// The capture mode
64
62
/// </summary>
65
- private TracingCaptureMode _captureMode ;
63
+ private readonly TracingCaptureMode _captureMode ;
64
+
65
+ /// <summary>
66
+ /// The segment name
67
+ /// </summary>
68
+ private readonly string _segmentName ;
66
69
67
70
/// <summary>
68
- /// Initializes a new instance
71
+ /// Initializes a new instance of the <see cref="TracingAspectHandler" /> class.
69
72
/// </summary>
70
- public TracingAspect ( )
73
+ /// <param name="segmentName">Name of the segment.</param>
74
+ /// <param name="nameSpace">The namespace.</param>
75
+ /// <param name="captureMode">The capture mode.</param>
76
+ /// <param name="powertoolsConfigurations">The Powertools for AWS Lambda (.NET) configurations.</param>
77
+ /// <param name="xRayRecorder">The X-Ray recorder.</param>
78
+ internal TracingAspectHandler
79
+ (
80
+ string segmentName ,
81
+ string nameSpace ,
82
+ TracingCaptureMode captureMode ,
83
+ IPowertoolsConfigurations powertoolsConfigurations ,
84
+ IXRayRecorder xRayRecorder
85
+ )
71
86
{
72
- _xRayRecorder = XRayRecorder . Instance ;
73
- _powertoolsConfigurations = PowertoolsConfigurations . Instance ;
87
+ _segmentName = segmentName ;
88
+ _namespace = nameSpace ;
89
+ _captureMode = captureMode ;
90
+ _powertoolsConfigurations = powertoolsConfigurations ;
91
+ _xRayRecorder = xRayRecorder ;
74
92
}
75
93
76
94
/// <summary>
77
- /// the code is executed instead of the target method.
78
- /// The call to original method is wrapped around the following code
79
- /// the original code is called with var result = target(args);
95
+ /// Handles the <see cref="E:Entry" /> event.
80
96
/// </summary>
81
- /// <param name="name"></param>
82
- /// <param name="args"></param>
83
- /// <param name="target"></param>
84
- /// <param name="triggers"></param>
85
- /// <returns></returns>
86
- [ Advice ( Kind . Around ) ]
87
- public object Around (
88
- [ Argument ( Source . Name ) ] string name ,
89
- [ Argument ( Source . Arguments ) ] object [ ] args ,
90
- [ Argument ( Source . Target ) ] Func < object [ ] , object > target ,
91
- [ Argument ( Source . Triggers ) ] Attribute [ ] triggers )
97
+ /// <param name="eventArgs">
98
+ /// The <see cref="T:AWS.Lambda.Powertools.Aspects.AspectEventArgs" /> instance containing the
99
+ /// event data.
100
+ /// </param>
101
+ public void OnEntry ( AspectEventArgs eventArgs )
92
102
{
93
- // Before running Function
94
-
95
- var trigger = triggers . OfType < TracingAttribute > ( ) . First ( ) ;
96
- try
97
- {
98
- if ( TracingDisabled ( ) )
99
- return target ( args ) ;
100
-
101
- _namespace = trigger . Namespace ;
102
-
103
- var segmentName = ! string . IsNullOrWhiteSpace ( trigger . SegmentName ) ? trigger . SegmentName : $ "## { name } ";
104
- var nameSpace = GetNamespace ( ) ;
105
-
106
- _xRayRecorder . BeginSubsegment ( segmentName ) ;
107
- _xRayRecorder . SetNamespace ( nameSpace ) ;
108
-
109
- if ( _captureAnnotations )
110
- {
111
- _xRayRecorder . AddAnnotation ( "ColdStart" , _isColdStart ) ;
112
-
113
- _captureAnnotations = false ;
114
- _isAnnotationsCaptured = true ;
115
-
116
- if ( _powertoolsConfigurations . IsServiceDefined )
117
- _xRayRecorder . AddAnnotation ( "Service" , _powertoolsConfigurations . Service ) ;
118
- }
119
-
120
- _isColdStart = false ;
103
+ if ( TracingDisabled ( ) )
104
+ return ;
121
105
122
- // return of the handler
123
- var result = target ( args ) ;
106
+ var segmentName = ! string . IsNullOrWhiteSpace ( _segmentName ) ? _segmentName : $ "## { eventArgs . Name } " ;
107
+ var nameSpace = GetNamespace ( ) ;
124
108
125
- // must get capture after all subsegments run
126
- _captureMode = trigger . CaptureMode ;
109
+ _xRayRecorder . BeginSubsegment ( segmentName ) ;
110
+ _xRayRecorder . SetNamespace ( nameSpace ) ;
127
111
128
- if ( CaptureResponse ( ) )
129
- {
130
- _xRayRecorder . AddMetadata
131
- (
132
- nameSpace ,
133
- $ "{ name } response",
134
- result
135
- ) ;
136
- }
137
-
138
- // after
139
- return result ;
140
- }
141
- catch ( Exception e )
112
+ if ( _captureAnnotations )
142
113
{
143
- _captureMode = trigger . CaptureMode ;
144
- HandleException ( e , name ) ;
145
- throw ;
114
+ _xRayRecorder . AddAnnotation ( "ColdStart" , _isColdStart ) ;
115
+
116
+ _captureAnnotations = false ;
117
+ _isAnnotationsCaptured = true ;
118
+
119
+ if ( _powertoolsConfigurations . IsServiceDefined )
120
+ _xRayRecorder . AddAnnotation ( "Service" , _powertoolsConfigurations . Service ) ;
146
121
}
122
+
123
+ _isColdStart = false ;
147
124
}
148
125
149
126
/// <summary>
150
- /// the code is injected after the method ends .
127
+ /// Called when [success] .
151
128
/// </summary>
152
- [ Advice ( Kind . After ) ]
153
- public void OnExit ( )
129
+ /// <param name="eventArgs">
130
+ /// The <see cref="T:AWS.Lambda.Powertools.Aspects.AspectEventArgs" /> instance containing the
131
+ /// event data.
132
+ /// </param>
133
+ /// <param name="result">The result.</param>
134
+ public void OnSuccess ( AspectEventArgs eventArgs , object result )
154
135
{
155
- if ( TracingDisabled ( ) )
156
- return ;
157
-
158
- if ( _isAnnotationsCaptured )
159
- _captureAnnotations = true ;
160
-
161
- _xRayRecorder . EndSubsegment ( ) ;
136
+ if ( CaptureResponse ( ) )
137
+ {
138
+ var nameSpace = GetNamespace ( ) ;
139
+
140
+ _xRayRecorder . AddMetadata
141
+ (
142
+ nameSpace ,
143
+ $ "{ eventArgs . Name } response",
144
+ result
145
+ ) ;
146
+ }
162
147
}
163
148
164
149
/// <summary>
165
- /// Code that handles when exceptions occur in the client method
150
+ /// Called when [exception].
166
151
/// </summary>
167
- /// <param name="exception"></param>
168
- /// <param name="name"></param>
169
- private void HandleException ( Exception exception , string name )
152
+ /// <param name="eventArgs">
153
+ /// The <see cref="T:AWS.Lambda.Powertools.Aspects.AspectEventArgs" /> instance containing the
154
+ /// event data.
155
+ /// </param>
156
+ /// <param name="exception">The exception.</param>
157
+ public void OnException ( AspectEventArgs eventArgs , Exception exception )
170
158
{
171
159
if ( CaptureError ( ) )
172
160
{
173
161
var nameSpace = GetNamespace ( ) ;
174
-
162
+
175
163
var sb = new StringBuilder ( ) ;
176
164
sb . AppendLine ( $ "Exception type: { exception . GetType ( ) } ") ;
177
165
sb . AppendLine ( $ "Exception message: { exception . Message } ") ;
@@ -185,48 +173,45 @@ private void HandleException(Exception exception, string name)
185
173
sb . AppendLine ( $ "Stack trace: { exception . InnerException . StackTrace } ") ;
186
174
sb . AppendLine ( "---END Inner Exception" ) ;
187
175
}
188
-
176
+
189
177
_xRayRecorder . AddMetadata
190
178
(
191
179
nameSpace ,
192
- $ "{ name } error",
180
+ $ "{ eventArgs . Name } error",
193
181
sb . ToString ( )
194
182
) ;
195
183
}
196
184
197
- // // The purpose of ExceptionDispatchInfo.Capture is to capture a potentially mutating exception's StackTrace at a point in time:
198
- // // https://learn.microsoft.com/en-us/dotnet/standard/exceptions/best-practices-for-exceptions#capture-exceptions-to-rethrow-later
185
+ // The purpose of ExceptionDispatchInfo.Capture is to capture a potentially mutating exception's StackTrace at a point in time:
186
+ // https://learn.microsoft.com/en-us/dotnet/standard/exceptions/best-practices-for-exceptions#capture-exceptions-to-rethrow-later
199
187
ExceptionDispatchInfo . Capture ( exception ) . Throw ( ) ;
200
188
}
201
189
202
190
/// <summary>
203
- /// Gets the namespace .
191
+ /// Handles the <see cref="E:Exit" /> event .
204
192
/// </summary>
205
- /// <returns>System.String.</returns>
206
- private string GetNamespace ( )
193
+ /// <param name="eventArgs">
194
+ /// The <see cref="T:AWS.Lambda.Powertools.Aspects.AspectEventArgs" /> instance containing the
195
+ /// event data.
196
+ /// </param>
197
+ public void OnExit ( AspectEventArgs eventArgs )
207
198
{
208
- return ! string . IsNullOrWhiteSpace ( _namespace ) ? _namespace : _powertoolsConfigurations . Service ;
199
+ if ( TracingDisabled ( ) )
200
+ return ;
201
+
202
+ if ( _isAnnotationsCaptured )
203
+ _captureAnnotations = true ;
204
+
205
+ _xRayRecorder . EndSubsegment ( ) ;
209
206
}
210
207
211
208
/// <summary>
212
- /// Method that checks if tracing is disabled
209
+ /// Gets the namespace.
213
210
/// </summary>
214
- /// <returns></returns>
215
- private bool TracingDisabled ( )
211
+ /// <returns>System.String. </returns>
212
+ private string GetNamespace ( )
216
213
{
217
- if ( _powertoolsConfigurations . TracingDisabled )
218
- {
219
- Console . WriteLine ( "Tracing has been disabled via env var POWERTOOLS_TRACE_DISABLED" ) ;
220
- return true ;
221
- }
222
-
223
- if ( ! _powertoolsConfigurations . IsLambdaEnvironment )
224
- {
225
- Console . WriteLine ( "Running outside Lambda environment; disabling Tracing" ) ;
226
- return true ;
227
- }
228
-
229
- return false ;
214
+ return ! string . IsNullOrWhiteSpace ( _namespace ) ? _namespace : _powertoolsConfigurations . Service ;
230
215
}
231
216
232
217
/// <summary>
@@ -235,6 +220,9 @@ private bool TracingDisabled()
235
220
/// <returns><c>true</c> if tracing should capture responses, <c>false</c> otherwise.</returns>
236
221
private bool CaptureResponse ( )
237
222
{
223
+ if ( TracingDisabled ( ) )
224
+ return false ;
225
+
238
226
switch ( _captureMode )
239
227
{
240
228
case TracingCaptureMode . EnvironmentVariable :
@@ -255,9 +243,9 @@ private bool CaptureResponse()
255
243
/// <returns><c>true</c> if tracing should capture errors, <c>false</c> otherwise.</returns>
256
244
private bool CaptureError ( )
257
245
{
258
- if ( TracingDisabled ( ) )
246
+ if ( TracingDisabled ( ) )
259
247
return false ;
260
-
248
+
261
249
switch ( _captureMode )
262
250
{
263
251
case TracingCaptureMode . EnvironmentVariable :
@@ -271,7 +259,28 @@ private bool CaptureError()
271
259
return false ;
272
260
}
273
261
}
262
+
263
+ /// <summary>
264
+ /// Tracing disabled.
265
+ /// </summary>
266
+ /// <returns><c>true</c> if tracing is disabled, <c>false</c> otherwise.</returns>
267
+ private bool TracingDisabled ( )
268
+ {
269
+ if ( _powertoolsConfigurations . TracingDisabled )
270
+ {
271
+ Console . WriteLine ( "Tracing has been disabled via env var POWERTOOLS_TRACE_DISABLED" ) ;
272
+ return true ;
273
+ }
274
+
275
+ if ( ! _powertoolsConfigurations . IsLambdaEnvironment )
276
+ {
277
+ Console . WriteLine ( "Running outside Lambda environment; disabling Tracing" ) ;
278
+ return true ;
279
+ }
274
280
281
+ return false ;
282
+ }
283
+
275
284
/// <summary>
276
285
/// Resets static variables for test.
277
286
/// </summary>
@@ -280,4 +289,4 @@ internal static void ResetForTest()
280
289
_isColdStart = true ;
281
290
_captureAnnotations = true ;
282
291
}
283
- }
292
+ }
0 commit comments