4

I send my Azure Functions TraceWriter output to Application Insights, via the App Insights integration. When I look for the traces, they don't appear in order. For example, I can run a query like

traces | where operation_Id == "<guid>" | order by timestamp asc

and get back 19 trace records from this invocation. But between them they only have 5 unique timestamps and so the records do not come back in perfect order.

Is there any other way to sort the traces?


This query confirms that the timing sent to App Insights is millisecond resolution - if that. (micros and nanos are always =0).

traces | project timestamp, datetime_part('microsecond', timestamp)
Janusz Nowak
  • 2,595
  • 1
  • 17
  • 36
Iain
  • 1,797
  • 1
  • 20
  • 38
  • Background: I'm trying Reactive .NET and don't fully understand it, so I need clarity on the order things are happening in. Because the 'Function Completed' trace comes ~13th out of the 19 traces, I conclude that the timestamp sorting is not doing the job. – Iain Mar 05 '18 at 05:12
  • 2
    I'm glad you asked this because the Durable Functions extension has the same problem: https://github.com/Azure/azure-functions-durable-extension/issues/71. I'm pinging the Functions team member who knows most about App Insights integration to get more clarity on what can be done here. – Chris Gillum Mar 05 '18 at 19:55

2 Answers2

3

I'm waiting for an official answer from the App Insights team to see if there's a way we can provide greater precision, but we may be at the mercy of DateTime.Now


[Update]: It looks like App Insights will be improving this. They filed two issues to track:

The workaround still applies until these are fixed.


However, you can add your own measurements using a Stopwatch and even have it be sortable in App Insights. You do this with the structured logging capabilities in ILogger.

A quick example:

using System.Net;
using System.Diagnostics;

public static HttpResponseMessage Run(HttpRequestMessage req, ILogger logger)
{
    // offset the Stopwatch with the current ticks so multiple runs don't overlap.
    var startTicks = DateTime.UtcNow.Ticks;
    Stopwatch sw = Stopwatch.StartNew();
    logger.LogInformation("[{PreciseTimeStamp}] Log 1", (startTicks + sw.ElapsedTicks).ToString());
    logger.LogInformation("[{PreciseTimeStamp}] Log 2", (startTicks + sw.ElapsedTicks).ToString());
    logger.LogInformation("[{PreciseTimeStamp}] Log 3", (startTicks + sw.ElapsedTicks).ToString());
    logger.LogInformation("[{PreciseTimeStamp}] Log 4", (startTicks + sw.ElapsedTicks).ToString()); 
    logger.LogInformation("[{PreciseTimeStamp}] Log 5", (startTicks + sw.ElapsedTicks).ToString());
    sw.Stop();

    return req.CreateResponse(HttpStatusCode.OK);
}

This will output something like:

2018-03-06T19:46:32.278 [Info] [636559623922781779] Log 1
2018-03-06T19:46:32.278 [Info] [636559623922783356] Log 2
2018-03-06T19:46:32.278 [Info] [636559623922784381] Log 3
2018-03-06T19:46:32.278 [Info] [636559623922785325] Log 4
2018-03-06T19:46:32.278 [Info] [636559623922786254] Log 5

And in App Insights, you can sort with order by tolong(customDimensions.prop__PreciseTimeStamp) asc. But since the timestamp is in the message, you could sort by that as well.

If you want to get fancier, you can add the new column to your trace without it showing up in your message with a logging helper like this:

public static void LogWithPrecision(ILogger logger, string message, long ticks)
{
    var state = new Dictionary<string, object>
    {
        ["PreciseTimeStamp"] = ticks.ToString()
    };

    logger.Log(LogLevel.Information, 0, state, null, (s, e) => message);
}

You can sort the same way as above but without the ticks showing up in the message.

brettsam
  • 2,702
  • 1
  • 15
  • 24
2

I'm looking for traces for a specific Azure Function invocation, and they don't appear in order

Actually, there are always three message status for the same operation. As you know, their timestamps are the same.You could filter operation_Id and message status to get specific Azure Function invocation.

enter image description here

Is there any other way to sort the traces?

As you mentioned that you don't believe timestamp field,so you could store the datetime to custom traces. Then you could know the order of records. Such as this article.

// Track a Metric
var metric = new MetricTelemetry("Test Metric", DateTime.Now.Millisecond);
UpdateTelemetryContext(metric.Context, context, name);
telemetryClient.TrackMetric(metric);
Janley Zhang
  • 1,567
  • 7
  • 11
  • Thanks for your answer. Edited my question to clarify, I am doing custom logging of traces. I think my use of Reactive .NET might be making things happen in weird orders, so I'm very interested to see traces in the order they were logged, and I think timestamp sorting is 'lying' to me. – Iain Mar 05 '18 at 05:08
  • @lain I have updated my answer. I hope my suggestion would be help. – Janley Zhang Mar 05 '18 at 07:00
  • Thanks, sure I can workaround this by using the App Insights API directly. I'll leave this S/O question for a bit in case Functions team respond. – Iain Mar 05 '18 at 07:08