We've a bunch of azure functions log metrics against the execution context... you don't seem to be able to do this using the OOTB TraceWriter
, or ILogger
(at least in what i have seen) as there isn't an equivalent to what i assume would be named log.LogEvent()
..
So.. this url (https://docs.microsoft.com/en-us/azure/azure-functions/functions-monitoring#custom-telemetry-in-c-functions) shows a pattern for leveraging a TelemetryClient()
inside of Azure Function to do the same, with examples for rolling your own for EventTelemetry()
etc, however to ensure the correlation works you have to set the context for each thing you log:
var evt = new EventTelemetry("Function called");
evt.Context.Operation.Id = executionContext.InvocationId.ToString();
telemetryClient.TrackEvent(evt);
This all seems fairly logical, except i have a shared class (TelemetryManager
) that helps creation of TelemetryClient()
- so we don't have to repeat code in every, single, function that just news up a client with a series of additional settings.. this also implements a logging interface ITelemetry
so that we have an interface later to unit test against, and lets you do.. (here using trace for simplicity):
static CustomTelemetryManager logger = new CustomTelemetryManager();
logger.Trace($"thing i want to trace: {x.value}");
logger.Trace()
method simply does is call the telemetryClient.TrackTrace()
method in the CustomTelemetryManager()
class - some other methods are more complex.
Anyway, the interface is there so that when unit testing we can just do:
// gets all the app insights key, and sets various other properties.
static DebugLogger logger = new DebugLogger();
logger.Trace($"thing i want to trace: {x.value}");
and it will just Debug.WriteLine()
instead of attempting to call out to AI
Question 1: Is there a "better" way to swap out Application Insights code for unit tests, as this is the only reason that we have this ITelemetry
interface at all... to facilitate a dummy logger for unit tests.
Ultimately though, what i need to do, is give the telemetryClient.TrackTrace()
the context of the invocation that is being executed, and the only way i have found to do that right now is, similar to the track event code above..
var trace = new TraceTelemetry($"i am a trace.");
trace.Context.Operation.Id = context.InvocationId.ToString();
logger.Trace(trace);
Because the TelemetryClient
is shared over all functions, i need to apply the context to the metric directly before sending it to log..
Question 2: Is the only way i can do this.. something like:
public void TrackTrace(string msg, ExecutionContext ctx)
{
var trace = new TraceTelemetry(msg);
trace.Context.Operation.Id = ctx.InvocationId.ToString();
client.TrackTrace(trace);
}
As this will mean modifying the interface, and then also mean for unit testing i shall also need to supply some sort of dummy context to the debug logger, which feels a bit clunky..
Somewhere in here, i think there is a simple tweak to simplify this needlessly confusing problem.. but i can't quite see the wood for the trees!
trace
prevents you from mockingTelemetryClient
. – Mikhail Shilkov