microsoft / ApplicationInsights-dotnet

ApplicationInsights-dotnet
MIT License
567 stars 285 forks source link

EventCounters in ASP.NET framework 4.8 #2375

Closed esyker closed 3 years ago

esyker commented 3 years ago

Are Event Counters only available for ASP.NET core and not for ASP.NET framework?

https://docs.microsoft.com/pt-pt/azure/azure-monitor/app/eventcounters

Couldn't find any documentation for ASP.NET framework, in my case 4.8.

This is also what seems from the github repo documentation:

https://github.com/Microsoft/ApplicationInsights-dotnet

cijothomas commented 3 years ago

The package is netstandard2.0, so you can use it in .NET core and .NET framework.

esyker commented 3 years ago

Yes I know I can use these classes in the SDK, but how do I configure the services to use the EventCountCollector, since there is no ConfigureServices function in ASP.NET? No example from the documentation https://docs.microsoft.com/pt-pt/azure/azure-monitor/app/eventcounters.

Also I checked that you cant configure dependency injection (configure services in ASP.NET): https://stackoverflow.com/questions/45222923/asp-net-classic-owin-startup-configureservices-not-called .

I tried calling the EventCountCollector and initialize with the current configuration in the Utilities Class.

` namespace Utilities { public class AppInsightsTelemetry { private static Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionModule collector = new Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionModule();

    static AppInsightsTelemetry()
    {
        collector.Initialize(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active);
    }

    public static void EventCounterCollector(string eventSourceName, string eventCounterName)
    {
        collector.Counters.Add(new EventCounterCollectionRequest(eventSourceName, eventCounterName));
    }
}

} `

Then in Global.asx.cs, in Application_Start I tried to configure the EventCountCollector, calling the utilities function.

void Application_Start(object sender, EventArgs e) { Utilities.AppInsightsTelemetry.EventCounterCollector("Clicked button", "Clicked button Count"); }

However this approach did not work. Can you help me with this one please? Provide a link if possible for documentation on how to configure the services in ASP.NET framework, since I can only find documentation for ASP.NET core.

cijothomas commented 3 years ago

Please try the below:

var eventCounterModule = new EventCounterCollectionModule();
eventCounterModule.Counters.Add(new EventCounterCollectionRequest("MyEventSource", "MyCounter")); // keep adding all your counters
eventCounterModule.Initialize(TelemetryCofiguration.Active);

(I assume you have already setup ikey,channel etc to TelemetryConfiguration.Active)

esyker commented 3 years ago

So I have done this inside Global.asax.cs Application_Start function and it does not work. All the other metrics are tracked correctly but no EventCounter metric appears.

Button on_click function:

protected void btnSubmit_Click(object sender, EventArgs e)
        {
            Utilities.AppInsightsTelemetry.TrackEvent("Clicked button", new Dictionary<string, string> { { "BtnType", "Contact" } },
                null);
}

Application_Start function, notice the last 3 lines where I add the EventCounterCollector:

        void Application_Start(object sender, EventArgs e)
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            RouteTable.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = System.Web.Http.RouteParameter.Optional }
            );
            Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey = INSTRUMENTATION_KEY;
            Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.ConnectionString = CONNECTION_STRING;

            Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionModule
                            collector = new Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionModule();
            collector.Initialize(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active);
            collector.Counters.Add(new Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionRequest("Clicked button", "Clicked button count"));

        }

I think I need to attach this to the service, like in the ASP.NET core syntax, isn't it? The catch is there is no way to Configure Services in ASP.NET framework 4.8.

    public void ConfigureServices(IServiceCollection services)
    {
        //... other code...

        // The following code shows how to configure the module to collect
        // additional counters.
        services.ConfigureTelemetryModule<EventCounterCollectionModule>(
            (module, o) =>
            {
                // This removes all default counters, if any.
                module.Counters.Clear();

                // This adds a user defined counter "MyCounter" from EventSource named "MyEventSource"
                module.Counters.Add(new EventCounterCollectionRequest("MyEventSource", "MyCounter"));

                // This adds the system counter "gen-0-size" from "System.Runtime"
                module.Counters.Add(new EventCounterCollectionRequest("System.Runtime", "gen-0-size"));
            }
        );
    }
cijothomas commented 3 years ago

I think I need to attach this to the service, like in the ASP.NET core syntax, isn't it?

No. There are plenty of unittests on it, which has working sample codes: https://github.com/microsoft/ApplicationInsights-dotnet/blob/develop/WEB/Src/EventCounterCollector/EventCounterCollector.Tests/EventCounterCollectionModuleTests.cs

esyker commented 3 years ago

I have everything correctly configured. All the other events both client-side and server-side appear (requests, pageViews, exceptions, traces) appear. When I make an event of type "Clicked button" no metric of type "Clicked button count" appears in customMetrics. However the "Clicked button" event appears in customEvents.

