Azure AppInsights alert notifications of warnings - azure

I have the following Azure function:
[FunctionName("FunctionSync")]
public async Task Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger _log) // where ILogger is Microsoft.Extensions.Logging.ILogger
{
try
{
// some code
}
catch (VerizonUnexpectedResponseException ex)
{
log.LogError($"{ex.Message}; response text: '{ex.ResponseText}'");
}
catch(VerizonUnsuccessfulResponseException failed_ex)
{
log.LogWarning($"Unexpected response; Error: '{failed_ex.Response.Error}', Description: '{failed_ex.Response.Description}'");
}
}
So, I wrote to AI some messages as Warning and Error when some conditions are true...
Right now I want to create Alert notifications (to email, for example), I go to Azure App Insights -> Rules -> Create New Rule and I don't understand which Signal Name should I select for it?

Custom log search, where the search could be something like
traces
| where message contains "some recognizable part of your message"
or
exceptions
| where type contains "VerizonUnexpectedResponseException"
or type contains "VerizonUnsuccessfulResponseException"

You should use custom log search.
When create the alert rule, for resources, you should select the connected Application Insights instead of the function app. Then for Condition, select Custom log search.
As per your code, both the messages from log.LogError and log.LogWarning will be flowed into traces table. For messages from log.LogError, the severityLevel property will be set as 3; For messages from log.LogWarning, the severityLevel property will be set as 2. And you can also use cloud_RoleName(here, it should be your function app name) property to identify your function app.
So in Custom log search, the query should look like below:
traces
| where severityLevel in (2,3)
| where cloud_RoleName == "function app name"
Then you can continue configure other settings for this alert rule.

Related

metadata in the insight query for QnAMaker logs

Please let me know how to include metadata in the insight query for QnAMaker logs
something as this, here the meatadata field comes empty
| where url endswith "generateAnswer"
| project timestamp, id, url, resultCode, duration, performanceBucket
| parse kind = regex url with *"(?i)knowledgebases/"KbId"/generateAnswer"
| join kind= inner (
traces | extend id = operation_ParentId
) on id
| extend question = tostring(customDimensions['traces'])
| extend answer = tostring(customDimensions['Answer'])
| extend score = tostring(customDimensions['Score'])
| extend metadata = tostring(customDimensions['qnaMakerOptions'])
| project answer,['metadata']
To help the other community Members posting the suggestion from the GITHUB where the issue is discussed.
If you look within the customEvents table, you can find an event with the name 'QnAMessage' - this is an event that is produced by the underlying QnAMaker service within the Bot Framework SDK, and produces more information beyond the trace event you identified. The corresponding class is Microsoft.Bot.Builder.AI.QnA.QnAMaker, located within the microsoft/botbuilder-dotnet repo.
With this class, it is possible to supply custom event properties and metrics that can be captured within Application Insights. To do this, the recommendation would be to create a custom dialog that inherits from QnAMakerDialog, and add logic as appropriate to supply any additional telemetry properties and metrics.
There is a sample custom dialog, the MultiplyDialog in the samples repo that shows how to write a custom dialog.
The general approach you would take is to write a custom dialog extending from QnAMakerDialog, probably overriding the protected getQnaMakerClient(...) method to return a custom QnAMaker implementation that includes the metadata you care about in the on QnaResults method. Below is some pseudocode that illustrates the example
class CustomQnAMakerDialog extends QnAMakerDialog {
async getQnaMakerClient(dialogContext) {
const client = await super.getQnAMakerClient(dialogContext);
const onQnaResults = client.onQnaResults.bind(client);
client.onQnaResults = (qnaResults, turnContext, properties = {}, metrics = {}) => {
properties = { ...properties, custom: 'property' };
metrics = { ...metrics, custom: 1.0 };
return onQnaResults(qnaResults, turnContext, properties, metrics);
}
}
}
For more information about logging metadata into app insights for qna maker service refer the below git hub link with complete code
QnaMakerDialog & QnaMaker

Can't get nested StartOperation to show up in the filter dropdown

