Trace Telemetry not showing up on Azure Portal - azure

I have an MVC app running on local IIS server. I have an existing App Insights resource on Azure where I want Telemetry from my app to show up. However, Trace messages are not showing up on Azure Portal. I have added ApplicationInsights to my project, specified the resource where Telemetry should show up in ApplicationInsights.config and also written a TelemetryWrapper that I use in my code to send out the actual Telemetry Info and Error messages.
I initialize the Telemetry service through the wrapper:
TelemetryWrapper.InitializeTelemetry("InstrumentationKey", "ApplicationName");
And send out messages from the wrapper too
TelemetryWrapper.TelemetryInfo(requestId, action, userId, ultimateId, systemId, payload);
An overview of the TelemetryWrapper:
public static void InitializeTelemetry(string apiKey, string appId)
{
bool postBackground = true;
_telemetry = new TelemetryHelper(apiKey, appId, false) { PostBackground = postBackground };
}
public static void TelemetryInfo(Guid requestId, string action, Guid userId, string ultimateId, string systemId,
string payload)
{
var telem = CreateInstance(requestId, action, ultimateId, userId, systemId, payload);
_telemetry.Info(telem);
}
What am I possibly doing wrong?

Need more information. all you've shown is your code, there's no AppInsights code here to look at. so it could be that your TelemetryHelper class isn't setting the ikey correctly, the ikey could be invalid.
However: The one thing that jumps out at me is your usage of the terms apiKey and appId in your code.
Those 2 things have specific meaning in application insights, but that is for reading data from the AI API services (and apiKey in that context is something you could consider a secret, as if someone has those keys they can read all of your data!) I'm not sure if you're using them in a different context here but that jumped out at me right away.
There's a different thing, "Instrumentation Key" or iKey that you use to send data to application insights. Are you possibly switching those things around and trying to use an AI appId and apiKey in place of an iKey?
One way to check is to use fiddler or some other tool locally to watch outbound http traffic. configure it to decrypt https, and watch for outbound calls to dc.services.visualstudio.com, which is where your telemetry is going. If you have outbound calls, then it is at least trying to send your telemetry. If those calls are failing, the response might tell you that the iKey you are using is invalid, if this is the case.
You do not need

Related

How to add custom properties to HTTPS calls so I can see them in Azure Application Insights?

