I want to join pageViews that are coming from the AppInsights browser SDK, to the request on the backend. I don't see a foreign key that makes sense, is there one OOTB? or do I need to code something to join them together?
To add context, I am interested in pageView duration by cloudRoleInstance (server), but cloudRoleInstance is only available on requests.
I tried the following, and did not work, I supose the operation IDs are not the same.
pageViews
| join (requests) on operation_Id
You can join by Operation ID (operation_Id).
Here is the query which returns all documents for a particular operation_Id:
union *
| where timestamp > ago(1d)
| where operation_Id == "<operation_id>"
I was interested in exactly the same thing and this is how I ended up solving it:
Set a "cloud_RoleInstance" cookie for each response from the server so that the client javascript would know which role instance sent the last response.
Add a TelemetryInitializer to the client-side Application Insights instance which pulls the RoleInstance cookie and adds it as data to the telemetry collected client-side.
*The reason I did it this way instead of joining on operationId as the other answer says is because operationId seemed to span many requests on the server, sometimes over the course of a half an hour. Maybe that has is because of the way our Single Page Application is set up, but operationId just wasn't working for me.
Code
BaseController.cs::BeginExecute (We have our own BaseController which all other controllers inherit from)
var roleInstanceCookie = requestContext.HttpContext.Response.Cookies.Get("cloud_RoleInstance");
roleInstanceCookie.Value = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CurrentRoleInstance.Id;
requestContext.HttpContext.Response.Cookies.Set(roleInstanceCookie);
ApplicationInsights.js (This contains our AI snippet that loads AI, currently using version 2.3.1 of the JS SDK)
// ... initialization snippet ...
appInsights.addTelemetryInitializer((envelope) => {
envelope.data.cloud_RoleInstance = getCookie("cloud_RoleInstance");
});
The cloud_RoleInstance will then end up in the customDimensions column of your PageViews in Application Insights
Related
Our exact same endpoint demo query request using Freemium plan is different than the HERE API demo api endpoint results. As you can see, we do not have Address or contacts. I'm not sure why the results vary on same exact query and endpoint. Any ideas?
We have expanded the initial search/explore response based for the Demo App ID in order to enable users do some testing, but it is not turned on for the Freemium App ID. If you need specific details (like address and contact) then you can use places/lookup api like shown below (you search with source: sharing, id: id for the place you can get this from your above query).
We do this because we expect the end-user to select an item to get additional information. When selected, we receive that request, and it is a signal to us that the result is relevant and important to the query.
https://places.demo.api.here.com/places/v1/places/124aabd1-0aef738f80350f8bebb5ed7539bd19a8;context=Zmxvdy1pZD1lNjIyNjczZS0xNDRmLTViMzctYjY3Mi1hNWQ5MmRkNWU4NzRfMTU0MTc4NDk3MzYzOV8wXzU1NDcmc2l6ZT01JlgtRldELUFQUC1JRD1LTnZIaDlhZ0E2WGxKbElDRWhOZiZYLU5MUC1UZXN0aW5nPTE?app_id=xxx&app_code=xxx
I have data which are stored in 3 different application insights resources, thanks to query across resource feature added last year (https://azure.microsoft.com/en-us/blog/query-across-resources/) was possible to query those 3 application insights at once with app identifier.
I'm trying to execute this query through app insights REST API : https://dev.applicationinsights.io (app insights REST API) for a very basic need from a static HTML page (no backend)
but without luck
I do suspect that app identifier isn't supported, it is actually the case ? any workaround for my use case (no backend).
Here is an example with the query in the body. My queries are quite complex and have a lot of let statements and therefore passing the query in the body is easier. There are some PowerShell quirks in the example below, but I'll update with a C# example tomorrow.
The let statement in the example below is pretty pointless, it's mostly there to show that you can do complex queries with let expressions etc.
AppId is the Application Insights resource ID - and NOT the instrumentation key. The API key is just a long string and you can create up to 10 of them AFAIK.
You will find both the id and keys under API Access (I've added a screenshot as it's easy to get them confused). When you use the app() function use the app id.
$app1Id = "GUID"
$app2Id = "GUID"
$app1Key = "string"
$app2Key = "string"
# EXAMPLE: "X-Api-Key" = "key1:GUID1,key2:GUID2"
$headers = #{ "X-Api-Key" = "${app1Key}:$app1Id,${app2Key}:$app2Id"; "Content-Type" = "application/json" }
# EXAMPLE: "query" = "union app('GUID1').something, app('GUID2').something | limit 5"
$query = #{"query" = "let days=1d;union app('$app1Id').exceptions,app('$app2Id').exceptions | where timestamp > ago(days)"}
$body = ConvertTo-Json $query | % { [regex]::Unescape($_) }
$result = Invoke-RestMethod "https://api.applicationinsights.io/v1/apps/$app1Id/query" -H $headers -Body $body -Method POST
The query above will return all the exceptions for the two Application insights resources for the last day. You can do a query across 10 resources at the time of writing, 200 requests per 30 seconds or a max of 86,400 requests per day (UTC). Other limits apply if you use ADD.
NOTE: the extra {} in the header is a PowerShell quirk in regards to variables and the use of the colon char, and as you can see in the example you should not bracket the keys in the header :)
Checked with the dev team that owns that service:
You should be able to put the api key in as apiKey1:appId1,apiKey2:appId2 in the api key box and this should work.
the [object ProgressEvent] response is a bug in the explorer that should have really showed you an error.
And as a workaround, you could always do the queries inside the azure portal itself in workbooks for any of the AI resources, or hypothetically also from the analytics portal for any of the AI resources, and those wouldn't require the API key at all, if all you needed was to see the data.
Current Project:
ASP.NET 4.5.2
MVC 5
PayPal API
I am using this example to build myself a PayPal transaction (and yes, my code is virtually identical), as I do not know of any other method that will return the three values in the title.
My main problem is that, the example I am utilizing is much more concise and compact than the one I used for a much older Web Forms application, and as such, I am unsure as to where or even how to grab the three values I need.
My initial thought was to do so right after the ACK, and indeed I was able to obtain the CorrelationId as well as the TimeStamp, but because this was prior to the user being carted off to PayPal’s site (sandbox in this case -- see the return new PayPalRedirect contained within the if), the TransactionId was blank. And in this example, PayPal explicitly redirects the user to a Success page without returning to the Action that sent the user to PayPal in the first place, and I am not seeing any GET values in the URL at all aside from the Token and the PayerId, much less ones that could provide me with the TransactionId.
Suggestions?
I have also looked at the following examples:
For ASP.NET Core, was unsure how to adapt to my current project particularly due to appsettings.json, but it looked quite well done. I really liked how the values were rolled up in lists.
For MVC 4, but I couldn’t find where ACK was being used to determine success or successwithwarning so I couldn’t hook into that.
I have also found the PayPal content to be like trying to drink from a fire hose at full blast -- not only was the content was hopelessly outdated (Web Forms code, FTW!) but there was also so many different examples it would have taken me days to determine which one was most appropriate to use.
Any assistance would be greatly appreciated.
Edit: my initial attempt at modifying the linked code has this portion:
values = Submit(values);
var ack = values["ACK"].ToLower();
if(ack == "success" || ack == "successwithwarning") {
using(_db = new ApplicationDbContext()) {
var updateOrder = await _db.Orders.FirstOrDefaultAsync(x => x.OrderId == order.OrderId);
if(updateOrder != null) {
updateOrder.OrderProcessed = false;
updateOrder.PayPalCorrelationId = values["CORRELATIONID"];
updateOrder.PayPalTransactionId = values["TRANSACTIONID"];
updateOrder.PayPalTimeStamp = values["TIMESTAMP"];
updateOrder.IPAddress = HttpContext.Current.Request.UserHostAddress;
_db.Entry(updateOrder).State = EntityState.Modified;
await _db.SaveChangesAsync();
}
}
return new PayPalRedirect {
Token = values["TOKEN"],
Url = $"https://{PayPalSettings.CgiDomain}/cgi-bin/webscr?cmd=_express-checkout&token={values["TOKEN"]}"
};
}
Everything within and including the using() is my added content. As I mentioned, the CorrelationId and the TimeStamp come through just fine, but I have yet to successfully obtain the TransactionId.
Edit 2:
More problems -- the transactions that are “successful” through the sandbox site (the ReturnUrl is getting called) aren’t reflecting properly on my Facilitator and Buyer accounts, even when I do payments straight from the buyer’s PayPal account (not using the Credit Card). I know I am supposed to see transactions in the Buyer’s account, either through the overall Dev account (Accounts -> Profile -> balance or Accounts -> Notifications) or through the Buyer’s account in the sandbox front end. And yet -- multiple transactions returning me to the ReturnUrl path, and yet no transactions in either.
Edit 3:
Okay, this is really, really weird. I have gone over all settings with a fine-toothed comb, and intentionally introduced errors to see where things should crap out. It turns out that the entire process goes swimmingly - except nothing shows up in my notifications and no amounts get moved between my different accounts (Facilitator and Buyer). It’s like all my transactions are going into /dev/null, yet the process is successful.
Edit 4: A hint!
In the sandbox, where Buyer accepts the transaction, there is a small note, “You will be able to review the transaction before completing it” or something like that -- suggesting that an additional page is not coming up and that the user is being uncerimoniously dumped back to the success page. Why the success page? No clue. But it’s happening.
It sounds like you are only doing the first part of the process.
Express Checkout consists of 3 API calls:
SetExpressCheckout
GetExpressCheckoutDetails
DoExpressCheckoutPayment
SEC generates a token, and then you redirect to PayPal where the user signs in and reviews the transactions before agreeing to pay.
They are then sent to the ReturnURL included in your SEC request, and this is where you'll call GECD in order to obtain all the buyer details that are now available since they signed in.
Using that data you can complete the final DECP request, which is what finalizes the procedure. No money is actually processed until this final call is completed successfully.
We need to track conversions that happen on a 3rd party site. The only thing we can place on that site is an image pixel and maybe some JS logic for when to fire it.
I know it is possible to fire a conversion using the Measurement Protocol: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#visitor
Ideally, I'd just give the 3rd party an IMG url and that would be it. The problem is the CID (unique client id).
I can try passing the CID from our site to the 3rd party via URL parameter. However, there are many cases where its not available (e.g., IMG pixcel will be in an email, the goal URL is on printed literature) or the 3rd party is not willing to go through the hassle. Is it best practice to pass this CID in this way?
I can try generating a CID, but I can't find a dead simple way of doing that e.g., var CID = generateCID(). The 3rd party site has its own GA on the page. Can I just take their Google Analytics CID and use it in the image pixel URL?
What the best way to do this? Thank you!
If the 3rd-party site has analytics.js already running then using that client ID is probably best. You can get it by doing the following:
var cid;
ga(function(tracker) {
cid = tracker.get('clientId'));
});
If analytics.js is not running, or if you can't access the ga variable for some reason, you can just generate the client ID randomly. This is approximately what Google does. It's a random 31-bit integer with the current date string appended:
var cid = Math.floor(Math.random() * 0x7FFFFFFF) + "." +
Math.floor(Date.now() / 1000);
Only to complement #Philip Walton excellent answer, Google Analytics expects a random UUID (version 4) as the Client ID, according to the official Documentation.
Client ID
Required for all hit types.
This anonymously identifies a particular user, device, or browser
instance. For the web, this is generally stored as a first-party
cookie with a two-year expiration. For mobile apps, this is randomly
generated for each particular instance of an application install. The
value of this field should be a random UUID (version 4) as described
in http://www.ietf.org/rfc/rfc4122.txt
#broofa provided a simple way to generate a RFC4122-compliant UUID in JavaScript here. Quoting it here for the sake of completeness:
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
In the Security model for out ASP.Net website (.Net 3.5) we store the page name:
page.GetType().Name
as the primary key in a database table to be able to lookup if a user has access to a certain page. The first time a page is visited this record is created automatically in the database.
We have exported these database statements to insert scripts, but each time a new page gets created we have to update the scripts, not a huge issue, but I would like to find an automated way to do this.
I created an attribute that I tagged a few pages with and then wrote a small process to get all the objects that have this attribute, through the reflection create an instance and insert the record using the same code to for page records mentioned above:
IEnumerable<Type> viewsecurityPages = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsDefined(typeof(ViewSecurityAttribute),false));
foreach (Type t in viewsecurityPages)
{
object obj = Activator.CreateInstance(t, false);
//clip..(This code just checks if the record already exists in the DB)
if (feature == null)
{
Attribute attb = Attribute.GetCustomAttribute(t, typeof(ViewSecurityAttribute));
if (attb != null)
{
CreateSecurableFeatureForPage((Page)obj, uow, attb.ToString());
}
}
}
The issue is that page.GetType().Name when the page goes through the actual page cycle process is something like this:
search_accounts_aspx
but when I used the activator method above it returns:
Accounts
So the records don't match the in the security table. Is there anyway to programtically "visit" a webpage so that it goes through the actual page lifecycle and I would get back the correct value from the Name parameter?
Any help/reference will be greatly appreciated.
Interesting problem...
Of course there's a (too obvious?) way to programmatically visit the page... use System.Net.HttpWebRequest. Of course, that requires the URI and not just a handle to the object. This is a "how do we get there from here?" problem.
My suggestions would be to simply create another attribute (or use that same one) which stores the identifier you need. Then it will be the same either way you access it, right?
Alternatively... why not just use a 3rd party web spider/crawler to crawl your site and hit all the pages? There are several free options. Or am I missing something?