Azure App Insights issue with end to end tracing - azure

I seem to be having some issues with tracing end to end using Azure functions and Service Bus Queue.
I have essentially a HTTP Trigger, that will then put the JSON message body onto the Service Bus Queue as a Message - with a generated Correlation Id (guid).
I have the Service Bus as a queue - this is fine.
I then have a Service Bus Queue Trigger function that pulls off the message from the queue. This is working fine.
However, the Service Map and the telematary and the request does not provide the end to end trace. It is split into two, my HTTP Trigger and Service Bus Trigger.
The operation-ids are different.
What am I doing wrong?
Here is the HTTP Trigger SEND function
[FunctionName("SendQueueMessage")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log,
[ServiceBus("busqueue", Connection = "xxxxx", EntityType = EntityType.Queue)] ICollector<Message> outputQueueItem)
{
log.LogInformation("Processing a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var correlationId = Guid.NewGuid().ToString();
outputQueueItem.Add(new Message(Encoding.UTF8.GetBytes(requestBody))
{
CorrelationId = correlationId
});
return new OkObjectResult($"Successful CorrelationId: {correlationId}");
}
Here is the Queue Trigger:
[FunctionName("RetrieveFromBusQueue")]
public static void Run([ServiceBusTrigger("busqueue",
Connection = "xxxxxxxx")]Message messageItem,
ILogger log)
{
log.LogInformation($"C# ServiceBus queue trigger function processed message {System.Text.Encoding.UTF8.GetString(messageItem.Body)}");
log.LogInformation($"Message ID: {messageItem?.CorrelationId}");
}
Is there some setting?
Both these functions are under the same FunctionApp.
It strangely never factors into the MAP the queue either.. I'm so confused here.
I am invoking the HTTP Trigger through the CODE and TEST page in Azure against the trigger function. Is it something to do with HTTP headers?
Can someone point me in the correct direction to go with this please?
UPDATE:
So... turns out, if I use a much older version of Microsoft.ApplicationInsights nuget package... 2.10.0 instead of 2.16.0 it actually traces my call to the Service bus and off the queue - with the correct display in the MAP.
This is absolutely bizarre to say the least - pulling my hair out for hours trying to figure out what I had done wrong. I still am unsure of why the latest version is causing this issue.

It seems a bug in the new version 2.16.0.
As per the comment, you'd better raise an issue about this in it's github here.

I had this issue recently with 3.1.6
Upgrading to 3.1.13 (latest) didn't help.
There is a compatibility problem in version >= 3.1.4, downgrading to 3.1.3 fixed the problem for me.

Related

Http Trigger Azure function returns 404 randomly

We have a .net core azure function on function runtime 3. This works perfectly fine ran locally and most of the time on our deployed app service. However we've experienced intermittent 404 responses for requests that go through perfectly fine at other times.
There's no entries appearing in our logs or application insights telemetry for the failing requests.
It feels a lot like this issue on the azure-function-host github project:
https://github.com/Azure/azure-functions-host/issues/5247
though that's targeting functions runtime 1 or 2.
Has anyone had similar issues or know of any way to get additional log info that might highlight what problem we're running into.
That might happen during scaling out or your function app about to change the server from one to another (for some reason). That's the actually cons of serverless applications.
But what I can suggest to you is:
Create HeartBeat Function similar to this:
private readonly IAsyncRepository<Business> _businessAsyncRepository;
public HeartBeat(IAsyncRepository<Business> businessAsyncRepository)
{
// Your all DI injections are here
_businessAsyncRepository = businessAsyncRepository;
}
[FunctionName(nameof(HeartBeat))]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
return new OkObjectResult("OK");
}
And then create availability test on Application Insights and call the HeartBeat.
This will also give you a warm instance of Azure Functions at all time. But obviously you spend your 1m free call on consumption plan every time you call the heartbeat depending on how frequently you call the AF.

Sequence processing with Azure Function & Service Bus

