public EventuousMetrics() { _meter = EventuousDiagnostics.GetMeter(MeterName); var eventStoreMetric = _meter.CreateHistogram <double>( Constants.Components.EventStore, "ms", "Event store operation duration, milliseconds" ); var appServiceMetric = _meter.CreateHistogram <double>( Constants.Components.AppService, "ms", "Application service operation duration, milliseconds" ); _listener = new ActivityListener { ShouldListenTo = x => x.Name == EventuousDiagnostics.InstrumentationName, Sample = (ref ActivityCreationOptions <ActivityContext> _) => ActivitySamplingResult.AllData, ActivityStopped = Record }; ActivitySource.AddActivityListener(_listener); void Record(Activity activity) { var dot = activity.OperationName.IndexOf('.'); if (dot == -1) { return; } var prefix = activity.OperationName[..dot];
/// <summary> /// Adds Eventuous activity source to OpenTelemetry trace collection /// </summary> /// <param name="builder"><seealso cref="TracerProviderBuilder"/> instance</param> /// <returns></returns> public static TracerProviderBuilder AddEventuousTracing(this TracerProviderBuilder builder) { // The DummyListener is added by default so the remote context is propagated regardless. // After adding the activity source to OpenTelemetry we don't need the dummy listener. EventuousDiagnostics.RemoveDummyListener(); return(Ensure.NotNull(builder) .AddSource(EventuousDiagnostics.InstrumentationName)); }
public ConnectorApplicationBuilder <TSourceConfig, TTargetConfig> AddOpenTelemetry( Action <TracerProviderBuilder, Action <Activity, string, object> >?configureTracing = null, Action <MeterProviderBuilder>?configureMetrics = null, Sampler?sampler = null, ExporterMappings <TracerProviderBuilder>?tracingExporters = null, ExporterMappings <MeterProviderBuilder>?metricsExporters = null ) { _otelAdded = true; if (!Config.Connector.Diagnostics.Enabled) { return(this); } EventuousDiagnostics.AddDefaultTag(ConnectorIdTag, Config.Connector.ConnectorId); if (Config.Connector.Diagnostics.Tracing is { Enabled : true })
public SubscriptionMetrics(IEnumerable <GetSubscriptionGap> measures) { _meter = EventuousDiagnostics.GetMeter(MeterName); var getGaps = measures.ToArray(); _checkpointMetrics = new Lazy <CheckpointCommitMetrics>(() => new CheckpointCommitMetrics()); IEnumerable <SubscriptionGap>?gaps = null; _meter.CreateObservableGauge( GapCountMetricName, () => TryObserving(GapCountMetricName, () => ObserveGapValues(getGaps)), "events", "Gap between the last processed event and the stream tail" ); _meter.CreateObservableGauge( GapTimeMetricName, () => TryObserving(GapTimeMetricName, ObserveTimeValues), "s", "Subscription time lag, seconds" ); _meter.CreateObservableGauge( CheckpointQueueLength, () => TryObserving(CheckpointQueueLength, _checkpointMetrics.Value.Record), "events", "Number of pending checkpoints" ); var histogram = _meter.CreateHistogram <double>(ProcessingRateName, "ms", "Processing duration, milliseconds"); var errorCount = _meter.CreateCounter <long>(ErrorCountName, "events", "Number of event processing failures"); _listener = new ActivityListener { ShouldListenTo = x => x.Name == EventuousDiagnostics.InstrumentationName, Sample = (ref ActivityCreationOptions <ActivityContext> _) => ActivitySamplingResult.AllData, ActivityStopped = x => ActivityStopped(histogram, errorCount, x) }; ActivitySource.AddActivityListener(_listener); IEnumerable <Measurement <double> > ObserveTimeValues() => gaps? .Select(x => Measure(x.TimeGap.TotalSeconds, x.SubscriptionId)) ?? Array.Empty <Measurement <double> >(); IEnumerable <Measurement <long> > ObserveGapValues(GetSubscriptionGap[] gapMeasure) => gapMeasure .Select(GetGap) .Where(x => x != SubscriptionGap.Invalid) .Select(x => Measure((long)x.PositionGap, x.SubscriptionId)); Measurement <T> Measure <T>(T value, string subscriptionId) where T : struct { if (_customTags.Length == 0) { return(new Measurement <T>(value, SubTag(subscriptionId))); } var tags = new List <KeyValuePair <string, object?> >(_customTags) { SubTag(subscriptionId) }; return(new Measurement <T>(value, tags)); } }