示例#1
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            //reader should be positioned at the start of the object "{"
            if (reader.TokenType != JsonToken.StartObject)
            {
                throw new DistributedTraceAcceptPayloadParseException(
                          $"expected to find beginning of DistributedTracePayload object. Found token: {Enum.GetName(typeof(JsonToken), reader.TokenType)}");
            }

            var parsedPayload = new DistributedTracePayload();
            var jObject       = JObject.Load(reader);

            foreach (var constraint in _validationConstraints)
            {
                constraint.ParseAndThrowOnFailure(jObject, parsedPayload);
            }

            if (string.IsNullOrEmpty(parsedPayload.Guid) && string.IsNullOrEmpty(parsedPayload.TransactionId))
            {
                throw new DistributedTraceAcceptPayloadParseException(
                          $"expected either the Guid or the TransactionId to be present. Found: neither");
            }

            return(parsedPayload);
        }
        public void DistributedTracePayload_RoundTrip(
            [Values("App", "Mobile")] string type,
            [Values("12345")] string accountId,
            [Values("1111")] string appId,
            [Random(0ul, 0xfffffffffffffffful, 1), Values(ulong.MinValue, ulong.MaxValue)] ulong parentId,
            [Random(0ul, 0xfffffffffffffffful, 1), Values(ulong.MinValue, ulong.MaxValue)] ulong guid,
            [Random(0ul, 0xfffffffffffffffful, 1), Values(ulong.MinValue, ulong.MaxValue)] ulong traceId,
            [Values("56789")] string trustKey,
            [Random(0f, 1.0f, 1), Values(0.0f, 1.0f, 0.1234567f)] float priority,
            [Values(true, false)] bool sampled,
            [Values(new[] { 1970, 1, 1, 0, 0, 1 }, new[] { 2018, 12, 31, 23, 59, 59 })] int[] time,
            [Random(0ul, 0xfffffffffffffffful, 1), Values(ulong.MinValue, ulong.MaxValue)] ulong _transactionId)
        {
            var input = DistributedTracePayload.TryBuildOutgoingPayload(type, accountId, appId, $"{guid:X8}", $"{traceId:X8}", trustKey, priority, sampled,
                                                                        new DateTime(time[0], time[1], time[2], time[3], time[4], time[5], DateTimeKind.Utc), $"{_transactionId:X8}");
            var serialized   = input.ToJson();
            var deserialized = DistributedTracePayload.TryBuildIncomingPayloadFromJson(serialized);

            Assert.That(deserialized.Version, Is.Not.Null);
            Assert.That(deserialized.Version, Has.Exactly(2).Items);
            Assert.That(deserialized.Version[0], Is.EqualTo(0));
            Assert.That(deserialized.Version[1], Is.EqualTo(1));

            Assert.That(deserialized.Type, Is.EqualTo(input.Type));
            Assert.That(deserialized.AccountId, Is.EqualTo(input.AccountId));
            Assert.That(deserialized.AppId, Is.EqualTo(input.AppId));
            Assert.That(deserialized.Guid, Is.EqualTo(input.Guid));
            Assert.That(deserialized.TraceId, Is.EqualTo(input.TraceId));
            Assert.That(deserialized.TrustKey, Is.EqualTo(input.TrustKey));
            Assert.That(deserialized.Sampled, Is.EqualTo(input.Sampled));
            Assert.That(deserialized.Timestamp, Is.EqualTo(input.Timestamp));
            Assert.That(deserialized.TransactionId, Is.EqualTo(input.TransactionId));
        }
示例#3
0
        public void TryDecodeAndDeserializeDistributedTracePayload_ThrowsException_IfEncodedAsInvalidType()
        {
            // The following base64 string isn't an encoding of a DistributedTracePayload but it is valid base64.
            var encodedString = "eyJ2IjpbMCwxXSwiZCI6eyJEaWZmZXJlbnQiOiJUeXBlIiwidHkiOiJBcHAiLCJhYyI6IjkxMjMiLCJhcCI6IjUxNDI0IiwiaWQiOiI1ZjQ3NGQ2NGI5Y2M5YjJhIiwidHIiOiIzMjIxYmYwOWFhMGJjZjBkIiwidGsiOiIxMjM0NSIsInByIjowLjEyMzQsInNhIjpmYWxzZSwidGkiOjE1Mjk0MjQxMzA2MDMsInR4IjoiMjc4NTZmNzBkM2QzMTRiNyJ9fQ==";

            Assert.Throws <DistributedTraceAcceptPayloadParseException>(() => DistributedTracePayload.TryDecodeAndDeserializeDistributedTracePayload(encodedString));
        }
