How can I add custom operation to Azure Application Insights's Performance tab? - azure

We have a GraphQL api that runs on .Net Core. Since all queries are made to the /graphql endpoint we only get one operation "POST /graphql" on the performance page of Azure Application Insights while a REST API would have allowed Aplication Insights to automatically give us the performance per endpoint (ex. GET /users, POST /events, etc...).
To still get performance indicators I added custom Telemetry to our code. When the code to retrieve the users is called I do this:
RequestTelemetry requestTelemetry = new RequestTelemetry
{
Name = "UsersRequest"
};
var operation = _telemetryClient.StartOperation(requestTelemetry);
And when it is all done I do this:
operation.Telemetry.Success = true;
_telemetryClient.StopOperation(operation);
return result;
Then I can see the dependency calls wrapped up inside a "UsersRequest" when I open a "POST /graphql" operation like the screenshot below (imagine that "CustomMiddleware" says "UsersRequest"):
That's already a great help, it's much more clear than having all DB requests under each other without structure.
The only thing missing it's that I can't see the "UsersRequest" or "CustomMiddleware" on the performance page as an operation itself. That would be a massive help, the performance page gives amazing insights. It would be super helpful to be able to see that "UsersRequest" has been called 500 times in the last 24h, that the performance has been degrading in the last 7 days or that the average duration is 50ms.
Thank you!

Related

Need help and guidance for accessing operationId in nodejs application

We are using nodejs as my backend application and react native in front end. And azure application insights for logging. In UI side, we are redirecting to Stripe checkout page(external page) for payment and then coming back to our application's confirmation page. Here we are loosing the flow on end-to-end transaction. My requirement is to link pre-stripe and post-stripe operation into one single flow. For this my approach of solving this problem is accessing OPERATIONID and pass it to stripe and receive it back from Stripe and use it in confirmation page so that we will one single flow. I Need help in guiding me to the right documentation/ solution proposals.
I read some articles(eg: How to get Application Insights operation id in javascript?) and figured out that operationId is a uniqueID which gets created out of my application and cant access it in the application. I tried to use below code and got response of that operationID as "ai.operation.id" but seems like this is not the right pattern(value) of operationId.
import { defaultClient } from 'applicationinsights';
const telemetryClient = defaultClient;
// tslint:disable-next-line:no-console
console.log(telemetryClient.context.keys[`operationId`]);
The main function of operationId is to help tracking distributed systems so you can correlate requests. So as given in this documentation in nodejs client, you should set the setDistributedTracingMode to appInsights.DistributedTracingModes.AI_AND_W3C as shown below.
const appInsights = require("applicationinsights");
appInsights
.setup("<your ikey>")
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)
.start()
You should be able to get the operation id using the following code snippet.
const AppInsights = require("applicationinsights");
var context = AppInsights.getCorrelationContext();
var oid = context.operation.id;
If it does not solve your problem then, I would suggest you to set telemetry.context.operation.id to be a unique id by yourself and confirm if this is tracked by the Application Insights properly.
Also note that the latest version of the JavaScript SDK (SDK v2) for Application Insights have some changes as given in this document.
Moved context.operation to context.telemetryTrace. Some fields were also changed (operation.id --> telemetryTrace.traceID).
To keep the trace ID unique, where you previously used Util.newId(), now use Util.generateW3CId(). Both ultimately end up being the operation ID.
For more information read this log custom telemetry document.

500 error when using the shopping.flightDates.get endpoint

Using your API for an fun app I am developing and I just started using your eendpoints, This particular endpoint gives me this responseError:
body: '{"errors":[{"status":500,"code":141,"title":"SYSTEM ERROR HAS OCCURRED","detail":"ORIGIN AND DESTINATION NOT ALLOWED FOR AMA4DEV EXTREME SEARCH REQUESTS ON ENVIRONMENT"}]}',
The endpoint I am hitting is:
amadeus.shopping.flightDates.get({
origin : 'PHX',
destination : 'MEX'
}).then(function(response){
console.log(response.data);
}).catch(function(responseError){
console.log(responseError.response);
});
To make sure it was not something with the auth token/secret I made sure to make a test call using your example on github that works which was:
amadeus.shopping.flightDates.get({
origin : 'MUC',
destination : 'MAD'
}).then(function(response){
console.log(response.data);
}).catch(function(responseError){
console.log(responseError.response);
});
No problem in hitting that endpoint. Thank you again for looking into this
If you use the test environment: it is free of charge but limited (limited number of API calls you can do per month and limited set of data (a subset of production data)). For each API you can find the data collection available here.
For Flight Cheapest Date Search API, the test environment doesn't have data for PHX as origin.
I tried in production and it does return data. Please note that Flight Inspiration Search and Flight Cheapest Date Search are built on top of a pre-computed cache (in production). As they are inspirational APIs we do not offer all pairs of origin-destination but only the most searched all over the world. If you want to get the full list of origin-destination pairs (even smaller cities), you need to use the Flight Offers Search API.