I have an ASP.NET Core application configured to log to Application Insights. I also have this method that I use to create dependencies within the Application Insights timeline:
private void TestLogOperations()
{
using (IOperationHolder<DependencyTelemetry> topHolder = telemetryClient.StartOperation<DependencyTelemetry>("TopOperation"))
{
logger.LogWarning("top holder log");
using (IOperationHolder<DependencyTelemetry> innerHolder = telemetryClient.StartOperation<DependencyTelemetry>("InnerOperation"))
{
logger.LogWarning("inner holder log");
}
}
}
The operations correclty appear nested within the timeline:
But when I want to filter by dependency (e.g I only want to filter logs within "InnerOperation"), they don't show up in the dropdown, only the top request operation is shown (localhost:5000 | POST User/Post):
I know it's possible to filter by dependencies because I've worked with projects that did it, but how do I do it?
As per my test, this is the default behavior for DependencyTelemetry.
If you want to show what you want in your post, you should change DependencyTelemetry to RequestTelemetry.
Here is the test code:
private void TestLogOperations()
{
using (IOperationHolder<RequestTelemetry> topHolder = telemetryClient.StartOperation<RequestTelemetry>("TopOperation1"))
{
//telemetryClient.TrackTrace("top holder log 111");
_logger.LogWarning("top holder log 1");
using (IOperationHolder<RequestTelemetry> innerHolder = telemetryClient.StartOperation<RequestTelemetry>("InnerOperation1"))
{
//telemetryClient.TrackTrace("inner holder log 1 111");
_logger.LogWarning("inner holder log 1");
}
}
}
And the test result:

How to stop 'Send order notification' & 'Send payment notification' in checkout process from code side in kentico

I know there is option in kentico admin setting to stop the sending notification email. but I want to check this in the code for my customization. so could you please suggest me where should I get the code in kentico.
Setting in kentico
Please refer to the official documentation.
You need to use SettingsKeyInfoProvider:
SettingsKeyInfoProvider.SetValue("CMSSettingName", "SiteName", value);
Leave out the site name parameter if you want to set it globally.
The settings names you are looking for are CMSStoreSendOrderNotification and CMSStoreSendPaymentNotification.
You can find more settings by querying the DB:
SELECT * FROM [CMS_SettingsKey] where keyname like '%cmsstoresend%'
If you are looking to intercept an action when a notification is being sent, you can use Global events for the EmailInfo object like this:
[assembly: RegisterModule(typeof(GlobalEventsModule))]
public class GlobalEventsModule : Module
{
public GlobalEventsModule() : base (typeof(GlobalEventsModule).Name)
{
}
protected override void OnInit()
{
base.OnInit();
EmailInfo.TYPEINFO.Events.Insert.Before += Insert_Before;
}
private void Insert_Before(object sender, ObjectEventArgs e)
{
// executed before an e-mail is inserted into DB
var email = (EmailInfo)e.Object;
}
}
To cancel the execution in code you can call Cancel() method (although you might get exceptions in this case - you have to test for yourself in your scenario):
private void Insert_Before(object sender, ObjectEventArgs e)
{
var email = (EmailInfo)e.Object;
e.Cancel();
}
This will also work only if you are using Email queue (which is highly recommended anyway) and will be executed for all outgoing e-mails, not just notifications.
Using the CMS.Ecommerce library you can check these settings through the API
SiteInfoIdentifier sii = new SiteInfoIdentifier(SiteContext.CurrentSiteID);
bool sendOrderNotificationEmail = CMS.Ecommerce.ECommerceSettings.SendOrderNotification(sii);
If you wanted to set them programmatically you would have to use the SettingsKeyInfoProvider
SettingsKeyInfoProvider.SetValue("CMSStoreSendOrderNotification ", false);

OMS log search doesnot display all the columns present in WADETWEventTable azure diagnostic table

I have a cusotm event source which has special properties like message, componentName,Priority.
[The custom etw event source properties gets converted into azure WADETWEventTable table columns] .
My idea is to view logs stored in azure tables by using Microsoft operations management suite (OMS). I can see the logs but it doesn't display all the columns.
But OMS doesnot display these columns. I am using below code/configuration-
[EventSource(Name = "CustomEtw.OperationTrace")]
public sealed class CustomEventSource : EventSource
{
public static CustomEventSource log = new CustomEventSource();
#region [Custom Event Source]
[Event(1, Level = EventLevel.Informational)]
public void Info(string message, string componentName, bool priority)
{
WriteEvent(1, message, componentName, priority);
}
[Event(2, Level = EventLevel.Warning)]
public void Warning(string warningData)
{
WriteEvent(2, warningData);
}
}
Above custom event source logs data on to ETW stream and the same is visible on azure diagnostic table i.e.WADETWEventTable. This Azure table has data in message,ComponentName and Priority columns as well, but OMS doesn't display these columns when we search thru log search.
Please help, am I missing any configuration that need to b done at OMS side?
Why OMS displays only few columns?

NServiceBus Event Subscriptions Not Working With Azure Service Bus

