@@ -10,22 +10,29 @@ namespace Temporalio.Bridge
10
10
internal class CustomMetricMeter
11
11
{
12
12
private readonly Temporalio . Runtime . ICustomMetricMeter meter ;
13
+ private readonly Temporalio . Runtime . CustomMetricMeterOptions options ;
13
14
private readonly List < GCHandle > handles = new ( ) ;
14
15
15
16
/// <summary>
16
17
/// Initializes a new instance of the <see cref="CustomMetricMeter" /> class.
17
18
/// </summary>
18
19
/// <param name="meter">Meter implementation.</param>
19
- public unsafe CustomMetricMeter ( Temporalio . Runtime . ICustomMetricMeter meter )
20
+ /// <param name="options">Options.</param>
21
+ public unsafe CustomMetricMeter (
22
+ Temporalio . Runtime . ICustomMetricMeter meter ,
23
+ Temporalio . Runtime . CustomMetricMeterOptions options )
20
24
{
21
25
this . meter = meter ;
26
+ this . options = options ;
22
27
23
28
// Create metric meter struct
24
29
var interopMeter = new Interop . CustomMetricMeter ( )
25
30
{
26
- metric_integer_new = FunctionPointer < Interop . CustomMetricMeterMetricIntegerNewCallback > ( CreateMetric ) ,
27
- metric_integer_free = FunctionPointer < Interop . CustomMetricMeterMetricIntegerFreeCallback > ( FreeMetric ) ,
28
- metric_integer_update = FunctionPointer < Interop . CustomMetricMeterMetricIntegerUpdateCallback > ( UpdateMetric ) ,
31
+ metric_new = FunctionPointer < Interop . CustomMetricMeterMetricNewCallback > ( CreateMetric ) ,
32
+ metric_free = FunctionPointer < Interop . CustomMetricMeterMetricFreeCallback > ( FreeMetric ) ,
33
+ metric_record_integer = FunctionPointer < Interop . CustomMetricMeterMetricRecordIntegerCallback > ( RecordMetricInteger ) ,
34
+ metric_record_float = FunctionPointer < Interop . CustomMetricMeterMetricRecordFloatCallback > ( RecordMetricFloat ) ,
35
+ metric_record_duration = FunctionPointer < Interop . CustomMetricMeterMetricRecordDurationCallback > ( RecordMetricDuration ) ,
29
36
attributes_new = FunctionPointer < Interop . CustomMetricMeterAttributesNewCallback > ( CreateAttributes ) ,
30
37
attributes_free = FunctionPointer < Interop . CustomMetricMeterAttributesFreeCallback > ( FreeAttributes ) ,
31
38
meter_free = FunctionPointer < Interop . CustomMetricMeterMeterFreeCallback > ( Free ) ,
@@ -58,38 +65,69 @@ private static unsafe string GetString(byte* bytes, UIntPtr size) =>
58
65
Interop . ByteArrayRef name ,
59
66
Interop . ByteArrayRef description ,
60
67
Interop . ByteArrayRef unit ,
61
- Interop . MetricIntegerKind kind )
68
+ Interop . MetricKind kind )
62
69
{
63
- Temporalio . Runtime . ICustomMetric < long > metric ;
70
+ GCHandle metric ;
64
71
var nameStr = GetString ( name ) ;
65
72
var unitStr = GetStringOrNull ( unit ) ;
66
73
var descStr = GetStringOrNull ( description ) ;
67
74
switch ( kind )
68
75
{
69
- case Interop . MetricIntegerKind . Counter :
70
- metric = meter . CreateCounter < long > ( nameStr , unitStr , descStr ) ;
76
+ case Interop . MetricKind . CounterInteger :
77
+ metric = GCHandle . Alloc ( meter . CreateCounter < long > ( nameStr , unitStr , descStr ) ) ;
71
78
break ;
72
- case Interop . MetricIntegerKind . Histogram :
73
- metric = meter . CreateHistogram < long > ( nameStr , unitStr , descStr ) ;
79
+ case Interop . MetricKind . HistogramInteger :
80
+ metric = GCHandle . Alloc ( meter . CreateHistogram < long > ( nameStr , unitStr , descStr ) ) ;
74
81
break ;
75
- case Interop . MetricIntegerKind . Gauge :
76
- metric = meter . CreateGauge < long > ( nameStr , unitStr , descStr ) ;
82
+ case Interop . MetricKind . HistogramFloat :
83
+ metric = GCHandle . Alloc ( meter . CreateHistogram < double > ( nameStr , unitStr , descStr ) ) ;
84
+ break ;
85
+ case Interop . MetricKind . HistogramDuration :
86
+ switch ( options . HistogramDurationFormat )
87
+ {
88
+ case Temporalio . Runtime . CustomMetricMeterOptions . DurationFormat . IntegerMilliseconds :
89
+ // Change unit from "duration" to "ms" since we're converting to ms
90
+ if ( unitStr == "duration" )
91
+ {
92
+ unitStr = "ms" ;
93
+ }
94
+ metric = GCHandle . Alloc ( meter . CreateHistogram < long > ( nameStr , unitStr , descStr ) ) ;
95
+ break ;
96
+ case Temporalio . Runtime . CustomMetricMeterOptions . DurationFormat . FloatSeconds :
97
+ // Change unit from "duration" to "s" since we're converting to s
98
+ if ( unitStr == "duration" )
99
+ {
100
+ unitStr = "s" ;
101
+ }
102
+ metric = GCHandle . Alloc ( meter . CreateHistogram < double > ( nameStr , unitStr , descStr ) ) ;
103
+ break ;
104
+ case Temporalio . Runtime . CustomMetricMeterOptions . DurationFormat . TimeSpan :
105
+ metric = GCHandle . Alloc ( meter . CreateHistogram < TimeSpan > ( nameStr , unitStr , descStr ) ) ;
106
+ break ;
107
+ default :
108
+ throw new InvalidOperationException ( $ "Unknown format: { options . HistogramDurationFormat } ") ;
109
+ }
110
+ break ;
111
+ case Interop . MetricKind . GaugeInteger :
112
+ metric = GCHandle . Alloc ( meter . CreateGauge < long > ( nameStr , unitStr , descStr ) ) ;
113
+ break ;
114
+ case Interop . MetricKind . GaugeFloat :
115
+ metric = GCHandle . Alloc ( meter . CreateGauge < double > ( nameStr , unitStr , descStr ) ) ;
77
116
break ;
78
117
default :
79
118
throw new InvalidOperationException ( $ "Unknown kind: { kind } ") ;
80
119
}
81
120
// Return pointer
82
- return GCHandle . ToIntPtr ( GCHandle . Alloc ( metric ) ) . ToPointer ( ) ;
121
+ return GCHandle . ToIntPtr ( metric ) . ToPointer ( ) ;
83
122
}
84
123
85
124
private unsafe void FreeMetric ( void * metric ) => GCHandle . FromIntPtr ( new ( metric ) ) . Free ( ) ;
86
125
87
- private unsafe void UpdateMetric ( void * metric , ulong value , void * attributes )
126
+ private unsafe void RecordMetricInteger ( void * metric , ulong value , void * attributes )
88
127
{
89
128
var metricObject = ( Temporalio . Runtime . ICustomMetric < long > ) GCHandle . FromIntPtr ( new ( metric ) ) . Target ! ;
90
129
var tags = GCHandle . FromIntPtr ( new ( attributes ) ) . Target ! ;
91
- // We trust that value will never be over Int64.MaxValue
92
- var metricValue = unchecked ( ( long ) value ) ;
130
+ var metricValue = value > long . MaxValue ? long . MaxValue : unchecked ( ( long ) value ) ;
93
131
switch ( metricObject )
94
132
{
95
133
case Temporalio . Runtime . ICustomMetricCounter < long > counter :
@@ -104,6 +142,51 @@ private unsafe void UpdateMetric(void* metric, ulong value, void* attributes)
104
142
}
105
143
}
106
144
145
+ private unsafe void RecordMetricFloat ( void * metric , double value , void * attributes )
146
+ {
147
+ var metricObject = ( Temporalio . Runtime . ICustomMetric < double > ) GCHandle . FromIntPtr ( new ( metric ) ) . Target ! ;
148
+ var tags = GCHandle . FromIntPtr ( new ( attributes ) ) . Target ! ;
149
+ switch ( metricObject )
150
+ {
151
+ case Temporalio . Runtime . ICustomMetricHistogram < double > histogram :
152
+ histogram . Record ( value , tags ) ;
153
+ break ;
154
+ case Temporalio . Runtime . ICustomMetricGauge < double > gauge :
155
+ gauge . Set ( value , tags ) ;
156
+ break ;
157
+ }
158
+ }
159
+
160
+ private unsafe void RecordMetricDuration ( void * metric , ulong valueMs , void * attributes )
161
+ {
162
+ var metricObject = GCHandle . FromIntPtr ( new ( metric ) ) . Target ! ;
163
+ var tags = GCHandle . FromIntPtr ( new ( attributes ) ) . Target ! ;
164
+ var metricValue = valueMs > long . MaxValue ? long . MaxValue : unchecked ( ( long ) valueMs ) ;
165
+ // We don't want to throw out of here, so we just fall through if anything doesn't match
166
+ // expected types (which should never happen since we controlled creation)
167
+ switch ( options . HistogramDurationFormat )
168
+ {
169
+ case Temporalio . Runtime . CustomMetricMeterOptions . DurationFormat . IntegerMilliseconds :
170
+ if ( metricObject is Temporalio . Runtime . ICustomMetricHistogram < long > histLong )
171
+ {
172
+ histLong . Record ( metricValue , tags ) ;
173
+ }
174
+ break ;
175
+ case Temporalio . Runtime . CustomMetricMeterOptions . DurationFormat . FloatSeconds :
176
+ if ( metricObject is Temporalio . Runtime . ICustomMetricHistogram < double > histDouble )
177
+ {
178
+ histDouble . Record ( metricValue / 1000.0 , tags ) ;
179
+ }
180
+ break ;
181
+ case Temporalio . Runtime . CustomMetricMeterOptions . DurationFormat . TimeSpan :
182
+ if ( metricObject is Temporalio . Runtime . ICustomMetricHistogram < TimeSpan > histTimeSpan )
183
+ {
184
+ histTimeSpan . Record ( TimeSpan . FromMilliseconds ( metricValue ) , tags ) ;
185
+ }
186
+ break ;
187
+ }
188
+ }
189
+
107
190
private unsafe void * CreateAttributes (
108
191
void * appendFrom , Interop . CustomMetricAttribute * attributes , UIntPtr attributesSize )
109
192
{
0 commit comments