Skip to content

Commit c306c91

Browse files
committed
ThreadSafe
1 parent 9d46fc5 commit c306c91

File tree

9 files changed

+170
-139
lines changed

9 files changed

+170
-139
lines changed

Prometheus.Client/Advanced/Collector.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ namespace Prometheus.Client.Advanced
2222

2323
protected abstract MetricType Type { get; }
2424

25+
public string Name { get; }
26+
27+
public string[] LabelNames { get; }
28+
29+
protected T Unlabelled => _unlabelledLazy.Value;
30+
2531
public T Labels(params string[] labelValues)
2632
{
2733
var key = new LabelValues(LabelNames, labelValues);
@@ -38,8 +44,6 @@ private T GetOrAddLabelled(LabelValues key)
3844
});
3945
}
4046

41-
protected T Unlabelled => _unlabelledLazy.Value;
42-
4347
protected Collector(string name, string help, string[] labelNames)
4448
{
4549
Name = name;
@@ -66,10 +70,6 @@ protected Collector(string name, string help, string[] labelNames)
6670
_unlabelledLazy = new Lazy<T>(() => GetOrAddLabelled(EmptyLabelValues));
6771
}
6872

69-
public string Name { get; }
70-
71-
public string[] LabelNames { get; private set; }
72-
7373
public MetricFamily Collect()
7474
{
7575
var result = new MetricFamily()

Prometheus.Client/Advanced/DotNetStatsCollector.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ public class DotNetStatsCollector : IOnDemandCollector
1717
private Gauge _workingSet;
1818
private Gauge _privateMemorySize;
1919
private Counter _cpuTotal;
20-
2120
private Gauge _startTime;
22-
2321
private Gauge _numThreads;
22+
private Gauge _pid;
2423

2524
public DotNetStatsCollector()
2625
{
@@ -44,21 +43,24 @@ public void RegisterMetrics()
4443
_virtualMemorySize = Metrics.CreateGauge("process_windows_virtual_bytes", "Process virtual memory size");
4544
_workingSet = Metrics.CreateGauge("process_windows_working_set", "Process working set");
4645
_privateMemorySize = Metrics.CreateGauge("process_windows_private_bytes", "Process private memory size");
47-
// _openHandles = Metrics.CreateGauge("process_windows_open_handles", "Number of open handles");
4846
_numThreads = Metrics.CreateGauge("process_windows_num_threads", "Total number of threads");
47+
_pid = Metrics.CreateGauge("process_windows_processid", "Process ID");
4948

5049
// .net specific metrics
5150
_totalMemory = Metrics.CreateGauge("dotnet_totalmemory", "Total known allocated memory");
5251
_perfErrors = Metrics.CreateCounter("dotnet_collection_errors_total", "Total number of errors that occured during collections");
5352

5453
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
5554
_startTime.Set((_process.StartTime.ToUniversalTime() - epoch).TotalSeconds);
55+
_pid.Set(_process.Id);
5656
}
5757

5858
public void UpdateMetrics()
5959
{
6060
try
6161
{
62+
_process.Refresh();
63+
6264
for (var gen = 0; gen <= GC.MaxGeneration; gen++)
6365
{
6466
var collectionCount = _collectionCounts[gen];
@@ -70,7 +72,6 @@ public void UpdateMetrics()
7072
_workingSet.Set(_process.WorkingSet64);
7173
_privateMemorySize.Set(_process.PrivateMemorySize64);
7274
_cpuTotal.Inc(_process.TotalProcessorTime.TotalSeconds - _cpuTotal.Value);
73-
7475
_numThreads.Set(_process.Threads.Count);
7576
}
7677
catch (Exception)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Threading;
3+
4+
namespace Prometheus.Client.Advanced
5+
{
6+
public struct ThreadSafeDouble
7+
{
8+
private long _value;
9+
10+
public ThreadSafeDouble(double value)
11+
{
12+
_value = BitConverter.DoubleToInt64Bits(value);
13+
}
14+
15+
public double Value
16+
{
17+
get
18+
{
19+
return BitConverter.Int64BitsToDouble(Interlocked.Read(ref _value));
20+
}
21+
set
22+
{
23+
Interlocked.Exchange(ref _value, BitConverter.DoubleToInt64Bits(value));
24+
}
25+
}
26+
27+
public void Add(double increment)
28+
{
29+
while (true)
30+
{
31+
long initialValue = _value;
32+
double computedValue = BitConverter.Int64BitsToDouble(initialValue) + increment;
33+
34+
if (initialValue == Interlocked.CompareExchange(ref _value, BitConverter.DoubleToInt64Bits(computedValue), initialValue))
35+
return;
36+
}
37+
}
38+
39+
public override string ToString()
40+
{
41+
return Value.ToString();
42+
}
43+
44+
public override bool Equals(object obj)
45+
{
46+
if (obj is ThreadSafeDouble)
47+
return Value.Equals(((ThreadSafeDouble)obj).Value);
48+
49+
return Value.Equals(obj);
50+
}
51+
52+
public override int GetHashCode()
53+
{
54+
return Value.GetHashCode();
55+
}
56+
}
57+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.Threading;
2+
3+
namespace Prometheus.Client.Advanced
4+
{
5+
public struct ThreadSafeLong
6+
{
7+
private long _value;
8+
9+
public ThreadSafeLong(long value)
10+
{
11+
_value = value;
12+
}
13+
14+
public long Value
15+
{
16+
get
17+
{
18+
return Interlocked.Read(ref _value);
19+
}
20+
set
21+
{
22+
Interlocked.Exchange(ref _value, value);
23+
}
24+
}
25+
26+
public void Add(long increment)
27+
{
28+
while (true)
29+
{
30+
long initialValue = _value;
31+
long computedValue = initialValue + increment;
32+
33+
if (initialValue == Interlocked.CompareExchange(ref _value, computedValue, initialValue))
34+
return;
35+
}
36+
}
37+
38+
public override string ToString()
39+
{
40+
return Value.ToString();
41+
}
42+
43+
public override bool Equals(object obj)
44+
{
45+
if (obj is ThreadSafeLong)
46+
return Value.Equals(((ThreadSafeLong)obj).Value);
47+
48+
return Value.Equals(obj);
49+
}
50+
51+
public override int GetHashCode()
52+
{
53+
return Value.GetHashCode();
54+
}
55+
}
56+
}

Prometheus.Client/Counter.cs

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,40 @@ namespace Prometheus.Client
66
{
77
public interface ICounter
88
{
9-
void Inc(double increment = 1);
9+
void Inc(double increment = 1.0D);
1010
double Value { get; }
1111
}
1212

1313
public class Counter : Collector<Counter.Child>, ICounter
1414
{
15-
1615
internal Counter(string name, string help, string[] labelNames)
1716
: base(name, help, labelNames)
1817
{
1918
}
2019

21-
public void Inc(double increment = 1)
20+
public void Inc(double increment = 1.0D)
2221
{
2322
Unlabelled.Inc(increment);
2423
}
2524

26-
public class Child : Client.Advanced.Child, ICounter
25+
public class Child : Advanced.Child, ICounter
2726
{
28-
private double _value;
29-
private readonly object _lock = new object();
27+
private ThreadSafeDouble _value;
3028

3129
protected override void Populate(Metric metric)
3230
{
33-
metric.counter = new Prometheus.Advanced.DataContracts.Counter();
34-
metric.counter.value = Value;
31+
metric.counter = new Prometheus.Advanced.DataContracts.Counter {value = Value};
3532
}
3633

37-
public void Inc(double increment = 1)
34+
public void Inc(double increment = 1.0D)
3835
{
39-
if (increment < 0)
40-
{
36+
if (increment < 0.0D)
4137
throw new InvalidOperationException("Counter cannot go down");
42-
}
4338

44-
lock (_lock)
45-
{
46-
_value += increment;
47-
}
39+
_value.Add(increment);
4840
}
4941

50-
public double Value
51-
{
52-
get
53-
{
54-
lock (_lock)
55-
{
56-
return _value;
57-
}
58-
}
59-
}
42+
public double Value => _value.Value;
6043
}
6144

6245
public double Value => Unlabelled.Value;

Prometheus.Client/Gauge.cs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ namespace Prometheus.Client
77
public interface IGauge
88
{
99
double Value { get; }
10-
void Inc(double increment = 1);
10+
void Inc(double increment = 1.0D);
1111
void Set(double val);
12-
void Dec(double decrement = 1);
12+
void Dec(double decrement = 1.0D);
1313
}
1414

1515
public class Gauge : Collector<Gauge.Child>, IGauge
@@ -21,7 +21,7 @@ internal Gauge(string name, string help, string[] labelNames)
2121

2222
protected override MetricType Type => MetricType.GAUGE;
2323

24-
public void Inc(double increment = 1)
24+
public void Inc(double increment = 1.0D)
2525
{
2626
Unlabelled.Inc(increment);
2727
}
@@ -32,7 +32,7 @@ public void Set(double val)
3232
}
3333

3434

35-
public void Dec(double decrement = 1)
35+
public void Dec(double decrement = 1.0D)
3636
{
3737
Unlabelled.Dec(decrement);
3838
}
@@ -42,46 +42,30 @@ public void Dec(double decrement = 1)
4242

4343
public class Child : Advanced.Child, IGauge
4444
{
45-
private readonly object _lock = new object();
46-
private double _value;
45+
private ThreadSafeDouble _value;
4746

48-
public void Inc(double increment = 1)
47+
public void Inc(double increment = 1.0D)
4948
{
50-
lock (_lock)
51-
{
52-
_value += increment;
53-
}
49+
_value.Add(increment);
5450
}
5551

5652
public void Set(double val)
5753
{
58-
Interlocked.Exchange(ref _value, val);
54+
_value.Value = val;
5955
}
6056

6157

62-
public void Dec(double decrement = 1)
58+
public void Dec(double decrement = 1.0D)
6359
{
6460
Inc(-decrement);
6561
}
6662

67-
public double Value
68-
{
69-
get
70-
{
71-
lock (_lock)
72-
{
73-
return _value;
74-
}
75-
}
76-
}
63+
public double Value => _value.Value;
64+
7765

7866
protected override void Populate(Metric metric)
7967
{
80-
metric.gauge = new Prometheus.Advanced.DataContracts.Gauge();
81-
lock (_lock)
82-
{
83-
metric.gauge.value = _value;
84-
}
68+
metric.gauge = new Prometheus.Advanced.DataContracts.Gauge { value = Value };
8569
}
8670
}
8771
}

0 commit comments

Comments
 (0)