I have a C# client application that calls a web application in Azure (also in written in C#, ASP .NET Core). Traffic gets captured in Azure Log Analytics so I can see it in Azure Application Insights.
When calling the web application from my client application, I would like to add some information about the version of the client application. I want this information to be easily viewable in Application Insights.
I notice that the requests table in Application Insights has a column called customDimensions. Maybe I can put stuff there, but I don't know how.
My idea is to add this information as a header and somehow configure the application to copy this information from the header into customDimensions. Is this a good way to go? If so, how do I accomplish the latter half (configure the application to copy this information from the header into customDimensions)?
You could write a telemetry initializer for this, as explained in the docs:
Use telemetry initializers to enrich telemetry with additional information or to override telemetry properties set by the standard telemetry modules.
There is a base class (TelemetryInitializerBase) that you can use which provides access to the http context to get details of the headers:
public class CustomInitializer : TelemetryInitializerBase
{
public CustomInitializer(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
{
var appVersion = platformContext.Request.Headers["x-app-version"].ToString();
if(!string.IsNullOrWhiteSpace(appVersion))
requestTelemetry.Properties["appVersion"] = appVersion;
}
}
Add this initializer to the web app running in Azure. Then, in the customDimensions field of the request telemetry you can find the value of appVersion.
Another option is to set custom propertions in the controller action like this:
var appVersion = Request.Headers["x-app-version"].ToString();
if (!string.IsNullOrWhiteSpace(appVersion))
{
var requestTelemetry = HttpContext.Features.Get<RequestTelemetry>();
requestTelemetry.Properties.Add("appVersion", appVersion);
}

How to get cpu/memory/network usage percentage in ASP.NET Core to do throttling?

My web application is deployed in azure, which is implemented in Asp.Net Core. I want to throttle requests basing on cpu/memory/network usage percentage. For example, when the cpu usage is above 90%, the throttling component will throttle 50% of the requests.
The big question is:
How to get cpu/memory/network usage percentage in ASP.NET Core?
As far as I know, azure WebApp is a sandbox, we don't have enough permission to access the Azure web app's worker server's metrics.
The user account must either be a member of the Administrators group or a member of the Performance Monitor Users group in Windows.
Here is a workaround, we could enable the application Insight to do that. We need to configurate Application Insight for Azure WebApp. Details, you could refer to this doc.
We could use Application Insight rest api to get the current web app's metrics like process cpu usage. API Document.
We could get the application id and api key in the Application Insight portal like below image shows:
Details, you could refer to this article.
Then you could use below codes to send request to Application Insight API to get current CPU usage.
public static string GetTelemetry(string appid, string apikey)
{
string Url = "https://api.applicationinsights.io/v1/apps/{0}/metrics/performanceCounters/processCpuPercentage";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", apikey);
var req = string.Format(Url, appid);
HttpResponseMessage response = client.GetAsync(req).Result;
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
else
{
return response.ReasonPhrase;
}
}
Result:

Azure Identity: Trying to get GetUserDelegationKey to work with an application Service Principal

It's not a good sign when the method I'm asking about, GetUserDelegationKey, yields zero search results on SO. Good luck, me.
I have a C# console app, .Net framework 4.8, using Azure.Storage.Blobs and Azure.Identity that will run on customer servers and access Azure blob storage to hold some stuff. I'm doing all of this with the library, not rolling my own REST. Built with VS2019, testing on Win10.
The plan is to use a single Azure storage account that I own, and create one Container per customer project with per-customer credentials that permit them only their own container. Projects never ever talk to each other.
I could set up credentials in the Azure portal by hand, but I am stubbornly trying to do this in software, where a simple project-management app connects as the project app's service principal (which I defined in Azure AD), creates the container, then creates the shared access signatures with a limited lifetime.
The storage account name / container name / access signature would then be configured on the customer server.
I'm having a terrible time.
Note: this is using the newer BlobClient mechanisms, not the older CloudBlob stuff. Dunno if that matters.
This is all documented here at Microsoft, and following even the simple example gets me the same failure.
using System;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Identity;
namespace Azure.Test
{
class Program
{
static void Main(string[] args)
{
var serviceClient = new BlobServiceClient(
new Uri("https://stevestorageacct.blob.core.windows.net"),
new DefaultAzureCredential(true)); // true=pop up login dlg
/*BOOM*/ UserDelegationKey key = serviceClient.GetUserDelegationKey(
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(30));
// use the key to create the signatures
}
}
}
Even though this program couldn't be simpler, it fails every time with an XML error calling GetUserDelegationKey
Unhandled Exception: Azure.RequestFailedException: The value for one of the XML nodes is not in the correct format.
RequestId:c9b7d324-401e-0127-4a4c-1fe6ce000000
Time:2020-05-01T00:06:21.3544489Z
Status: 400 (The value for one of the XML nodes is not in the correct format.)
ErrorCode: InvalidXmlNodeValue
The XML being sent is supposed to be super simple, I think just the start/end dates for validity, but I have no idea how to get to it to inspect, and http is forbidden for this kind of call, so no Wireshark.
It also fails the same way when I use my application's service principal:
static void Main(string[] args)
{
var tokenCredential = new ClientSecretCredential(
"xxxx-xxxx-xxxx-xxxxx", // tenant ID
"yyyy-yyyy-yyyy-yyyyy, // application ID
"**************"); // client secret
var serviceClient = new BlobServiceClient(
new Uri("https://stevestorageacct.blob.core.windows.net"),
tokenCredential);
UserDelegationKey key = serviceClient.GetUserDelegationKey(
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(30));
// ALSO: boom
I'm really at a loss.
I suppose I could try rolling my own REST and playing with it that way, but it doesn't feel like this should be necessary: this kind of error feels like a bug even if I'm doing something wrong. XML nodes?
Also open to entirely different ways of approaching this problem if they are superior, but would like to at least find out why this is failing.
I've had some issues with this also. The first things to try is removing the start time (pass null) or setting it ~15 minutes in the past. This is to avoid clock skew between the requesting pc and azure servers.
The second thing to verify is that the user that you are using has the "Storage Blob Data Contributor" role on the storage account. I had to grant it at the storage account level in the end otherwise it just refused to work for me. However in your use case it might be that you need to grant it at the container level to allow you to have one container per client.
Hope this helps.

webapi to IoTHub not working from Azure deployment

was: "Iot Hub diagnostics azure deployed app"
Strange issue. I have a very simple 4.5.2 based webapi application that acts as a field gateway; that is each method connects to IoT Hub on behalf of the consumer which are actual devices capable of only posting to HTTP endpoints.
When I run the code from my local development machine everything works as expected and my IoT Hub receives the data. so, then, I published the webapi application to azure and ran the same methods but there is no activity to the IoT Hub detected at all. weird. I went so far as to debug the application code in azure and everything is working without error. There's no external configuration to mess things up at the moment, its all in the code.
Is there are logical explanation for this behavior?
I'm new to IoT Hub so maybe this is a simple thing. Where can I turn on verbose diagnostics? Since I have code that I believe to be working where can I see the next logical information? Are there permissions of some sort that may be preventing the data to pass through?
WebApi method(s) basically call this code which is contained in a separate assembly
public static void SendTempData(string Name, string value)
{
var telemetryDataPoint = new
{
deviceId = HOME_TEMP_DEVICE,
DeviceName = Name,
TValue = value
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
var task = Task.Run(() =>
{
deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey(HOME_TEMP_DEVICE, HOME_TEMP_DEVICE_KEY), TransportType.Mqtt);
var message = new Message(Encoding.ASCII.GetBytes(messageString));
deviceClient.SendEventAsync(message);
});
WaitForTask(ref task);
CheckForFail(task);
}
private static void WaitForTask(ref Task task)
{
while (task.Status != TaskStatus.RanToCompletion)
{
if ((task.IsCanceled) || (task.IsFaulted))
break;
System.Diagnostics.Debug.WriteLine("Thread ID: {0}, Status: {1}", Thread.CurrentThread.ManagedThreadId, task.Status);
}
}
Bottom line is I have no visibility. Is there some verbose setting I can enable to see why IoTHub never sees a connection or data?

How to get the details of a continuous Azure WebJob invocation

Looking at the Kudu Azure WebJobs API docs https://github.com/projectkudu/kudu/wiki/WebJobs-API I see there are several calls I can do to manage WebJobs programmatically.
What is missing is a call to get, for a continuous webjob, the details of a single invocation. With invocation I mean the single execution of the function for a given message.
What I am trying to do is, for a message getting in the poison queue, to get the exception message of the parent invocation. In the poison message I get the id of the parent invocation with the json prop $AzureWebJobsParentId.
I would like to manage the poison queue with a function that emails the details of the error and moves the message in a dead-letter queue.
Any idea if this is possible?
The Azure WebJobs SDK Core extensions contain a binding for ExecutionContext which allows you to access invocation specific system information in your function. An example showing how to access the function Invocation ID:
public static void ProcessOrder(
[QueueTrigger("orders")] Order order,
TextWriter log,
ExecutionContext context)
{
log.WriteLine("InvocationId: {0}", context.InvocationId);
}
The invocation ID is used in the Dashboard logs, so having access to this programatically allows you to correlate an invocation to those logs.
Create a function specific error handler that will only handle errors for one function. This is done by naming convention based on an "ErrorHandler" suffix.
public static void ProcessOrderErrorHandler(
[ErrorTrigger()] TraceFilter filter,
TextWriter log)
{
var lastMessage = filter.Message;
var lastMessages = filter.GetDetailedMessage(5);
}
For email notifications
public static void ErrorMonitor(
[ErrorTrigger("0:30:00", 10, Throttle = "1:00:00")] TraceFilter filter,
[SendGrid] SendGridMessage message)
{
message.Subject = "WebJobs Error Alert";
message.Text = filter.GetDetailedMessage(5);
}
There's not an official way to do this yet, but there's an issue to track exposing stable APIs (C# and REST) for reading the individual function instances: See https://github.com/Azure/azure-webjobs-sdk/issues/880 for status
Given a WebJobs SDK invocation ID, you can access the details of that execution via the WebJobs Dashboard. You can access the Dashboard via the WebJobs blade in the portal (the link will be in the "LOGS" column).
Or in the browser you can form the URL yourself, for example (substituting your app name and invocation ID):
https://<yourapp>.scm.azurewebsites.net/azurejobs/#/functions/invocations/<invocation-id>
That is how you would access these details manually.

Resources