示例#4
0
        public void TryBuildOutgoingPayload_ReturnsNull_WhenDoesNotContainGuidOrTransactionId(string guid, string transactionId)
        {
            var payload = DistributedTracePayload.TryBuildOutgoingPayload(TransportType, AccountId, AppId, guid, TraceId,
                                                                          TrustKey, Priority, Sampled, Timestamp, transactionId);

            Assert.Null(payload);
        }
示例#5
0
        private bool IsValidPayload(DistributedTracePayload payload)
        {
            if (payload == null)
            {
                return(false);
            }

            return(HasTraceablePayload(payload) && HasTrustedAccountKey(payload));
        }
示例#6
0
        public void TryDecodeAndDeserializeDistributedTracePayload_ThrowsException_IfInvalidVersion()
        {
            var payload = BuildSampleDistributedTracePayload();

            payload.Version = new int[] { 9999, 1 };
            var encodedString = DistributedTracePayload.SerializeAndEncodeDistributedTracePayload(payload);

            Assert.Throws <DistributedTraceAcceptPayloadVersionException>(() => DistributedTracePayload.TryDecodeAndDeserializeDistributedTracePayload(encodedString));
        }
示例#7
0
        public void SerializeAndEncodeDistributedTracePayload_CreatesCorrectEncodedString()
        {
            var payload           = BuildSampleDistributedTracePayload();
            var jsonString        = payload.ToJson();
            var encodedJsonString = Strings.Base64Encode(jsonString);
            var serializedPayload = DistributedTracePayload.SerializeAndEncodeDistributedTracePayload(payload);

            Assert.AreEqual(encodedJsonString, serializedPayload);
        }
        public void TestDistributedTraceInstrinsicsShowUpIn_ErrorEvents_ErrorTraces_SpanEvent_AnalyticEvent()
        {
            var dtPayload = new DistributedTracePayload
            {
                Type          = "App",
                AccountId     = "test-accountid",
                AppId         = "test-appid",
                Guid          = "test-guid",
                TraceId       = "test-traceid",
                TrustKey      = "test-trustkey",
                Priority      = 1.0F,
                Sampled       = true,
                Timestamp     = DateTime.Now,
                TransactionId = "test-transactionid",
            };

            var tags = new Dictionary <string, string>
            {
                { "newrelic", dtPayload.SerializeAndEncodeDistributedTracePayload() }
            };

            var tracer = LambdaTracer.Instance;

            var lambdaPayloadContext = (LambdaPayloadContext)tracer.Extract(BuiltinFormats.TextMap, new TextMapExtractAdapter(tags));

            var startTime = DateTimeOffset.UtcNow;
            var span      = TestUtil.CreateRootSpan("operationName", startTime, new Dictionary <string, object>(), "testGuid", logger: _logger);

            span.RootSpan.DistributedTracingState.SetInboundDistributedTracePayload(lambdaPayloadContext.GetPayload());
            span.RootSpan.DistributedTracingState.SetTransportDurationInMillis(1000);
            span.RootSpan.PrioritySamplingState.Priority = (span.RootSpan.DistributedTracingState.InboundPayload.Priority.HasValue)
                                                        ? span.RootSpan.DistributedTracingState.InboundPayload.Priority.Value
                                                        : LambdaTracer.TracePriorityManager.Create();
            span.RootSpan.PrioritySamplingState.Sampled = span.RootSpan.DistributedTracingState.InboundPayload.Sampled.Value;

            var exception = new CustomException("my exception.", "this is a stack trace.");

            var errorAttributes = CreateSpanErrorAttributes(exception, exception.Message, exception.StackTrace);

            span.Log(errorAttributes);

            span.Finish();

            var deserializedPayload = JsonConvert.DeserializeObject <object[]>(_logger.LastLogMessage);
            var data = TestUtil.DecodeAndDecompressNewRelicPayload(deserializedPayload[3] as string);

            Assert.IsTrue(data.Contains("analytic_event_data"));
            Assert.IsTrue(data.Contains("\"error\":true"));
            Assert.IsTrue(data.Contains("\"error_event_data\":["));
            Assert.IsTrue(data.Contains("\"error_data\":[null,[["));

            Assert.AreEqual(4, TestUtil.CountStringOccurrences(data, "\"parent.type\":\"App\""));
            Assert.AreEqual(4, TestUtil.CountStringOccurrences(data, "\"parent.account\":\"test-accountid\""));
            Assert.AreEqual(4, TestUtil.CountStringOccurrences(data, "\"parent.app\":\"test-appid\""));
            Assert.AreEqual(4, TestUtil.CountStringOccurrences(data, "\"parent.transportType\":\"Unknown\""));
            Assert.AreEqual(4, TestUtil.CountStringOccurrences(data, "\"parent.transportDuration\":1000.0"));
        }
