11/*
22 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3- *
3+ *
44 * Licensed under the Apache License, Version 2.0 (the "License").
55 * You may not use this file except in compliance with the License.
66 * A copy of the License is located at
7- *
7+ *
88 * http://aws.amazon.com/apache2.0
9- *
9+ *
1010 * or in the "license" file accompanying this file. This file is distributed
1111 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212 * express or implied. See the License for the specific language governing
1313 * permissions and limitations under the License.
1414 */
1515
1616using System ;
17- using System . Linq ;
1817using System . Runtime . ExceptionServices ;
1918using System . Text ;
20- using AspectInjector . Broker ;
2119using AWS . Lambda . Powertools . Common ;
2220
2321namespace AWS . Lambda . Powertools . Tracing . Internal ;
2422
2523/// <summary>
26- /// This aspect will automatically trace all function handlers .
27- /// Scope.Global is singleton
24+ /// Class TracingAspectHandler .
25+ /// Implements the <see cref="IMethodAspectHandler" />
2826/// </summary>
29- [ Aspect ( Scope . Global ) ]
30- public class TracingAspect
27+ /// <seealso cref="IMethodAspectHandler" />
28+ internal class TracingAspectHandler : IMethodAspectHandler
3129{
3230 /// <summary>
3331 /// The Powertools for AWS Lambda (.NET) configurations
@@ -48,130 +46,120 @@ public class TracingAspect
4846 /// If true, capture annotations
4947 /// </summary>
5048 private static bool _captureAnnotations = true ;
51-
49+
5250 /// <summary>
5351 /// If true, annotations have been captured
5452 /// </summary>
5553 private bool _isAnnotationsCaptured ;
56-
54+
5755 /// <summary>
5856 /// Tracing namespace
5957 /// </summary>
60- private string _namespace ;
61-
58+ private readonly string _namespace ;
59+
6260 /// <summary>
6361 /// The capture mode
6462 /// </summary>
65- private TracingCaptureMode _captureMode ;
63+ private readonly TracingCaptureMode _captureMode ;
64+
65+ /// <summary>
66+ /// The segment name
67+ /// </summary>
68+ private readonly string _segmentName ;
6669
6770 /// <summary>
68- /// Initializes a new instance
71+ /// Initializes a new instance of the <see cref="TracingAspectHandler" /> class.
6972 /// </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+ )
7186 {
72- _xRayRecorder = XRayRecorder . Instance ;
73- _powertoolsConfigurations = PowertoolsConfigurations . Instance ;
87+ _segmentName = segmentName ;
88+ _namespace = nameSpace ;
89+ _captureMode = captureMode ;
90+ _powertoolsConfigurations = powertoolsConfigurations ;
91+ _xRayRecorder = xRayRecorder ;
7492 }
7593
7694 /// <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.
8096 /// </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 )
92102 {
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 ;
121105
122- // return of the handler
123- var result = target ( args ) ;
106+ var segmentName = ! string . IsNullOrWhiteSpace ( _segmentName ) ? _segmentName : $ "## { eventArgs . Name } " ;
107+ var nameSpace = GetNamespace ( ) ;
124108
125- // must get capture after all subsegments run
126- _captureMode = trigger . CaptureMode ;
109+ _xRayRecorder . BeginSubsegment ( segmentName ) ;
110+ _xRayRecorder . SetNamespace ( nameSpace ) ;
127111
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 )
142113 {
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 ) ;
146121 }
122+
123+ _isColdStart = false ;
147124 }
148125
149126 /// <summary>
150- /// the code is injected after the method ends .
127+ /// Called when [success] .
151128 /// </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 )
154135 {
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+ }
162147 }
163148
164149 /// <summary>
165- /// Code that handles when exceptions occur in the client method
150+ /// Called when [exception].
166151 /// </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 )
170158 {
171159 if ( CaptureError ( ) )
172160 {
173161 var nameSpace = GetNamespace ( ) ;
174-
162+
175163 var sb = new StringBuilder ( ) ;
176164 sb . AppendLine ( $ "Exception type: { exception . GetType ( ) } ") ;
177165 sb . AppendLine ( $ "Exception message: { exception . Message } ") ;
@@ -185,48 +173,45 @@ private void HandleException(Exception exception, string name)
185173 sb . AppendLine ( $ "Stack trace: { exception . InnerException . StackTrace } ") ;
186174 sb . AppendLine ( "---END Inner Exception" ) ;
187175 }
188-
176+
189177 _xRayRecorder . AddMetadata
190178 (
191179 nameSpace ,
192- $ "{ name } error",
180+ $ "{ eventArgs . Name } error",
193181 sb . ToString ( )
194182 ) ;
195183 }
196184
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
199187 ExceptionDispatchInfo . Capture ( exception ) . Throw ( ) ;
200188 }
201189
202190 /// <summary>
203- /// Gets the namespace .
191+ /// Handles the <see cref="E:Exit" /> event .
204192 /// </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 )
207198 {
208- return ! string . IsNullOrWhiteSpace ( _namespace ) ? _namespace : _powertoolsConfigurations . Service ;
199+ if ( TracingDisabled ( ) )
200+ return ;
201+
202+ if ( _isAnnotationsCaptured )
203+ _captureAnnotations = true ;
204+
205+ _xRayRecorder . EndSubsegment ( ) ;
209206 }
210207
211208 /// <summary>
212- /// Method that checks if tracing is disabled
209+ /// Gets the namespace.
213210 /// </summary>
214- /// <returns></returns>
215- private bool TracingDisabled ( )
211+ /// <returns>System.String. </returns>
212+ private string GetNamespace ( )
216213 {
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 ;
230215 }
231216
232217 /// <summary>
@@ -235,6 +220,9 @@ private bool TracingDisabled()
235220 /// <returns><c>true</c> if tracing should capture responses, <c>false</c> otherwise.</returns>
236221 private bool CaptureResponse ( )
237222 {
223+ if ( TracingDisabled ( ) )
224+ return false ;
225+
238226 switch ( _captureMode )
239227 {
240228 case TracingCaptureMode . EnvironmentVariable :
@@ -255,9 +243,9 @@ private bool CaptureResponse()
255243 /// <returns><c>true</c> if tracing should capture errors, <c>false</c> otherwise.</returns>
256244 private bool CaptureError ( )
257245 {
258- if ( TracingDisabled ( ) )
246+ if ( TracingDisabled ( ) )
259247 return false ;
260-
248+
261249 switch ( _captureMode )
262250 {
263251 case TracingCaptureMode . EnvironmentVariable :
@@ -271,7 +259,28 @@ private bool CaptureError()
271259 return false ;
272260 }
273261 }
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+ }
274280
281+ return false ;
282+ }
283+
275284 /// <summary>
276285 /// Resets static variables for test.
277286 /// </summary>
@@ -280,4 +289,4 @@ internal static void ResetForTest()
280289 _isColdStart = true ;
281290 _captureAnnotations = true ;
282291 }
283- }
292+ }
0 commit comments