Skip to content

Commit

Permalink
add elections counter metric
Browse files Browse the repository at this point in the history
  • Loading branch information
dhingrak committed Mar 13, 2024
1 parent f64d8b9 commit 870ef6d
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/EventStore.ClusterNode/metricsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"Scavenge": true
},

"ElectionsCount": true,

"Checkpoints": {
"Writer": true,
"Index": true,
Expand Down
4 changes: 3 additions & 1 deletion src/EventStore.Common/Configuration/MetricsConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ public class LabelMappingCase {
public Dictionary<EventTracker, bool> Events { get; set; } = new();

public Dictionary<Cache, bool> CacheHitsMisses { get; set; } = new();


public bool ElectionsCount { get; set; } = false;

public bool CacheResources { get; set; } = false;

// must be 0, 1, 5, 10 or a multiple of 15
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Net;
using System.Runtime.CompilerServices;
using EventStore.Core.Data;
using EventStore.Core.Messages;
using EventStore.Core.Metrics;
using EventStore.Core.Tests;
using Xunit;

namespace EventStore.Core.XUnit.Tests.Metrics;

public class ElectionsCounterTrackerTests : IDisposable {
private readonly Disposables _disposables = new();
private readonly ElectionMessage.ElectionsDone _electionsDoneMessage;

public ElectionsCounterTrackerTests() {
var endPoint = new DnsEndPoint("127.0.0.1", 1113);
var memberInfo = Cluster.MemberInfo.Initial(Guid.Empty, DateTime.UtcNow,
VNodeState.Unknown, true,
endPoint, endPoint, endPoint, endPoint, endPoint,
null, 0, 0, 0, false);
_electionsDoneMessage = new ElectionMessage.ElectionsDone(1, 1, memberInfo);
}

public void Dispose() {
_disposables?.Dispose();
}

private (ElectionsCounterTracker, TestMeterListener<long>) GenSut(
[CallerMemberName]string callerName = "") {

var meter = new Meter($"{typeof(ElectionsCounterTrackerTests)}--{callerName}").DisposeWith(_disposables);
var listener = new TestMeterListener<long>(meter).DisposeWith(_disposables);
var metric = new CounterMetric(meter, "test-metric", unit:"");
var sut = new ElectionsCounterTracker(new CounterSubMetric(metric, []));

return (sut, listener);
}

[Fact]
public void test_election_count_for_one_election() {
var (sut, listener) = GenSut();
sut.Handle(_electionsDoneMessage);

AssertMeasurements(listener, AssertMeasurement(1));
}

[Fact]
public void test_election_count_for_five_elections() {
var (sut, listener) = GenSut();
sut.Handle(_electionsDoneMessage);
sut.Handle(_electionsDoneMessage);
sut.Handle(_electionsDoneMessage);
sut.Handle(_electionsDoneMessage);
sut.Handle(_electionsDoneMessage);

AssertMeasurements(listener, AssertMeasurement(5));
}

static Action<TestMeterListener<long>.TestMeasurement> AssertMeasurement(
int expectedValue) =>
actualMeasurement => {
Assert.Equal(expectedValue, actualMeasurement.Value);
};

static void AssertMeasurements(
TestMeterListener<long> listener,
params Action<TestMeterListener<long>.TestMeasurement>[] actions) {

listener.Observe();
Assert.Collection(listener.RetrieveMeasurements("test-metric"), actions);
}
}
4 changes: 4 additions & 0 deletions src/EventStore.Core/ClusterVNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
using EventStore.Core.Caching;
using EventStore.Core.Certificates;
using EventStore.Core.Cluster;
using EventStore.Core.Metrics;
using EventStore.Core.Services.Storage.InMemory;
using EventStore.Core.Services.PeriodicLogs;
using EventStore.Core.Synchronization;
Expand Down Expand Up @@ -1465,6 +1466,9 @@ public class ClusterVNode<TStreamId> :
GossipAdvertiseInfo.AdvertiseTcpPortToClientAs,
options.Cluster.NodePriority, options.Cluster.ReadOnlyReplica, VersionInfo.Version);

// ELECTIONS TRACKER
_mainBus.Subscribe<ElectionMessage.ElectionsDone>(trackers.ElectionCounterTracker);

// TELEMETRY
var telemetryService = new TelemetryService(
Db.Manager,
Expand Down
8 changes: 6 additions & 2 deletions src/EventStore.Core/Metrics/CounterMetric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ public class CounterMetric {
private readonly object _lock = new();

public CounterMetric(Meter meter, string name, string unit) {
meter.CreateObservableCounter(name + "-" + unit, Observe);
if (!string.IsNullOrWhiteSpace(unit)) {
name = name + "-" + unit;
}

meter.CreateObservableCounter(name, Observe);
}

public void Add(CounterSubMetric subMetric) {
lock (_lock) {
_subMetrics.Add(subMetric);
Expand Down
25 changes: 25 additions & 0 deletions src/EventStore.Core/Metrics/ElectionsCounterTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using EventStore.Core.Bus;
using EventStore.Core.Messages;


namespace EventStore.Core.Metrics;

public interface IElectionCounterTracker : IHandle<ElectionMessage.ElectionsDone> {
}

public class ElectionsCounterTracker : IElectionCounterTracker {
private readonly CounterSubMetric _electionsCounter;

public ElectionsCounterTracker(CounterSubMetric electionsCounter) {
_electionsCounter = electionsCounter;
}

public void Handle(ElectionMessage.ElectionsDone message) {
_electionsCounter.Add(1);
}

public class NoOp : IElectionCounterTracker {
public void Handle(ElectionMessage.ElectionsDone message) {
}
}
}
7 changes: 7 additions & 0 deletions src/EventStore.Core/MetricsBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class Trackers {
public IDurationMaxTracker WriterFlushDurationTracker { get; set; } = new DurationMaxTracker.NoOp();
public ICacheHitsMissesTracker CacheHitsMissesTracker { get; set; } = new CacheHitsMissesTracker.NoOp();
public ICacheResourcesTracker CacheResourcesTracker { get; set; } = new CacheResourcesTracker.NoOp();
public IElectionCounterTracker ElectionCounterTracker { get; set; } = new ElectionsCounterTracker.NoOp();
}

public class GrpcTrackers {
Expand Down Expand Up @@ -84,6 +85,7 @@ public static class MetricsBootstrapper {
var queueBusyMetric = new AverageMetric(coreMeter, "eventstore-queue-busy", "seconds", label => new("queue", label));
var byteMetric = new CounterMetric(coreMeter, "eventstore-io", unit: "bytes");
var eventMetric = new CounterMetric(coreMeter, "eventstore-io", unit: "events");
var electionsCounterMetric = new CounterMetric(coreMeter, "eventstore-elections-count", unit:"");

// incoming grpc calls
var enabledCalls = conf.IncomingGrpcCalls.Where(kvp => kvp.Value).Select(kvp => kvp.Key).ToArray();
Expand Down Expand Up @@ -111,6 +113,11 @@ public static class MetricsBootstrapper {
trackers.CacheResourcesTracker = new CacheResourcesTracker(metrics);
}

// elections count
if (conf.ElectionsCount) {
trackers.ElectionCounterTracker = new ElectionsCounterTracker(new CounterSubMetric(electionsCounterMetric, []));
}

// events
if (conf.Events.TryGetValue(Conf.EventTracker.Read, out var readEnabled) && readEnabled) {
var readTag = new KeyValuePair<string, object>("activity", "read");
Expand Down

0 comments on commit 870ef6d

Please sign in to comment.