public void BuildSpan() { var span = new NewRelicSpan( traceId: "traceId", spanId: "spanId", timestamp: 1L, parentSpanId: "parentId", attributes: new Dictionary <string, object>() { { "attrKey", "attrValue" }, { "adsfasdf", 12 }, { NewRelicConsts.Tracing.AttribNameDurationMs, 67 }, { NewRelicConsts.Tracing.AttribNameServiceName, "serviceName" }, { NewRelicConsts.Tracing.AttribNameName, "name" }, }); Assert.Equal("spanId", span.Id); Assert.Equal("traceId", span.TraceId); Assert.Equal(1L, span.Timestamp); Assert.Equal("serviceName", span.Attributes?["service.name"]); Assert.Equal(67, span.Attributes?["duration.ms"]); Assert.Equal("name", span.Attributes?["name"]); Assert.Equal("parentId", span.Attributes?["parent.id"]); Assert.Equal("attrValue", span.Attributes?["attrKey"]); }
public void SendANonEmptySpanBatch() { var traceId = "123"; var span = new NewRelicSpan( traceId: null, spanId: "Span1", timestamp: DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), parentSpanId: null, attributes: new Dictionary <string, object>() { { NewRelicConsts.Tracing.AttribNameName, "TestSpan" }, }); var spanBatch = new NewRelicSpanBatch( spans: new[] { span }, commonProperties: new NewRelicSpanBatchCommonProperties(traceId)); var dataSender = new TraceDataSender(new TelemetryConfiguration() { ApiKey = "123456" }, null); dataSender.WithHttpHandlerImpl((serializedJson) => { var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); return(Task.FromResult(response)); }); var response = dataSender.SendDataAsync(spanBatch).Result; Assert.Equal(NewRelicResponseStatus.Success, response.ResponseStatus); }
public async Task <IEnumerable <WeatherForecast> > Get() { // Each span must have a unique identifier. In this example, we are using a Guid. var spanId = Guid.NewGuid().ToString(); var spanTimeStamp = DateTimeOffset.UtcNow; var spanAttribs = new Dictionary <string, object>(); // Wrapping the unit of work inside a try/catch is helpful to ensure that // spans are always reported to the endpoint, even if they have exceptions. try { // This is the unit of work being tracked by the span. var rng = new Random(); var result = Enumerable.Range(1, 5) .Select(index => new WeatherForecast() { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); return(result); } // If an unhandled exception occurs, it can be denoted on the span. catch (Exception ex) { spanAttribs[NewRelicConsts.Tracing.AttribNameErrorMsg] = ex; //This ensures that tracking of spans doesn't interfere with the normal execution flow throw; } // In all cases, the span is sent up to the New Relic endpoint. finally { spanAttribs[NewRelicConsts.Tracing.AttribNameName] = "WeatherForecast/Get"; spanAttribs[NewRelicConsts.Tracing.AttribNameDurationMs] = DateTimeOffset.UtcNow.Subtract(spanTimeStamp).TotalMilliseconds; var span = new NewRelicSpan( traceId: Guid.NewGuid().ToString(), spanId: spanId, timestamp: spanTimeStamp.ToUnixTimeMilliseconds(), parentSpanId: null, attributes: spanAttribs); // Send it to the New Relic endpoint. var newRelicResult = await _spanDataSender.SendDataAsync(new[] { span }); if (newRelicResult.ResponseStatus == NewRelicResponseStatus.Failure) { _logger.LogWarning("There was a problem sending the SpanBatch to New Relic endpoint"); } } }
/// <summary> /// In this example, multiple traces will be reported in the same batch. /// Accordingly, the TraceId is applied to the individual spans, and NOT on /// the SpanBatch. /// </summary> private static async Task Example_SpanBatchForMultipleTraces() { // The collection of Spans var spans = new List <NewRelicSpan>(); for (var traceIdx = 0; traceIdx < 3; traceIdx++) { var traceId = Guid.NewGuid().ToString(); // Perform 10 units of work as part of this trace/spanBatch for (var spanIdx = 0; spanIdx < 5; spanIdx++) { var spanStartTime = DateTime.UtcNow; var spanAttribs = new Dictionary <string, object>(); try { // Attempt to perform a unit of work DoWork($"Hello World #{spanIdx}"); } catch (Exception ex) { // In the event of an exception, mark the span // as having an error and record a custom attribute // with the details about the exception. spanAttribs[NewRelicConsts.Tracing.AttribNameErrorMsg] = ex.Message; } finally { spanAttribs[NewRelicConsts.Tracing.AttribNameName] = $"{traceId} - {spanIdx}"; spanAttribs[NewRelicConsts.Tracing.AttribNameDurationMs] = DateTime.UtcNow.Subtract(spanStartTime).TotalMilliseconds; // Create a new Span assigning it a random guid as the spanId var span = new NewRelicSpan( traceId: traceId, //Since we're mixing traces in the same batch, the trace id is supplied on each span spanId: Guid.NewGuid().ToString(), parentSpanId: null, timestamp: DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), attributes: spanAttribs); spans.Add(span); } } } var spanBatch = new NewRelicSpanBatch(spans); // Send the SpanBatch to the New Relic endpoint. await SendDataToNewRelic(spanBatch); }