I'm attempting to modify the Azure-based Video Store sample app so that the front-end Ecommerce site can scale out.
Specifically, I want all instances of the web site to be notified of events like OrderPlaced so that no matter which web server the client web app happens to be connected to via SignalR, it will correctly receive the notification and update the UI.
Below is my current configuration in the Global.asax:
Feature.Disable<TimeoutManager>();
Configure.ScaleOut(s => s.UseUniqueBrokerQueuePerMachine());
startableBus = Configure.With()
.DefaultBuilder()
.TraceLogger()
.UseTransport<AzureServiceBus>()
.PurgeOnStartup(true)
.UnicastBus()
.RunHandlersUnderIncomingPrincipal(false)
.RijndaelEncryptionService()
.CreateBus();
Configure.Instance.ForInstallationOn<Windows>().Install();
bus = startableBus.Start();
And I've also configured the Azure Service Bus queues using:
class AzureServiceBusConfiguration : IProvideConfiguration<NServiceBus.Config.AzureServiceBusQueueConfig>
{
public AzureServiceBusQueueConfig GetConfiguration()
{
return new AzureServiceBusQueueConfig()
{
QueuePerInstance = true
};
}
}
I've set the web role to scale to two instances, and as expected, two queues (ecommerce and ecommerce-1) are created. I do not, however, see additional topic subscriptions being created under the videostore.sales.events topic. Instead, I see:
I would think that you would see VideoStore.ECommerce-1.OrderCancelled and VideoStore.ECommerce-1.OrderPlaced subscriptions under the Videostore.Sales.Events topic. Or is that not how subscriptions are stored when using Azure Service Bus?
What am I missing here? I get the event on one of the ecommerce instances, but never on both. Even if this isn't the correct way to scale out SignalR, my use case extends to stuff like cache invalidation.
I also find it strange that two error and audit queues are being created. Why would that happen?
UPDATE
Yves is correct. The AzureServiceBusSubscriptionNamingConvention was not applying the correct individualized name. I was able to fix this by implementing the following EndpointConfig:
namespace VideoStore.ECommerce
{
public class EndpointConfig : IConfigureThisEndpoint, IWantCustomInitialization
{
public void Init()
{
AzureServiceBusSubscriptionNamingConvention.Apply = BuildSubscriptionName;
AzureServiceBusSubscriptionNamingConvention.ApplyFullNameConvention = BuildSubscriptionName;
}
private static string BuildSubscriptionName(Type eventType)
{
var subscriptionName = eventType != null ? Configure.EndpointName + "." + eventType.Name : Configure.EndpointName;
if (subscriptionName.Length >= 50)
subscriptionName = new DeterministicGuidBuilder().Build(subscriptionName).ToString();
if (!SettingsHolder.GetOrDefault<bool>("ScaleOut.UseSingleBrokerQueue"))
subscriptionName = Individualize(subscriptionName);
return subscriptionName;
}
public static string Individualize(string queueName)
{
var parser = new ConnectionStringParser();
var individualQueueName = queueName;
if (SafeRoleEnvironment.IsAvailable)
{
var index = parser.ParseIndexFrom(SafeRoleEnvironment.CurrentRoleInstanceId);
var currentQueue = parser.ParseQueueNameFrom(queueName);
if (!currentQueue.EndsWith("-" + index.ToString(CultureInfo.InvariantCulture))) //individualize can be applied multiple times
{
individualQueueName = currentQueue
+ (index > 0 ? "-" : "")
+ (index > 0 ? index.ToString(CultureInfo.InvariantCulture) : "");
}
if (queueName.Contains("#"))
individualQueueName += "#" + parser.ParseNamespaceFrom(queueName);
}
return individualQueueName;
}
}
}
I could not, however, get NServiceBus to recognize my EndpointConfig class. Instead, I had to call it manually before starting the bus. From my Global.asax.cs:
new EndpointConfig().Init();
bus = startableBus.Start();
Once I did this, the subscription names appeared as expected:
Not sure why it's ignoring my IConfigureThisEndpoint, but this works.
This sounds like a bug, can you raise a github issue on this at https://github.com/Particular/NServiceBus.Azure
That said, I think it's better to use signalr's scaleout feature instead of using QueuePerInstance as signalr needs to replicate other information like (connection/group mappings) internally as well when running in scaleout mode.
Update:
I think I see the issue, the subscriptions should be individualised as well, which isn't the case in current naming conventions
https://github.com/Particular/NServiceBus.Azure/blob/master/src/NServiceBus.Azure.Transports.WindowsAzureServiceBus/NamingConventions/AzureServiceBusSubscriptionNamingConvention.cs
while it is in the queuenamingconventions
https://github.com/Particular/NServiceBus.Azure/blob/master/src/NServiceBus.Azure.Transports.WindowsAzureServiceBus/NamingConventions/AzureServiceBusQueueNamingConvention.cs#L27
As these conventions are public you can override them to work around the problem by changing the func in IWantCustomInitialization until I can get a fix in, just copy the current method and add the individualizer logic. The queue individualizer is internal though, so you'll have to copy that class from
https://github.com/Particular/NServiceBus.Azure/blob/master/src/NServiceBus.Azure.Transports.WindowsAzureServiceBus/Config/QueueIndividualizer.cs

Resources