apm-agent-dotnet icon indicating copy to clipboard operation
apm-agent-dotnet copied to clipboard

Manually send custom metrics (Agent API or integration with a Metrics Library)

Open gregkalapos opened this issue 5 years ago • 23 comments

We should offer users the ability to manually send metrics.

I think there would be 2 approaches:

  1. step: decide which approach to take
  2. step: implement.

gregkalapos avatar Jun 26 '19 15:06 gregkalapos

For my project having custom metrics is really important, and it is also available in other APM products on the market. It would be really awesome to have this!

From a consumers point of view, in a ASP .NET Core application, I would expect to be able to register a source of IMetricsProvider (it could be a list, a factory, etc) with my DI container by using a simple extension method on IServiceCollection for example services.AddElasticApmMetrics(IReadOnlyCollection<IMetricsProvider> metricProviders) (That collection/factory could later be injected into a new MetricsCollector class ctor)

Without custom metrics key stakeholders in our company will most likely choose another product.

Thanks a lot for the great effort you're doing with APM agent for dotnet!

oleh-zheleznyak avatar Jun 27 '19 07:06 oleh-zheleznyak

Could this be done using Agent.PayloadSender.QueueMetrics(IMetricSet metrics);

andrewharry avatar Jun 30 '19 22:06 andrewharry

Otherwise the IMetricsCollector.MetricsProviders needs to be exposed via a public API

andrewharry avatar Jun 30 '19 22:06 andrewharry

https://github.com/workbetter-com-au/apm-agent-dotnet-metrics Attempted a quick manual 'send metric'. Couldn't get it to work. No errors were logged. I will pull into the project the actual Elastic.Apm to troubleshoot why it didn't work

andrewharry avatar Jul 01 '19 22:07 andrewharry

Couldn't get it to work. No errors were logged.

Let me try to help.

The agent currently sends data to the APM Server when one of these 2 things happen:

  • A transaction ends (Transaction.End() is called either manually or by auto instrumentation)
  • There are at least 20 events recorded (1 event is e.g. a span, or a metricset with 1 timespan)

In your sample you only record metrics, so probably that's the issue - you need at least 20 of those to make the agent send it to the server. You can either force it by also capturing the transaction (just turn on the agent normally with UseElasticApm) - or simply change the code temporarily - or send at least 20 metrics to fill the queue.

Probably we should add a config setting for this... that'd be a nicer way of doing this.

Also I'd like to point out that in PayloadSenderV2 we already do the big part of the work (serialization and sending to the server) on a separate thread, the payloadSender.QueueMetrics(metrics) already returns very fast. I'm not sure your BatchWorker is needed.

Hope this helps.

gregkalapos avatar Jul 02 '19 10:07 gregkalapos

I think I have identified the issue https://github.com/elastic/apm-agent-dotnet/blob/master/src/Elastic.Apm/Report/PayloadSenderV2.cs#L151

The payloadsender specifically checks if the metric is of type Metrics.MetricSet where as I don't have access to the metricset class (Internal)

If this was changed to check for the Interface instead - IMetricSet - Maybe it would work then?

andrewharry avatar Jul 02 '19 11:07 andrewharry

I wasn't too familiar with the internal workings of the payloadsender. I was reproducing the MetricCollector behaviour with the BatchWorker pattern. In general, I'm eager for the internal classes to be opened up a lot more :) - But I get the logic of not exposing potentially breaking changes early in the process

andrewharry avatar Jul 02 '19 12:07 andrewharry

If this was changed to check for the Interface instead - IMetricSet - Maybe it would work then?

We should rather make MetricSet public - at least that was my plan, its just a plain C# type to transfer data, I think it's a good candidate to use it on the API surface.

gregkalapos avatar Jul 02 '19 12:07 gregkalapos

That would be ideal. I also hit issues with the TraceParent being internal. And the internal constructor on the DistributedTracingData object

andrewharry avatar Jul 02 '19 12:07 andrewharry

I also hit issues with the TraceParent being internal. And the internal constructor on the DistributedTracingData object

What usecase was that?

gregkalapos avatar Jul 02 '19 12:07 gregkalapos

I also hit issues with the TraceParent being internal. And the internal constructor on the DistributedTracingData object

What usecase was that?

I have put together a project in .NET Framework showing how I have integrated with the Elastic.Apm dotnet client https://github.com/workbetter-com-au/apm-agent-dotnet-framework

andrewharry avatar Jul 03 '19 01:07 andrewharry

@andrewharry Thank you - I will definitely take a look at your implementation of the integrations and consider if and how to make them available with the agent out of the box.

SergeyKleyman avatar Jul 03 '19 06:07 SergeyKleyman

I'm closing #708. As suggested this seems a better place for the matter. Just for the record, my suggestion was to allow registration of more (and custom) IMetricsProvider. The OTB functionality is great, but there is no need in hitting you when somebody wants this or that, counter, or even a custom one; I found they're pretty easy to implement if they can be added to the queue...

For me having a pluggable or custom PayloadSenderV2 would be interesting too. I would like to route some of the events to some other system or even add new ones (such as log entries) to the switch in ProcessQueue. (I know that's out of scope for you, as it is paired with the APM service ingestion, but having it open would not harm). Well, by now I have a fork of the agent I can live with, but asking is free :)))

Thank you

marcoregueira avatar Jan 31 '20 11:01 marcoregueira

I did a PR to have access to MetricSet and looking forward to write a Reporter for Metrics.NET.

In the same time I thought maybe will be a good idea to create a separate package for Metrics, Elastic.Apm.Metrics and maybe also for Server communication Elastic.Apm.Reporter (IPayloadSender). The classes are already splitted on folder level but will be nice to have separate nuget packages for 3rd party integrators libraries.

glucaci avatar Mar 22 '21 08:03 glucaci

Any update on this? We'd be interested in contributing App.Metrics support for Elastic.Apm but it looks like this isn't feasible today.

Aaronontheweb avatar May 19 '21 17:05 Aaronontheweb

@gregkalapos - any update on this issue? I am really looking forward to this feature as I would like to send multiple custom metrics using APM.

kbalys avatar Jul 21 '21 06:07 kbalys

Since kibana apm seems to have support for opentelemetry protocol I think you can try opentelemetry dotnet client which supports metrics in beta release and setup otpl protocol exporter to kibana apm.

Matiszak avatar Nov 29 '21 13:11 Matiszak

It would be nice to have support for https://docs.microsoft.com/en-us/dotnet/core/diagnostics/event-counters

fuzolan avatar Mar 16 '22 10:03 fuzolan

Is anyone working on this feature?

BenWolstencroft avatar Aug 30 '22 10:08 BenWolstencroft

Is there a demo project that can be used to send a custom metric to the APM Server?

smarandav avatar Oct 23 '22 13:10 smarandav

@gregkalapos are there plans in the nearest future to implement this feature?

kbalys avatar Nov 29 '22 12:11 kbalys

@gregkalapos, could you share updates or plans regarding this feature?

kbalys avatar Oct 26 '23 09:10 kbalys

I'm also curious if you could get this working by using .net telemetry exporter https://opentelemetry.io/docs/instrumentation/net/exporters/

to setup exporting to OpenTelemetry intake API: https://www.elastic.co/guide/en/apm/guide/current/api-otlp.html

Anybody tested this ?

johanknirk avatar Nov 12 '23 19:11 johanknirk