示例#9
0
        private bool HasTraceablePayload(DistributedTracePayload payload)
        {
            if ((payload.Guid == null) && (payload.TransactionId == null))
            {
                Log.Debug("Incoming Guid and TransactionId were null, which is invalid for a Distributed Trace payload.");
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadParseException();

                return(false);
            }

            return(true);
        }
示例#10
0
        private static void ParseVersion(JToken selection, DistributedTracePayload payload)
        {
            payload.Version = selection.ToObject <int[]>();
            var payloadMajorVersion = payload.Version[0];
            var payloadMinorVersion = payload.Version[1];

            if (payloadMajorVersion > DistributedTracePayload.SupportedMajorVersion)
            {
                throw new DistributedTraceAcceptPayloadVersionException(
                          $"unsupported DistributedTracePayload version. Expected: {DistributedTracePayload.SupportedMajorVersion}.{DistributedTracePayload.SupportedMinorVersion}  Found: {payloadMajorVersion}.{payloadMinorVersion}");
            }
        }
示例#11
0
        private bool HasTrustedAccountKey(DistributedTracePayload payload)
        {
            var incomingTrustKey = payload.TrustKey ?? payload.AccountId;
            var isTrusted        = incomingTrustKey == _configurationService.Configuration.TrustedAccountKey;

            if (!isTrusted)
            {
                Log.Debug($"Incoming trustKey or accountId [{incomingTrustKey}] not trusted, distributed trace payload will be ignored.");
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadIgnoredUntrustedAccount();
            }

            return(isTrusted);
        }
示例#12
0
 private static DistributedTracePayload BuildSampleDistributedTracePayload()
 {
     return(DistributedTracePayload.TryBuildOutgoingPayload(
                Type.ToString(),
                AccountId,
                AppId,
                Guid,
                TraceId,
                TrustKey,
                Priority,
                Sampled,
                Timestamp,
                TransactionId));
 }
        public void DistributedTracePayloadWithZeroBasedTimestampThrows()
        {
            var type          = "App";
            var accountId     = "12345";
            var appId         = "1111";
            var parentId      = $"{0xfffffffffffffffful:X9}";
            var guid          = $"{0xfffffffffffffffful:X9}";
            var traceId       = $"{0xfffffffffffffffful:X9}";
            var trustKey      = "56789";
            var priority      = 0f;
            var sampled       = true;
            var time          = new int[] { 1970, 1, 1, 0, 0, 0 };
            var timestamp     = new DateTime(time[0], time[1], time[2], time[3], time[4], time[5], DateTimeKind.Utc);
            var transactionId = $"{0xfffffffffffffffful:X9}";

            var input      = DistributedTracePayload.TryBuildOutgoingPayload(type, accountId, appId, $"{guid:X8}", $"{traceId:X8}", trustKey, priority, sampled, timestamp, transactionId);
            var serialized = input.ToJson();

            Assert.Throws <DistributedTraceAcceptPayloadParseException>(() => DistributedTracePayload.TryBuildIncomingPayloadFromJson(serialized));
        }
