Beispiel #1
0
        public void TestSubsegment()
        {
            _recorder.BeginSubsegment("subsegment1");
            Subsegment    subsegment1   = (Subsegment)AWSXRayRecorder.Instance.TraceContext.GetEntity();
            FacadeSegment facadeSegment = (FacadeSegment)subsegment1.RootSegment;

            _recorder.EndSubsegment();
            Assert.AreEqual(typeof(LambdaContextContainer), AWSXRayRecorder.Instance.TraceContext.GetType());
            Assert.AreEqual(facadeSegment.GetType(), typeof(FacadeSegment));
            Assert.IsFalse(facadeSegment.Subsegments.Contains(subsegment1));         // only subsegment is streamed
            Assert.IsFalse(AWSXRayRecorder.Instance.TraceContext.IsEntityPresent()); // facade segment is cleared from AWSXRayRecorder.Instance.TraceContext
        }
Beispiel #2
0
        /// <summary>
        /// Processes Begin request by starting subsegment.
        /// </summary>
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            var    request = executionContext.RequestContext.Request;
            Entity entity  = null;

            try
            {
                entity = _recorder.GetEntity();
            }
            catch (EntityNotAvailableException e)
            {
                _recorder.TraceContext.HandleEntityMissing(_recorder, e, "Cannot get entity while processing AWS SDK request");
            }

            var serviceName = RemoveAmazonPrefixFromServiceName(request.ServiceName);

            _recorder.BeginSubsegment(AWSXRaySDKUtils.FormatServiceName(serviceName));
            _recorder.SetNamespace("aws");

            entity = entity == null ? null : _recorder.GetEntity();

            if (TraceHeader.TryParse(entity, out TraceHeader traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }
        }
        /// <summary>
        /// Processes HTTP request.
        /// </summary>
        private void ProcessHTTPRequest(HttpContext context)
        {
            HttpRequest request      = context.Request;
            string      headerString = null;

            if (request.Headers.TryGetValue(TraceHeader.HeaderKey, out StringValues headerValue))
            {
                if (headerValue.ToArray().Length >= 1)
                {
                    headerString = headerValue.ToArray()[0];
                }
            }

            // Trace header doesn't exist, which means this is the root node. Create a new traceId and inject the trace header.
            if (!TraceHeader.TryParse(headerString, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid : ({0}). Injecting a new one.", headerString);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                string serviceName = request.Host.Host;
                string url         = request.Path;
                string method      = request.Method;
                traceHeader.Sampled = _recorder.SamplingStrategy.Sample(serviceName, url, method);
            }

            if (AWSXRayRecorder.Instance.IsLambda())
            {
                _recorder.BeginSubsegment(SegmentNamingStrategy.GetSegmentName(request));
            }
            else
            {
                _recorder.BeginSegment(SegmentNamingStrategy.GetSegmentName(request), traceHeader.RootTraceId, traceHeader.ParentId, traceHeader.Sampled);
            }

            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                var requestAttributes = new Dictionary <string, object>();
                PopulateRequestAttributes(request, requestAttributes);
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            if (isSampleDecisionRequested)
            {
                context.Response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString()); // Its recommended not to modify response header after _next.Invoke() call
            }
        }
        public async Task <NumberPlateTrigger> FunctionHandler(S3Event evnt, ILambdaContext context)
        {
            var s3Event = evnt.Records?[0].S3;

            context.Logger.LogLine("EVENT Received: " + JsonConvert.SerializeObject(s3Event));

            if (regExNumberPlate == null)
            {
                context.Logger.LogLine("regExNumberPlate is not yet populated. Calling getNumberPlateFromSecretsManager()...");
                regExNumberPlate = await getNumberPlateFromSecretsManager(context);

                context.Logger.LogLine("regExNumberPlate is " + regExNumberPlate);
            }

            NumberPlateTrigger result = new NumberPlateTrigger
            {
                bucket        = s3Event.Bucket.Name,
                key           = s3Event.Object.Key,
                contentType   = "",
                contentLength = s3Event.Object.Size,
                charge        = int.Parse(Environment.GetEnvironmentVariable("TollgateCharge")),
                numberPlate   = new NumberPlate()
                {
                    numberPlateRegEx = this.regExNumberPlate,
                    detected         = false
                }
            };

            AWSXRayRecorder recorder = AWSXRayRecorder.Instance;

            recorder.BeginSubsegment("TollGantry::Detect Number Plate in Captured Image");
            recorder.AddMetadata("bucket", s3Event.Bucket.Name);
            recorder.AddMetadata("key", s3Event.Object.Key);
            recorder.AddMetadata("regex", this.regExNumberPlate);
            //
            // TODO: Call Rekognition to detect text in the captured image
            //
            recorder.EndSubsegment();

            //
            // Kick off the step function
            //
            context.Logger.LogLine("Starting the state machine");
            IAmazonStepFunctions stepFunctionsClient = new AmazonStepFunctionsClient();
            await stepFunctionsClient.StartExecutionAsync(new StartExecutionRequest()
            {
                StateMachineArn = Environment.GetEnvironmentVariable("NumberPlateProcessStateMachine"), Input = JsonConvert.SerializeObject(result)
            });

            context.Logger.LogLine("State machine started");
            return(result);
        }