I have an issue with Azure Function Service Bus trigger.
The issue is Azure function cannot wait a message done before process a new message. It process Parallel, it not wait 5s before get next message. But i need it process sequencecy (as image bellow).
How can i do that?
[FunctionName("HttpStartSingle")]
public static void Run(
[ServiceBusTrigger("MyServiceBusQueue", Connection = "Connection")]string myQueueItem,
[OrchestrationClient] DurableOrchestrationClient starter,
ILogger log)
{
Console.WriteLine($"MessageId={myQueueItem}");
Thread.Sleep(5000);
}
I resolved my problem by using this config in my host.json
{
"version": "2.0",
"extensions": {
"serviceBus": {
"messageHandlerOptions": {
"maxConcurrentCalls": 1
}
}
}}
There are two approaches you can accomplish this,
(1) You are looking for Durable Function with function chaining
For background jobs you often need to ensure that only one instance of
a particular orchestrator runs at a time. This can be done in Durable
Functions by assigning a specific instance ID to an orchestrator when
creating it.
(2) Based on the messages that you are writing to Queue, you need to partition the data, that will automatically handle the order of messages which you do not need to handle manually by azure function
In general, ordered messaging is not something I'd be striving to implement since the order can and at some point will be distorted. Saying that, in some scenarios, it's required. For that, you should either use Durable Function to orchestrate your messages or use Service Bus message Sessions.
Azure Functions has recently added support for ordered message delivery (accent on the delivery part as processing can still fail). It's almost the same as the normal Function, with a slight change that you need to instruct the SDK to utilize sessions.
public async Task Run(
[ServiceBusTrigger("queue",
Connection = "ServiceBusConnectionString",
IsSessionsEnabled = true)] Message message, // Enable Sessions
ILogger log)
{
log.LogInformation($"C# ServiceBus queue trigger function processed message: {Encoding.UTF8.GetString(message.MessageId)}");
await _cosmosDbClient.Save(...);
}
Here's a post for more detials.
Warning: using sessions will require messages to be sent with a session ID, potentially requiring a change on the sending side.

Automatic retry to CosmosDb output binding