示例#14
0
        public void AcceptDistributedTraceHeadersHydratesValidNewRelicPayload()
        {
            var encodedPayload = DistributedTracePayload.SerializeAndEncodeDistributedTracePayload(BuildSampleDistributedTracePayload());

            var headers = new Dictionary <string, string>()
            {
                { NewRelicPayloadHeaderName, encodedPayload }
            };

            var tracingState = TracingState.AcceptDistributedTraceHeaders(carrier: headers, getter: GetHeader, transportType: TransportType.AMQP, agentTrustKey: TrustKey, transactionStartTime: DateTime.UtcNow.Add(TimeSpan.FromMilliseconds(1)));

            Assert.IsNotNull(tracingState);
            Assert.AreEqual(Type, tracingState.Type);
            Assert.AreEqual(AccountId, tracingState.AccountId);
            Assert.AreEqual(AppId, tracingState.AppId);
            Assert.AreEqual(Guid, tracingState.Guid);
            Assert.AreEqual(TraceId, tracingState.TraceId);
            Assert.AreEqual(Priority, tracingState.Priority);
            Assert.AreEqual(Sampled, tracingState.Sampled);
            Assert.AreEqual(TransactionId, tracingState.TransactionId);
            Assert.IsTrue(tracingState.Timestamp != default, $"Timestamp should not be {(DateTime)default}");
示例#15
0
        public void OneTimeSetUp()
        {
            // type, accountId, appId, guid, traceId, trustKey, priority, sampled, timestamp, transactionId
            _dtPayload = new DistributedTracePayload
            {
                Type          = "App",
                AccountId     = "test-accountid",
                AppId         = "test-appid",
                Guid          = "test-guid",
                TraceId       = "test-traceid",
                TrustKey      = "test-trustkey",
                Priority      = 1.0F,
                Sampled       = true,
                Timestamp     = DateTime.Now,
                TransactionId = "test-transactionid"
            };

            _tags = new Dictionary <string, string>
            {
                { "newrelic", _dtPayload.SerializeAndEncodeDistributedTracePayload() }
            };
        }
示例#16
0
        public void Inject <TCarrier>(ISpanContext spanContext, IFormat <TCarrier> format, TCarrier carrier)
        {
            var context = (LambdaSpanContext)spanContext;
            var span    = context.GetSpan();
            var payload = DistributedTracePayload.TryBuildOutgoingPayload(
                type: "App",
                accountId: AccountId,
                appId: PrimaryApplicationId,
                guid: span.Guid(),
                traceId: span.RootSpan.DistributedTracingState.InboundPayload?.TraceId ?? span.RootSpan.TransactionState.TransactionId,
                trustKey: TrustedAccountKey,
                priority: span.RootSpan.PrioritySamplingState.Priority,
                sampled: span.RootSpan.PrioritySamplingState.Sampled,
                timestamp: span.TimeStamp.DateTime,
                transactionId: span.RootSpan.TransactionState.TransactionId
                );

            // If we couldnt build a payload just return
            if (payload == null)
            {
                return;
            }

            if (format.Equals(BuiltinFormats.TextMap))
            {
                // "text" version of payload
                ((ITextMap)carrier).Set(NEWRELIC_TRACE_HEADER, payload.ToJson());
            }
            else if (format.Equals(BuiltinFormats.HttpHeaders))
            {
                // "httpSafe" version of payload
                ((ITextMap)carrier).Set(NEWRELIC_TRACE_HEADER, payload.SerializeAndEncodeDistributedTracePayload());
            }
            //else if (format.Equals(BuiltinFormats.Binary))
            //{
            //	var payloadBytes = Encoding.UTF8.GetBytes(payload.ToJson());
            //	((MemoryStream)carrier).Write(payloadBytes, 0, payloadBytes.Length);
            //}
        }
示例#17
0
        public ISpanContext Extract <TCarrier>(IFormat <TCarrier> format, TCarrier carrier)
        {
            var payload = GetPayloadString(format, carrier);

            if (string.IsNullOrEmpty(payload))
            {
                return(null);
            }

            var distributedTracePayload = DistributedTracePayload.TryDecodeAndDeserializeDistributedTracePayload(payload);

            if (distributedTracePayload == null)
            {
                var message = $"{NEWRELIC_TRACE_HEADER} header value was not accepted.";
                _logger.Log(message, false, "ERROR");
                throw new ArgumentNullException(message);
            }

            var transportDurationInMillis = (DateTimeOffset.UtcNow - distributedTracePayload.Timestamp).TotalMilliseconds;

            return(new LambdaPayloadContext(distributedTracePayload, transportDurationInMillis));
        }
示例#18
0
        public DistributedTracePayload TryDecodeInboundSerializedDistributedTracePayload(string serializedPayload)
        {
            DistributedTracePayload payload = null;

            try
            {
                payload = DistributedTracePayload.TryDecodeAndDeserializeDistributedTracePayload(serializedPayload);
            }
            catch (DistributedTraceAcceptPayloadVersionException)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadIgnoredMajorVersion();
            }
            catch (DistributedTraceAcceptPayloadNullException)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadIgnoredNull();
            }
            catch (DistributedTraceAcceptPayloadParseException)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadParseException();
            }
            catch (Exception)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadException();
            }

            if (!IsValidPayload(payload))
            {
                return(null);
            }

            if (_configurationService.Configuration.PayloadSuccessMetricsEnabled)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceAcceptPayloadSuccess();
            }

            return(payload);
        }