Beispiel #5
0
        /// <inheritdoc />
        public async Task <TResult> InterceptAsync <TResult>(Func <Task <TResult> > method, DbCommand command)
        {
            _recorder.BeginSubsegment(BuildSubsegmentName(command));
            try
            {
                _recorder.SetNamespace("remote");
                var ret = await method();

                CollectSqlInformation(command);

                return(ret);
            }
            catch (Exception e)
            {
                _recorder.AddException(e);
                throw;
            }
            finally
            {
                _recorder.EndSubsegment();
            }
        }
        /// <summary>
        /// Processes Begin request by starting subsegment.
        /// </summary>
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            var request = executionContext.RequestContext.Request;

            if (TraceHeader.TryParse(_recorder.GetEntity(), out TraceHeader traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }

            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(request.ServiceName));
            _recorder.SetNamespace("aws");
        }
Beispiel #7
0
        private void ProcessBeginCommand(CommandEventData eventData)
        {
            Entity entity = null;

            try
            {
                entity = _recorder.GetEntity();
            }
            catch (EntityNotAvailableException e)
            {
                _recorder.TraceContext.HandleEntityMissing(_recorder, e, "Cannot get entity while processing start of Entity Framework command.");
            }

            _recorder.BeginSubsegment(BuildSubsegmentName(eventData.Command));
            _recorder.SetNamespace("remote");
            CollectSqlInformation(eventData);
        }
        public void TestTryParseSubsegment()
        {
            using (var recorder = new AWSXRayRecorder())
            {
                recorder.BeginSegment("TraceHeaderTest", TraceId);
                recorder.BeginSubsegment("subjob");
                var subsegment = TraceContext.GetEntity();

                TraceHeader header;
                Assert.IsTrue(TraceHeader.TryParse(subsegment, out header));

                Assert.AreEqual(TraceId, header.RootTraceId);
                Assert.AreEqual(subsegment.Id, header.ParentId);
                Assert.AreEqual(SampleDecision.Sampled, header.Sampled);

                recorder.EndSubsegment();
                recorder.EndSegment();
            }
        }
Beispiel #9
0
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            var    request = executionContext.RequestContext.Request;
            Entity entity  = null;

            try
            {
                entity = _recorder.GetEntity();
            }
            catch (EntityNotAvailableException e)
            {
                _recorder.TraceContext.HandleEntityMissing(_recorder, e, "Cannot get entity while processing AWS SDK request");
            }

            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(request.ServiceName));
            _recorder.SetNamespace("aws");

            entity = entity == null ? null : _recorder.GetEntity();

            if (TraceHeader.TryParse(entity, out var traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();

                if (request.Parameters.Any(p => p.Value == "AWSTraceHeader"))
                {
                    return;
                }

                var index = request
                            .Parameters
                            .Where(x => x.Key.StartsWith("MessageSystemAttribute"))
                            .Select(x => int.TryParse(x.Value.Split('.')[1], out var idx) ? idx : 0)
                            .Union(new[] { 0 })
                            .Max() + 1;

                request.Parameters.Add("MessageSystemAttribute" + "." + index + "." + "Name",
                                       StringUtils.FromString("AWSTraceHeader"));
                request.Parameters.Add("MessageSystemAttribute" + "." + index + "." + "Value.DataType",
                                       StringUtils.FromString("String"));
                request.Parameters.Add("MessageSystemAttribute" + "." + index + "." + "Value" + "." + "StringValue",
                                       StringUtils.FromString(traceHeader.ToString()));
            }
        }
