Unhandled Exception with Azure serviceBusService - azure

I'm trying to send a serviceBusQueue message from an API function in my Azure mobile-service and even though it successfully creates the queueService and the queue exists I get a nasty exception. Any clue how I fix this?
I've attached the send code and stack trace.
function sendBusMessage(request, params, message, success)
{
console.log(params);
var queueService = azure.createServiceBusService(params.namespace,params.key);
console.log(queueService);
if (queueService)
{
queueService.sendQueueMessage('worker', message, function (error)
{
if (!error)
{
success();
}
else
{
request.respond(statusCodes.INTERNAL_SERVER_ERROR,error);
}
});
}
}
Exception stack:
An unhandled exception occurred. TypeError: Cannot set property 'body' of null
at ServiceClient._performRequest.self._buildRequestOptions.operation (D:\home\site\wwwroot\node_modules\azure\lib\services\core\serviceclient.js:210:34)
at ServiceClient._performRequest (D:\home\site\wwwroot\node_modules\azure\lib\services\core\serviceclient.js:264:7)
at ServiceBusService.ServiceClient._initDefaultFilter.filter (D:\home\site\wwwroot\node_modules\azure\lib\services\core\serviceclient.js:534:7)
at ServiceClient._performRequest (D:\home\site\wwwroot\node_modules\azure\lib\services\core\serviceclient.js:261:10)
at ServiceBusServiceClient._buildRequestOptions (D:\home\site\wwwroot\node_modules\azure\lib\services\core\servicebusserviceclient.js:107:5)
at Wrap.signRequest (D:\home\site\wwwroot\node_modules\azure\lib\services\serviceBus\wrap.js:69:5)
at WrapTokenManager.getAccessToken (D:\home\site\wwwroot\node_modules\azure\lib\services\serviceBus\wraptokenmanager.js:76:5)
at WrapService.wrapAccessToken.finalCallback (D:\home\site\wwwroot\node_modules\azure\lib\services\serviceBus\wrapservice.js:98:7)
at ServiceClient._initDefaultFilter.filter (D:\home\site\wwwroot\node_modules\azure\lib\services\core\serviceclient.js:538:11)
at WrapService.wrapAccessToken.processResponseCallback (D:\home\site\wwwroot\node_modules\azure\lib\services\serviceBus\wrapservice.js:101:5)

Namespace
The namespace for configuring Node.js is the one visible under Service Bus tab (that is pretty straightforward).
Access Key
Unfortunately it can be easily confused with access keys defined for the specific messaging capability instances (such as queues). Providing an invalid access key may result in a stacktrace like the one in question.
The access key which should be used for configuring Node.js is the one accessible from the Connection Information window. To get there, you need to navigate to the Service Bus main tab (one with the cloud icon), then click Connection Information button available from the bar at the bottom. It is the Default Key right beneath the DEFAULT ISSUER section.
Configuring Namespace and Access Key
Both namespace and access key can either be passed to azure.createServiceBusService() function directly, or (when configuring a Mobile Service) set via AZURE_SERVICEBUS_NAMESPACE and AZURE_SERVICEBUS_ACCESS_KEY keys in the app settings configuration section.

Make sure you are using the top level configuration from the Service Bus->Namespace not anything deeper in the tree. An incorrect access key will not throw a useful exception (like "Can't use a queue key to access a namespace") but instead produces the problem above.

Related

Set message custom properties when rejecting message