示例#19
0
        private static void TestPayloadInfoMatchesSpanInfo(DistributedTracePayload payload, ISpanEventWireModel rootSpan, ISpanEventWireModel actualSpan)
        {
            Assert.NotNull(rootSpan);

            var rootSpanIntrinsicAttributes = rootSpan.IntrinsicAttributes();

            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.TraceId, rootSpanIntrinsicAttributes["traceId"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.Priority, rootSpanIntrinsicAttributes["priority"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.Sampled, rootSpanIntrinsicAttributes["sampled"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.Guid, rootSpanIntrinsicAttributes["parentId"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo("generic", rootSpanIntrinsicAttributes["category"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(true, rootSpanIntrinsicAttributes["nr.entryPoint"]));

            Assert.NotNull(actualSpan);

            var actualSpanIntrinsicAttributes = actualSpan.IntrinsicAttributes();

            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.TraceId, actualSpanIntrinsicAttributes["traceId"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.Priority, actualSpanIntrinsicAttributes["priority"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(payload.Sampled, actualSpanIntrinsicAttributes["sampled"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(rootSpanIntrinsicAttributes["guid"], actualSpanIntrinsicAttributes["parentId"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo(rootSpanIntrinsicAttributes["transactionId"], actualSpanIntrinsicAttributes["transactionId"]));
            Assert.IsTrue(AttributeComparer.IsEqualTo("datastore", actualSpanIntrinsicAttributes["category"]));
        }
 public void SetInboundDistributedTracePayload(DistributedTracePayload payload)
 {
     InboundPayload = payload;
 }
 public void DistributedTracePayload_OptionalAndRequired(string json, IConstraint constraint)
 {
     Assert.That(() => DistributedTracePayload.TryBuildIncomingPayloadFromJson(json), constraint);
 }
示例#22
0
        public void BuildOutgoingPayload_ReturnsNull_WhenRequiredFieldsNotPresent(string type, string accountId, string appId, string traceId)
        {
            var payload = DistributedTracePayload.TryBuildOutgoingPayload(type, accountId, appId, Guid, traceId, TrustKey, Priority, Sampled, Timestamp, TransactionId);

            Assert.Null(payload);
        }
 public LambdaPayloadContext(DistributedTracePayload payload, double transportDurationInMillis)
 {
     _payload = payload;
     _transportDurationInMillis = transportDurationInMillis;
 }
示例#24
0
        private IDistributedTracePayload TryGetOutboundDistributedTraceApiModelInternal(IInternalTransaction transaction, ISegment segment, DateTime timestamp)
        {
            var accountId = _configurationService.Configuration.AccountId;
            var appId     = _configurationService.Configuration.PrimaryApplicationId;

            if (!_configurationService.Configuration.SpanEventsEnabled && !_configurationService.Configuration.TransactionEventsEnabled)
            {
                Log.Finest("Did not generate payload because Span Events and Transaction Events were both disabled, preventing a traceable payload.");
                return(DistributedTraceApiModel.EmptyModel);
            }

            transaction.SetSampled(_adaptiveSampler);
            var transactionIsSampled = transaction.Sampled;

            if (transactionIsSampled.HasValue == false)
            {
                Log.Error("Did not generate payload because transaction sampled value was null.");
                return(DistributedTraceApiModel.EmptyModel);
            }

            var payloadGuid   = _configurationService.Configuration.SpanEventsEnabled ? segment?.SpanId : null;
            var trustKey      = _configurationService.Configuration.TrustedAccountKey;
            var transactionId = (_configurationService.Configuration.TransactionEventsEnabled) ? transaction.Guid : null;
            var traceId       = transaction.TraceId;

            var distributedTracePayload = DistributedTracePayload.TryBuildOutgoingPayload(
                DistributedTraceTypeDefault,
                accountId,
                appId,
                payloadGuid,
                traceId,
                trustKey,
                transaction.Priority,
                transactionIsSampled,
                timestamp,
                transactionId);

            if (distributedTracePayload == null)
            {
                return(DistributedTraceApiModel.EmptyModel);
            }

            string encodedPayload;

            try
            {
                encodedPayload = DistributedTracePayload.SerializeAndEncodeDistributedTracePayload(distributedTracePayload);
            }
            catch (Exception ex)
            {
                Log.Error($"Failed to get encoded distributed trace headers for outbound request: {ex}");
                _agentHealthReporter.ReportSupportabilityDistributedTraceCreatePayloadException();
                return(DistributedTraceApiModel.EmptyModel);
            }

            transaction.TransactionMetadata.HasOutgoingTraceHeaders = true;

            if (_configurationService.Configuration.PayloadSuccessMetricsEnabled)
            {
                _agentHealthReporter.ReportSupportabilityDistributedTraceCreatePayloadSuccess();
            }

            return(new DistributedTraceApiModel(encodedPayload));
        }