Beispiel #10
0
        private void BeforeRequestEventHandler(object sender, RequestEventArgs e)
        {
            var args = e as WebServiceRequestEventArgs;

            if (args == null)
            {
                _logger.DebugFormat("Failed to handle BeforeRequestEvent, because e can't be converted to WebServiceRequestEventArgs.");
                return;
            }
            if (TraceHeader.TryParse(_recorder.GetEntity(), out TraceHeader traceHeader))
            {
                args.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }
            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(args.ServiceName));
            _recorder.SetNamespace("aws");
        }
Beispiel #11
0
        public void TestLogErrorModeForContextMissingStrategy()
        {
            using (var recorder = new AWSXRayRecorder())
            {
                recorder.ContextMissingStrategy = ContextMissingStrategy.LOG_ERROR;

                recorder.EndSegment();
                recorder.BeginSubsegment("no segment");
                recorder.EndSubsegment();
                recorder.SetNamespace("dummy namespace");
                recorder.AddAnnotation("key", "value");
                recorder.AddHttpInformation("key", "value");
                recorder.MarkError();
                recorder.MarkFault();
                recorder.MarkThrottle();
                recorder.AddException(new ArgumentNullException());
                recorder.AddPrecursorId(Entity.GenerateId());
                recorder.AddSqlInformation("sqlKey", "value");
                recorder.AddMetadata("key", "value");
            }
        }
        /// <summary>
        /// Processes Begin request by starting subsegment.
        /// </summary>
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            if (AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                _logger.DebugFormat("X-Ray tracing is disabled, do not handle AWSSDK request.");
                return;
            }

            var request = executionContext.RequestContext.Request;

            if (TraceHeader.TryParse(TraceContext.GetEntity(), out TraceHeader traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }

            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(request.ServiceName));
            _recorder.SetNamespace("aws");
        }
        private TResult Intercept <TResult>(Func <TResult> method)
        {
            AWSXRayRecorder recorder = AWSXRayRecorder.Instance;

            recorder.BeginSubsegment(Connection.Database + "@" + SqlUtil.RemovePortNumberFromDataSource(Connection.DataSource));
            try
            {
                recorder.SetNamespace("remote");
                var ret = method();
                CollectSqlInformation();

                return(ret);
            }
            catch (Exception e)
            {
                recorder.AddException(e);
                throw;
            }
            finally
            {
                recorder.EndSubsegment();
            }
        }
Beispiel #14
0
        public void TestSyncCreateSegmentAndSubsegments()
        {
            _recorder.BeginSegment("parent", TraceId);

            Segment parent = (Segment)AWSXRayRecorder.Instance.TraceContext.GetEntity();

            _recorder.BeginSubsegment("child");
            Subsegment child = (Subsegment)AWSXRayRecorder.Instance.TraceContext.GetEntity();

            _recorder.EndSubsegment();
            Assert.ReferenceEquals(AWSXRayRecorder.Instance.TraceContext.GetEntity(), parent);

            _recorder.EndSegment();

            Assert.ReferenceEquals(parent, child.Parent);
            Assert.IsTrue(parent.Subsegments.Contains(child));
        }
Beispiel #15
0
 /// <summary>
 /// Process command to begin subsegment.
 /// </summary>
 /// <param name="command">Instance of <see cref="DbCommand"/>.</param>
 /// <param name="collectSqlQueriesOverride">Nullable to indicate whether to collect sql query text or not.</param>
 internal static void ProcessBeginCommand(DbCommand command, bool?collectSqlQueriesOverride)
 {
     _recorder.BeginSubsegment(BuildSubsegmentName(command));
     _recorder.SetNamespace("remote");
     CollectSqlInformation(command, collectSqlQueriesOverride);
 }
        /// <summary>
        /// Process http request.
        /// </summary>
        internal static void ProcessRequest(HttpContext httpContext)
        {
            HttpRequest request      = httpContext.Request;
            string      headerString = null;

            if (request.Headers.TryGetValue(TraceHeader.HeaderKey, out StringValues headerValue))
            {
                if (headerValue.Count >= 1)
                {
                    headerString = headerValue[0];
                }
            }

            if (!TraceHeader.TryParse(headerString, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid : ({0}). Injecting a new one.", headerString);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            var  segmentName = SegmentNamingStrategy.GetSegmentName(request);
            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            string ruleName = null;

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                string           host           = request.Host.Host;
                string           url            = request.Path;
                string           method         = request.Method;
                SamplingInput    samplingInput  = new SamplingInput(host, url, method, segmentName, _recorder.Origin);
                SamplingResponse sampleResponse = _recorder.SamplingStrategy.ShouldTrace(samplingInput);
                traceHeader.Sampled = sampleResponse.SampleDecision;
                ruleName            = sampleResponse.RuleName;
            }

            if (AWSXRayRecorder.IsLambda())
            {
                _recorder.BeginSubsegment(segmentName);
            }
            else
            {
                SamplingResponse samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled); // get final ruleName and SampleDecision
                _recorder.BeginSegment(SegmentNamingStrategy.GetSegmentName(request), traceHeader.RootTraceId, traceHeader.ParentId, samplingResponse);
            }

            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                var requestAttributes = PopulateRequestAttributes(request);
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            // Mark the segment as auto-instrumented
            AgentUtil.AddAutoInstrumentationMark();

            if (isSampleDecisionRequested)
            {
                httpContext.Response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString()); // Its recommended not to modify response header after _next.Invoke() call
            }
        }