I have this simple application that uses node-amqp10 to read messages from some subscriptions and process/accepts or rejects messages due to some error that might happen.
My question is, is it possible for the consumer to set any additional property into the message when rejecting? (like DeadLetterError)
I've thought the receiverLink.reject would get the error parameter and set into the message automatically, but maybe this is not even possible (consumer setting properties into the message)
I am assuming you are using Azure Service Bus based on the tag in your question. If you use #azure/service-bus package instead, you have the option of updating properties of the message. Also while dead lettering you can provide deadLetterReason and deadLetterErrorDescription like below:
async function receiveMessage() {
// If receiving from a subscription you can use the createReceiver(topicName, subscriptionName) overload
const receiver = sbClient.createReceiver(queueName);
const messages = await receiver.receiveMessages(1);
if (messages.length) {
console.log(
">>>>> Deadletter the one message received from the main queue - ",
messages[0].body
);
// Deadletter the message received
await receiver.deadLetterMessage(messages[0], {
deadLetterReason: "Incorrect Recipe type",
deadLetterErrorDescription: "Recipe type does not match preferences."
});
} else {
console.log(">>>> Error: No messages were received from the main queue.");
}
await receiver.close();
}
For more details, refer Azure Service Bus client library for Javascript.
My question is, is it possible for the consumer to set any additional
property into the message when rejecting? (like DeadLetterError)
No, you can't. I know what you want to do, But the method of the basic module '#azure/service-bus' is not designed as you think.
For NODE.JS, it is deadLetterMessage(ServiceBusReceivedMessage, DeadLetterOptions & [key: string]: any).
JavaScript reference API:
https://learn.microsoft.com/en-us/javascript/api/#azure/service-bus/servicebusreceiver?view=azure-node-latest#deadLetterMessage_ServiceBusReceivedMessage__DeadLetterOptions____key__string___any_
It don't allow you to add custom properties.
But if you using C#, then it is possible:
DeadLetterAsync(String, IDictionary<String,Object>)
C# API reference:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.servicebus.queueclient.deadletterasync?view=azure-dotnet
In short, for NODE.JS you can only change the description of the dead-letter message, but can't add custom properties.

How to catch errors raised in Azure Device SDK?

I am using the Azure Device SDK for .NET Core in order to connect my devices to Azure IoT Hub. From time to time the server rejects some messages (like twin updates or telemetry messages) from the devices and responds with status code 400. As a result there are exceptions thrown on client side but due to its asynchronous nature they are swallowed somewhere inside the Azure SDK and never thrown at my code.
How can I actually be notified about these errors so I can handle and display them?
I can also see from the Azure Device SDK code that it uses some kind of logging (EventSource) but this is never enabled in the code:
From Logging.Common.cs:
Log.IsEnabled() // always returns false
Can you point me to some way where I can 1) actually enable logging in the Azure Device SDK and 2) find the content that was actually logged?
Update: Details regarding exception that is swallowed somewhere
// Fired here after I send twin reported properties to server:
AmqpTransportHandler.VerifyResponseMessage:
if (status >= 400)
{
throw new InvalidOperationException("Service rejected the message with status: " + status);
}
// Then becomes caught and re-fired here:
AmqpTransportHandler.SendTwinPatchAsync:
throw AmqpClientHelper.ToIotHubClientContract(exception);
// Then it disappears somewhere in the "dance" of the async tasks
You can capture traces: https://github.com/Azure/azure-iot-sdk-csharp/tree/master/tools/CaptureLogs
Our sample demonstrates best practice regarding exception catching, for example: https://github.com/Azure/azure-iot-sdk-csharp/blob/master/iothub/device/samples/DeviceClientMqttSample/Program.cs

BadRequestObjectResult does not return detailed error message to the client

I have a Azure function with an HTTP trigger. It produces a 400 response when an input value is not specified:
if (string.IsNullOrEmpty(artistName))
{
return new BadRequestObjectResult("Artist name not specified.");
}
When the function is running locally (func host start) and the API is called incorrectly (I am using curl -X POST ...), the above error message is shown.
When deployed to Azure and called in a similar way - instead of the detailed error message - only Bad Request is returned.
Why?
How can I change this behaviour?
It's a known issue for function runtime 2.0.11888 that HttpTrigger does not return response content properly.
If you want to solve this, go to Application settings, pin your FUNCTIONS_EXTENSION_VERSION to previous runtime 2.0.11857-alpha until new version is released.
See Azure Functions Runtime 2.0.11888 Preview.
Update
This issue has already been fixed from 2.0.11933.

Why does application insight log 400 bad request as successful request and not log exception

