I have implemented Azure App Insights for my .NET 6 application. Does anyone know why innermostAssembly is empty? This screen is from "Monitoring" > "Logs" in Azure Application Insights
Because it has no inner exception.
Take this example code:
var simpleException = new Exception("simpleException");
var nestedException = new Exception("nestedException", new Exception("innerexceptino"));
_telemetryClient.TrackException(simpleException);
_telemetryClient.TrackException(nestedException);
This will be the result:
The logged simpleException won't have the innermost fields filled, the logged nestedException will.
Related
I'm currently using an .NET 6.0 isolated function with an HTTP trigger.
Because the activity is not being filled, I've added a middleware that creates the activity based on the W3C traceparent header.
My expectation based on MS docs is that when using Application Insights, the operation_ParentId would relate directly to the ParentSpanId of an Activity where logging is done.
Yet that is not what I'm seeing. What I'm seeing is following
Application A sends a request using traceparent = 00-3abe9f15e940badc5f1521e6eb1eb411-bfd30439c918c783-00
In middleware of application B, an activity is started and a message is logged. I can also validate that the ParentId of the activity is equal to 00-3abe9f15e940badc5f1521e6eb1eb411-bfd30439c918c783-00. The ParentSpanId is equal to bfd30439c918c783
using var requestActivity = new Activity(context.FunctionDefinition.Name);
requestActivity.SetParentId(traceParent);
requestActivity.Start();
_logger.LogInformation("Invoking '{Name}'", context.FunctionDefinition.Name);
In application insights I see OperationId being equal to the WC3 trace-id 3abe9f15e940badc5f1521e6eb1eb411 as expected. However, the operation_ParentId is a span I've not seen before. It is neither the requestActivity.SpanId nor the requestActivity.ParentSpanId.
What is happening that I do not understand? Does Application Insights not use the active Activity when logging?
my app configuration
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(worker =>
{
worker.UseMiddleware<TracingMiddleware>();
})
.ConfigureServices(collection =>
{
})
.ConfigureLogging(x=>x.AddApplicationInsights())
.Build();
host.Run();
My middleware function
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
using var requestActivity = new Activity(context.FunctionDefinition.Name);
SetParentId(context, requestActivity);
requestActivity.Start();
_logger.LogInformation("Invoking '{Name}'", context.FunctionDefinition.Name);
var t = Activity.Current;
System.Console.WriteLine();
System.Console.WriteLine($"Activity.TraceId: {t.TraceId}");
System.Console.WriteLine($"Activity.ParentId: {t.ParentId}");
System.Console.WriteLine($"Activity.SpanId: {t.SpanId}");
await next(context);
var statusCode = (context.Items != null)
? context.GetHttpResponseData()?.StatusCode
: System.Net.HttpStatusCode.OK;
_logger.LogInformation(
"Executed '{Name}', Result {Result}, Duration = {Duration}ms",
context.FunctionDefinition.Name,
statusCode,
(DateTime.UtcNow - requestActivity.StartTimeUtc).TotalMilliseconds);
requestActivity.Stop();
}
As per the MS-Doc the Operation ID is equal to TraceId. And the Operation_parent Id has the combination of both Trace-ID with Parent-ID. The Format has .
The operation_ParentId field is in the format
<trace-id>.<parent-id>, where both trace-id and parent-id are
taken from the trace header that was passed in the request.
I have noticed that It was not actually same. I have tired with many possible ways. I end up with The operation-ID is not equal to the Trace-ID and the Operation-parent-ID is not equal to < Trace-ID>.< Parent-ID>.
In my middle ware i have added the current context like below
ILogger logger = context.GetLogger<MyCustomMiddleware>();
//logger.LogInformation("From function: {message}", message);
using var requestActivity = new Activity(context.FunctionDefinition.Name);
//t.SetParentId(context, requestActivity);
requestActivity.Start();
logger.LogInformation("Invoking '{Name}'", context.FunctionDefinition.Name);
//requestActivity.SetParentId(Convert.ToString(requestActivity.RootId));
requestActivity.SetParentId(requestActivity.TraceId,requestActivity.SpanId,ActivityTraceFlags.None);
var t = Activity.Current;
//Activity.SetParentId(context, requestActivity,);
//t.SetParentId(context, requestActivity)
logger.LogInformation($"Activity.TraceId: {t.TraceId}");
logger.LogInformation($"Activity.ParentId: {t.ParentId}");
logger.LogInformation($"Activity.SpanId: {t.SpanId}");
logger.LogInformation($"Activity.Id: {t.Id}");
logger.LogInformation($"Activity.ParentSpanId: {t.ParentSpanId}");
logger.LogInformation($"Activity.RootId: {t.RootId}");
logger.LogInformation($"Activity.Parent: {t.Parent}");
Result I got.
Refer here for one of my workarounds with more details.
I have a logic app that has more than 100 actions. I am using following code to get all the actions and status for a logic app run,
return _client
.WorkflowRunActions
.ListWithHttpMessagesAsync(_resourceGroup, logicApp, workflowRunName)
.Result.Body.OrderBy(x => x.StartTime);
But it only returns 30, not all actions. In my logic app, I have some actions to insert a record to Azure Sql tables, for instance,
But those actions were not returned by above code. Also I noticed all the actions under conditions were not returned either. Can anyone share some thoughts?
In the Result Body, there is a NextPageLink property, it's used to get the next response page. You could refer to my below code.
Task<AzureOperationResponse<IPage<WorkflowRunAction>>> actions = client.WorkflowRunActions.ListWithHttpMessagesAsync(resourceGroupName: "resource group name", workflowName: "gelogic", runName: "run name");
var nextaction = client.WorkflowRunActions.ListNextWithHttpMessagesAsync(actions.Result.Body.NextPageLink);
var numerator = nextaction.Result.Body.GetEnumerator();
while (numerator.MoveNext()) {
WorkflowRunAction item = numerator.Current;
Console.WriteLine(item.Name);
}
I am following the example in the link https://github.com/microsoftgraph/msgraph-training-changenotifications and creating and updating the notification subscription using a timer class.
[HttpGet]
public ActionResult<string> Get()
{
var graphServiceClient = GetGraphClient();
var sub = new Microsoft.Graph.Subscription();
sub.ChangeType = "updated";
sub.NotificationUrl = config.Ngrok + "/api/notifications";
sub.Resource = "/users";
sub.ExpirationDateTime = DateTime.UtcNow.AddMinutes(5);
sub.ClientState = "SecretClientState";
var newSubscription = graphServiceClient
.Subscriptions
.Request()
.AddAsync(sub).Result;
Subscriptions[newSubscription.Id] = newSubscription;
if(subscriptionTimer == null)
{
subscriptionTimer = new Timer(CheckSubscriptions, null, 5000, 15000);
}
return $"Subscribed. Id: {newSubscription.Id}, Expiration: {newSubscription.ExpirationDateTime}";
}
But I have noticed the timer does not always get triggered(eg: network related issue/ after a fresh deployment of the code).
Is there a better way to replace this timer?
I have heard about webjobs in azure, is it possible to replace this timer with azure webjobs? If so can someone point me to some documentation on how?
I noticed you're using ASPNET, if you're using the ASPNETCORE version, since 2.x, you can have background services that you could run every X hours to resubscribe (update) the subscriptions. That's what we're using (and we're on Azure). I would guess webjobs could do the trick, but I have not used them yet. You could also have an external service that calls one of your endpoints every X hours (like a CRON job) .
hope this helps!
JS
I have a console application logging to TrackRequest in a TelemetryClient, but I can't figure out what tile to display in the Azure portal to see the data.
Is there some guidance that lists each method, the data, and what tile exposes it?
With the following code in a console app:
TelemetryClient client = new TelemetryClient(new TelemetryConfiguration()
{
InstrumentationKey = "<your ikey>",
TelemetryChannel = new InMemoryChannel()
});
client.TrackRequest("Hello", DateTimeOffset.Now, TimeSpan.FromSeconds(1), "200", true);
Console.ReadLine();
Request data will appear on main overview page and in search results.
I know there is a way to determine the number of messages (or approximate number) in the Azure Queue (Store Account); however is there a way to query for the number of pending messages on an Azure Service Bus queue?
var nsmgr = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(connectionString);
long count = nsmgr.GetQueue(queueName).MessageCount;
It is called MessagesCountDetails.ActiveMessageCount.
It returns the number of the Active Messages in the Queue. You probably have some Dead letter messages:
var msg = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(Settings.Default.ConnectionString);
numofmessages.Text = msg.GetQueue(QueueName).MessageCountDetails.ActiveMessageCount.ToString();
Correct answer as of 2020+
Use of new packages as follows:
<PackageReference Include="Azure.Messaging.ServiceBus" Version="x.x.x" />
also two namespaces in the same package
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
and then you can use the new class ServiceBusAdministrationClient
var administrationClient = new ServiceBusAdministrationClient("connectionString");
var props = await administrationClient.GetQueueRuntimePropertiesAsync("queue");
var messageCount = props.Value.ActiveMessageCount;
have you looked at the Queue Description API? There's a property called MessageCount.
Here's the .NET SDK reference documentation page as well.
Based off what Joseph had as an answer I came up with, but for Topics and Subscriptions.
public async Task<long> GetCounterMessages()
{
var client = new ManagementClient(ServiceBusConnectionString);
var subs = await client.GetSubscriptionRuntimeInfoAsync(TopicName, SubscriptionName);
var countForThisSubscription = subs.MessageCount; //// (Comes back as a Long.)
return countForThisSubscription;
}
I ran into this same problem trying to get the count from the dead letter queue. It looks like the deadletterqueue doesn't allow you to get a count directly, you get it from the MessageCountDetails of the normal Queue.
string connectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.Connstr"].ToString();
NamespaceManager nsmgr = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(connectionString);
return nsmgr.GetQueue(QueueName).MessageCountDetails.DeadLetterMessageCount;
Here's a PowerShell example to continually eyeball the queue length as used in Azure Portal Cloud Shell
cd "Azure:\<MySubscription>\"
while (1) {(Get-AzureRmServiceBusQueue -ResourceGroup <myRG> -NamespaceName <myNS> -QueueName <myQueueName>).CountDetails | Select -expand ActiveMessageCount}
I've spent good 2 hours digging through docs to get that and for people using .net core and Microsoft.Azure.ServiceBus nuget package, code looks like that:
var managementClient = new ManagementClient("queue connection string"));
var runtimeInfo = await managementClient.GetQueueRuntimeInfoAsync("queueName");
var messagesInQueueCount = runtimeInfo.MessageCountDetails.ActiveMessageCount;
Aparently you get the information about all Counts(including deadletter, active, etc.) from QueueRuntimeInfo object instead of old QueueDescription object.
As per the recommendation by Microsoft, it is recommended to use Microsoft.Azure.ServiceBus in which you can easily fetch the message count by
var managementClient = new ManagementClient("connection string for queue");
var queue = await managementClient.GetQueueRuntimeInfoAsync("queue name");
var messages = queue.MessageCount;
Also..you can check the pending messages on Azure Management Portal...on the dashboard for service bus queue...under quick glance...you can see the queue length...this is the number of current/pending messages in length at the time of dashboard page load.