Beispiel #17
0
        public async Task <NumberPlateTrigger> FunctionHandler(S3Event evnt, ILambdaContext context)
        {
            var s3Event = evnt.Records?[0].S3;

            context.Logger.LogLine("EVENT Received: " + JsonConvert.SerializeObject(s3Event));

            if (regExNumberPlate == null)
            {
                context.Logger.LogLine("regExNumberPlate is not yet populated. Calling getNumberPlateFromSecretsManager()...");
                regExNumberPlate = await getNumberPlateFromSecretsManager(context);

                context.Logger.LogLine("regExNumberPlate is " + regExNumberPlate);
            }

            //var response = await this.S3Client.GetObjectMetadataAsync(s3Event.Bucket.Name, s3Event.Object.Key);
            //return response.Headers.ContentType;

            NumberPlateTrigger result = new NumberPlateTrigger
            {
                bucket        = s3Event.Bucket.Name,
                key           = s3Event.Object.Key,
                contentType   = "",
                contentLength = s3Event.Object.Size,
                charge        = int.Parse(Environment.GetEnvironmentVariable("TollgateCharge")),
                numberPlate   = new NumberPlate()
                {
                    numberPlateRegEx = this.regExNumberPlate,
                    detected         = false
                }
            };

            recorder.BeginSubsegment("TollGantry::Detect Number Plate in Captured Image");
            recorder.AddMetadata("bucket", s3Event.Bucket.Name);
            recorder.AddMetadata("key", s3Event.Object.Key);
            recorder.AddMetadata("regex", this.regExNumberPlate);

            S3Object s3Object = new S3Object();

            s3Object.Bucket = s3Event.Bucket.Name;
            s3Object.Name   = s3Event.Object.Key;
            DetectTextRequest detectTextReq = new DetectTextRequest {
                Image = new Image {
                    S3Object = s3Object
                }
            };

            context.Logger.LogLine("Calling Rekognition ... ");
            DetectTextResponse detectTextResponse = await rekognitionClient.DetectTextAsync(detectTextReq);

            context.Logger.LogLine($"Response from Rekognition: {JsonConvert.SerializeObject(detectTextResponse)}");

            // Check if the a valid number was detected...
            foreach (var textItem in detectTextResponse.TextDetections)
            {
                if (!result.numberPlate.detected && textItem.Type.Value == "LINE" && textItem.Confidence > float.Parse(Environment.GetEnvironmentVariable("RekognitionTextMinConfidence")))
                {
                    Regex           regex   = new Regex(regExNumberPlate);
                    MatchCollection matches = regex.Matches(textItem.DetectedText);
                    context.Logger.LogLine($"Matches collection: {matches.Count}");
                    string plateNumber = "";
                    foreach (Match match in matches)
                    {
                        plateNumber += (match.Groups[1].Value + match.Groups[2].Value);
                    }
                    if (!string.IsNullOrEmpty(plateNumber))
                    {
                        result.numberPlate.detected          = true;
                        result.numberPlate.confidence        = textItem.Confidence;
                        result.numberPlate.numberPlateString = plateNumber;
                        context.Logger.LogLine($"A valid plate number was detected ({result.numberPlate.numberPlateString})");
                    }
                }
            }

            recorder.EndSubsegment();

            //
            // At this point, we either know it is a valid number plate
            // or it couldn't be determined with adequate confidence
            // so we need manual intervention
            //

            //
            // Kick off the step function
            //

            context.Logger.LogLine("Starting the state machine");
            //TODO: add code to start the state machine
            context.Logger.LogLine("State machine started");

            return(result);
        }