i am encountering a problem i'm not familiar with.
So i'm trying to log exceptions from a test Azure Function but when i throw an exception and return a 400 bad request, application insight registers the log as a successful request.
As i understand it it is probably register the function's successful run but what i don't understand is how i then should log the exception.
So what i have done so far is this.
(I Will be referring to Application Insights as AI from here on out)
I started by created an AI-Resource.
Then i took the instrument key and applied it to the app settings of my function.
After that i installed the AI NUGET to my function bu creating a Projet.json file and then pasting something like this which installed the necessary assemblies and such.
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ApplicationInsights": "2.4.0"
}
}
}
}
after this i initialize the TelemetryClient in the function and try to log and exception in a catch:
Initiation:
string key = TelemetryConfiguration.Active.InstrumentationKey = System.Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY", EnvironmentVariableTarget.Process);
TelemetryClient telemetry = new TelemetryClient() {
InstrumentationKey = key
};
Catch:
catch (Exception e)
{
Dictionary<string,string> properties = new Dictionary<string,string>();
properties.Add("Function Payload", data.ToString());
properties.Add("Function Exception", e.ToString());
telemetry.TrackException(e, properties);
return req.CreateResponse(HttpStatusCode.BadRequest, e);
}
Test running the function i get:
2018-03-07T14:24:36.171 [Info] Function started (Id=0292b455-314d-4c4c-872a-2b8137a72305)
2018-03-07T14:24:37.092 [Info] Function completed (Success, Id=0292b455-314d-4c4c-872a-2b8137a72305, Duration=931ms)
In Application insights i can can only see bad requests for StatusCode: 500
but 400 Bad requests gets logged as Successful requests.
And also the TrackException functionality doesn't log any of the custom properties...
So what am i missing?
MORE DETAILS ABOUT EXCEPTION LOGGING:
#Mikhail is right that we treat this as a success because the function is a success. We didn't want to use status codes to guess whether there was a successful operation or not, so we look for whether the function threw an exception.
Your exception isn't appearing in that screen because it hasn't been property correlated with this function execution. If you go to App Insights Analytics and query for that ExceptionTelemetry, you should see it.
In order to correlate it with a specific function, you'd need to set the OperationId, which is the same as the function's InvocationId. There is a sample that shows how to do this with Events, Metrics, and Dependencies, but doing it for Exceptions is the same (you can ignore the User.Id assignment): https://learn.microsoft.com/en-us/azure/azure-functions/functions-monitoring#custom-telemetry-in-c-functions
Update: From what you've shown of your function above, you may be able to get away with doing something like:
catch (Exception e)
{
log.Error("Function Payload " + data.ToString());
throw;
}
That would return a 500 (rather than a 400), and Functions would log the trace to Application Insights, and then log the exception as well as the Request failure. If you're not using your TelemetryClient anywhere else, you could remove that from your code.
The server (Azure Function) processed the request without errors, you returned a result from it, so from the point of view of Function App runtime the request was processed successfully. You can see that from the log too:
... Function completed (Success, ...
So, it makes sense that the Function App registers the call as success in Application Insights too. At least, that's how they chose to implement it.
the "for this operation" not showing exceptions implies that the exception that you sent does not have the same operationId as the azure function. operation
id is how application insights "links" related telemetry together.
your "exeption logging" screenshot is not an exception, but a request, so the custom properties logged on your exception won't be there.
if you want your azure function to fail, and show as a failed request, and log an exception, why are you catching the exception and logging it yourself? doesn't catching the exception then cause the azure function to succeed? why not just let the exception trickle out and let the function runtime do that part for you? (doesn't it?)

Azure Redis Cache: "role discovery data is unavailable"

I'm trying to connect to an instance of Azure Redis Cache from my local dev machine. I'm using StackExchange.Redis like so:
var lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(
$"{redisServerUrl},abortConnect=false,ssl=true,password={redisServerKey},connectTimeout=10000,syncTimeout=10000");
});
When lazyConnection is called I get an InvalidOperationException with the message:
"role discovery data is unavailable"
and this one-liner stack trace:
Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.get_CurrentRoleInstance()
Why is the exception thrown and how can I avoid it?
StackExchange.Redis tries to discover the RoleInstance name under the covers if you don't specify a ConfigurationOptions.ClientName value. It is odd that you are getting this error bubbled out to your code because the code in question handles all exceptions and defaults back to returning the Computer name.
I suspect that if you add ",name=XXX" to your connection string, the error will go away because you will avoid that code path.

Resources