I'm using an Azure function that sends an array of around 200 documents to a CosmosDB via the Output Binding. That function gets triggered about 1000 at the same time by queue messages.
In some cases I get the "Request rate is large" error and the function execution fails. The documentation says when this error occurs, I can retry the execution in some milliseconds, but I suspect the azure function runtime is doing that for me. I couldn't find any documentation explicitly saying that when the output binding throws that exception it will retry automatically (like with the .NET Linq library).
Can someone point me out to see if this is the case?
The Output binding uses SDK 1.13.2 which already has the retry mechanism in place.
Assuming you are using Azure Functions v1, if you are using the IAsyncCollection the Function will do an UpsertDocumentAsync for each AddAsync, if you are using a single document output, then the UpsertDocumentAsync should be happening once.
In any case, the SDK retries by default 9 times on a throttled result, after that, the exception is bubbled and you Function will error; the document should go back to the queue for retrying as per the QueueTrigger design and after a couple of iterations, it goes to the deadletter queue..
If you want more granular control of the flow, you could obtain the DocumentClient and do the UpsertDocumentAsync yourself with a try/catch, if it fails more than 9 times, you can opt to send to another Queue or retry another set of times. Something like:
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
[FunctionName("CosmosDBSample")]
public static async Task<HttpResponseMessage> Run(
[QueueTrigger("my-queue")] MyPOCOClass myMessage,
[DocumentDB("test", "test", ConnectionStringSetting = "CosmosDB"] DocumentClient client,
TraceWriter log)
{
try
{
await client.UpsertDocumentAsync(myMessage);
}
catch(DocumentClientException ex)
{
// retry / queue somewhere else?
log.Warning($"DocumentClientException {ex.Message} in document {myMessage.Id}.");
}
}

Azure Functions SendGrid out binding does not show in SendGrid as a message

I am trying to use Azure Functions to send an email message through SendGrid. I have a function that has a storage queue trigger and an SendGrid output parameter. After adding a message in the queue the function runs but nothing else happens. When I login to Sendgrid it shows I have zero requests and delivered messages. Also I am not receiving any emails.
What could possibly be causing this? Is there any way to debug this further?
Here is my function code in C#:
public static class SendChatEmail {
[FunctionName ("SendChatEmail")]
public static void Run ([QueueTrigger ("decision-tree-emails", Connection = "AzureWebJobsStorage")] ChatData myQueueItem, [SendGrid (ApiKey = "SendGridApiKey")] out SendGridMessage message,
TraceWriter log) {
log.Info ($"C# Queue trigger function processed: {myQueueItem}");
message = new SendGridMessage ();
message.AddTo ("matti.petrelius#gmail.com");
message.AddContent ("text/html", "Hello there!");
message.SetFrom (new EmailAddress ("matti.petrelius#gmail.com"));
message.SetSubject ("Chat conversation");
}
}
I'm using:
Azure Functions Core Tools (220.0.0-beta.0)
Function Runtime Version: 2.0.11651.0
Microsoft Visual Studio Enterprise 2017 Version 15.7.1
Azure Functions and Web Jobs Tools - 15.0.40502.0
I've also tried to make a similar Function in Node.js without getting it to work any better. Maybe I'm using SendGrid somehow wrong?
Ok, nevermind this! Turns out the dashboard in SendGrid was just reaaaaally slow to update and did not show the requests before many hours later. So the requests were sent and delivered, the dashboard just didn't show it. Also I didn't notice receiving emails because they were directed straight to junk email! So this was a false alarm. The SendGrid binding works fine the way I did it.

How to abandon or deadletter messages on ServiceBus BrokeredMessage level on AzureFunction V2?

I am encountering one major road block issue when trying to use ServiceBusTrigger in azureFunction. I am trying to abandon, or deadletter, a service bus message in V2 ServiceBusTrigger, How can I do so? I've tried the following solution, but I didn't get anywhere.
Here is the codeSample I used:
public async static Task Run(Message myQueueItem, TraceWriter log, ExecutionContext context)
{
log.Info($"C# ServiceBus queue trigger function processed message delivery count: {myQueueItem.SystemProperties.DeliveryCount}");
QueueClient queueClient = new QueueClient("[connectionstring]","[queueName]");
////await queueClient.DeadLetterAsync(myQueueItem.SystemProperties.LockToken);
await queueClient.AbandonAsync(myQueueItem.SystemProperties.LockToken);
}
Solution 1: I tried to substitute Message myQueueItem for BrokeredMessage like in V1, I then can call myQueueItem.Abandon, or deadletter, on the message lever. However It came back with exception:
Microsoft.Azure.WebJobs.Host: Exception binding parameter 'myQueueItem'. System.Private.DataContractSerialization: There was an error deserializing the object of type Microsoft.ServiceBus.Messaging.BrokeredMessage. The input source is not correctly formatted. System.Private.DataContractSerialization: The input source is not correctly formatted."
At least I can go one step further. to
solution 2. Solution 2: is to use:
QueueClient queueClient = new QueueClient("[connectionstring]","[queueName]");
////await queueClient.DeadLetterAsync(myQueueItem.SystemProperties.LockToken);
await queueClient.AbandonAsync(myQueueItem.SystemProperties.LockToken);
I can use the lock provided in the Message Object, however, when I try to send it with queueClient, It said the message gone from the queue. or no longer available.
Can anybody let me know if i am on the right track? If I am not, please kindly guide me in the right track.
Service Bus messages are automatically completed or abandoned by Azure Functions runtime based on the success/failure of the function call, docs:
The Functions runtime receives a message in PeekLock mode. It calls Complete on the message if the function finishes successfully, or calls Abandon if the function fails.
So, the suggested way to Abandon your message is to throw an exception from function invocation.

Resources