Do I have to define a metric in another way? I tried to make the configuration you said (I had already done before you said it) inside Application_Start and inside the buttonSubmit_Click event. Neither of these approaches work. I have checked in run time inside Application_Start with the debugger and both instrumentation key and channel are properly set. Additionally, if this wasn't enough, I initialized the collector inside btnSubmit_onClick function, in case there was an error in doing it inside Application_Start because Application Insights haven't already started or something out of my scope.

Is it because I need to manually add a line to add EventCounterCollectors to ApplicationInsights.config? I think when I had the module through nugget package the configuration line with EventCounterCollector should be added. Nevertheless, I only see a line concerning PerfCollectors.

Check my configuration file:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
  <TelemetryModules>
    <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
      <!--
      Use the following syntax here to collect additional performance counters:

      <Counters>
        <Add PerformanceCounter="\Process(??APP_WIN32_PROC??)\Handle Count" ReportAs="Process handle count" />
        ...
      </Counters>

      PerformanceCounter must be either \CategoryName(InstanceName)\CounterName or \CategoryName\CounterName

      NOTE: performance counters configuration will be lost upon NuGet upgrade.

      The following placeholders are supported as InstanceName:
        ??APP_WIN32_PROC?? - instance name of the application process  for Win32 counters.
        ??APP_W3SVC_PROC?? - instance name of the application IIS worker process for IIS/ASP.NET counters.
        ??APP_CLR_PROC?? - instance name of the application CLR process for .NET counters.
      -->
    </Add>
    <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryModule, Microsoft.AI.PerfCounterCollector" />
  </TelemetryModules>
  <TelemetrySinks>
    <Add Name="default">
      <TelemetryProcessors>
        <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryProcessor, Microsoft.AI.PerfCounterCollector" />
      </TelemetryProcessors>
    </Add>
  </TelemetrySinks>
</ApplicationInsights>

Application_Start code:

void Application_Start(object sender, EventArgs e)
        {
            // Code that runs on application startup
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            RouteTable.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = System.Web.Http.RouteParameter.Optional }
            );

            Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey = INSTRUMENTATION_KEY;
            Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.ConnectionString = CONNECTION_STRING;

            System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener("c:\\temp\\test.txt"));
            System.Diagnostics.Debug.AutoFlush = true;
            System.Diagnostics.Debug.WriteLine(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode);
            System.Diagnostics.Debug.WriteLine(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryChannel.EndpointAddress);
            System.Diagnostics.Debug.WriteLine(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.InstrumentationKey);
            ////Utilities.AppInsightsTelemetry.EventCounterCollector("Clicked button", "Clicked button Count");
            Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionModule
                            collector = new Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionModule();
            collector.Counters.Add(new Microsoft.ApplicationInsights.Extensibility.EventCounterCollector.EventCounterCollectionRequest("Clicked button", "Clicked button count"));
            collector.Initialize(Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active);
        }

btn_submit_Click code:

protected void btnSubmit_Click(object sender, EventArgs e)
        {            
            Utilities.AppInsightsTelemetry.TrackEvent("Clicked button", new Dictionary<string, string> { { "BtnType", "Contact" } },
                null);
        }

See that the tracked event has the name of "Clicked button", as defined in the collector. The counter has the name of "Clicked button count". No customMetric appears with that name, despite "Clicked button" appearing in customEvents.

Please reopen the issue if possible, @cijothomas .

esyker commented 3 years ago

@cijothomas You can try it yourself. Clone the project, change the instrumentation key for one of yours in Application_Start Global.asax and see with your eyes. The go to Contact page, fill the form and press submit button. You will get a "Clicked button" event but no counter in customMetrics.

https://dev.azure.com/linkestagiodiogomoura/SampleWebAppTransfer

esyker commented 3 years ago

Guess there is a way to configure EventCounterCollectors as for PerformanceCounterCollectors through the .config file. There is no documentation for that however, so I am going to replicate the syntax from here: https://docs.microsoft.com/en-us/azure/azure-monitor/app/performance-counters

<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
      <Counters>
        <Add PerformanceCounter="\Objects\Processes"/>
        <Add PerformanceCounter="\Sales(photo)\# Items Sold" ReportAs="Photo sales"/>
      </Counters>
    </Add>

You might think I am a noob but, in fact, it does not work with the code you provided ;)

esyker commented 3 years ago

Sorry to inportunate you, but maybe I made a mistake. Now that I setup the PerfCountCollectors ( which are not working for some random reason), I realized thay probably the EvenCountCollector isn't a collector for customEvents generated for log analytics, but a collector for events generated using EventCounter class, isn't it? Thanks for your help, Diogo