Google Analytics API service object - no management attribute

I am trying to set up an application that uses the Google Analytics API. I have all the authorization steps working correctly and can pull all the data as expected. However, at the moment, it is working because I have hardcoded my own view ID into the queries to the API. E.g:
response = analytics.reports().batchGet(
body={
"reportRequests":
[
{
"viewId": "ga:12345678",
...
From what I understand, what I need to do is before I start querying the data, is use the service object to first get a view Id (or list of View Ids), then use that in the data queries. I have been attempting to do just that and have been failing miserably. Basically, I have the following (just to get the first step of a list of accounts):
credentials = client.OAuth2Credentials.from_json(session['credentials'])
http = credentials.authorize(httplib2.Http())
analytics = build('analytics', 'v4', http=http) #create the service object
data = analytics.management().accounts().list().execute()
The error I am getting is 'Resource' object has no attribute 'management'. What am I missing here??
Ok, so for those who come across this question, the issue seemed to be that, as of the time of writing, version 4 of the API does not have the management features. What I/we did instead was build a second service to get the account details using version 3:
service = build('analytics', 'v3', http=http)
accounts = service.management().accounts().list().execute()
That seemed to do the trick, although there was some additional fiddling required in order to get the view ID(s). However, once you have the object, it is just a matter of manipulating the object as needed.

Azure Notification Hub Sending thousands of notifications and getting back results from each

We're setting up Push Notifications for our app. We are creating a console app now that will determine which users to send to, and then send them to said users. What's not obvious to us at this point is how do we know when each one of them completed? Or didn't complete? There's not a lot of documentation provided by Microsoft (big surprise there) and whatever documentation there is doesn't really explain how to read the responses.
For instance, here's an example snippet of what we think we need to implement, because we could have thousands of people receiving a notification at one time, we would want them to run parallel and not block UI.
public async Task GenerateNotifications()
{
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(AppHelper.AzureNotificationHubConnectionString, "myhub");
List<Task<NotificationOutcome>> notificaitonTasks = new List<Task<NotificationOutcome>>();
for (int i = 0; i < 10; i++)
{
var notification = new
{
aps = new
{
alert = string.Format("Awesome Notification {0}", i),
sound = "default"
}
};
string notificationJSON = JsonConvert.SerializeObject(notification);
notificaitonTasks.Add(hub.SendAppleNativeNotificationAsync(notificationJSON, "mytag"));
}
await Task.WhenAll(notificaitonTasks);
}
This makes sense to us, we use the WhenAll method to execute all the tasks on parralel threads. But then is there a way to know what happens with EACH task that gets run? For instance, the ContinueWith method seems to do what we want, except we think that this will only run after ALL the tasks are completed, and not after each one (please correct me if I'm wrong).
So, is there a way to read each response of a WhenAll call? If no, is there a better way to do what we are trying to do? I will supply any other information needed, please just ask.
You can use per message Telemetry feature to get the result of each notification sent. You will need to however upgrade to Standard Tier to do that. See link
Per Message Telemetry
Per Message Telemetry Blog
On a side note you can use NotificationOutcome.Result property by using the EnableTestSend property as shown in the link EnableTestSend property(Search for Debug Failed notifications). This will only send the notification to 10 devices that matches your condition. This is primarily used for debugging purpose

azure method blows up if the records does not exist

I am using this method from the azure mobile services tutorial:
await todoTable.LookupAsync(id). I have 2 rows in a table of id 1,2.
If i do await todoTable.LookupAsync(1), it works and return the record. If i do
await todoTable.LookupAsync(8) to see how it's going to handle null, it just blows up with Not Found exception.
Thanks for help on this.
NULL would mean there is a record for id = 8, but its value is `NULL'. But in your case you do not have a record. Which is different.
What you observe is what you should observe if you do not have a record.
And this is a standard for REST based HTTP services. If record is not there, you get an HTTP 404 from the service.
Azure mobile services is nothing more than a combination of Web API and a wrapping (plumbing) code for your application. And every Web API call to a non-existent record would result into an HTTP 404 error.
And as already said in the comments, you should wrap your code around try - catch blocks and inspect the exception.
In .NET 4.5/4.6 there is new HttpClient type along with HttpResponseMessage and HttpRequestMessatge. The former has EnsureSuccessStatusCode() method. Which, if called will trigger exception.
In the older versions of the Framework there WebClient class, which would throw an exception if the HTTP status code is not 200.
So, again, at the end - you observe absolutely normal behavoir. Just have to read a little more about HTTP REST services, HTTP VERBS and HTTP Status Codes. Then also understand how the particular framework you use (.NET) handles the HTTP Status Codes.

Resources