@@ -16,11 +16,14 @@ internal sealed class PrometheusCollectionManager
16
16
private readonly Dictionary < Metric , PrometheusMetric > metricsCache ;
17
17
private readonly HashSet < string > scopes ;
18
18
private int metricsCacheCount ;
19
- private byte [ ] buffer = new byte [ 85000 ] ; // encourage the object to live in LOH (large object heap)
19
+ private byte [ ] plainTextBuffer = new byte [ 85000 ] ; // encourage the object to live in LOH (large object heap)
20
+ private byte [ ] openMetricsBuffer = new byte [ 85000 ] ; // encourage the object to live in LOH (large object heap)
20
21
private int targetInfoBufferLength = - 1 ; // zero or positive when target_info has been written for the first time
22
+ private ArraySegment < byte > previousPlainTextDataView ;
23
+ private ArraySegment < byte > previousOpenMetricsDataView ;
21
24
private int globalLockState ;
22
- private ArraySegment < byte > previousDataView ;
23
- private DateTime ? previousDataViewGeneratedAtUtc ;
25
+ private DateTime ? previousPlainTextDataViewGeneratedAtUtc ;
26
+ private DateTime ? previousOpenMetricsDataViewGeneratedAtUtc ;
24
27
private int readerCount ;
25
28
private bool collectionRunning ;
26
29
private TaskCompletionSource < CollectionResponse > collectionTcs ;
@@ -44,16 +47,20 @@ public Task<CollectionResponse> EnterCollect(bool openMetricsRequested)
44
47
45
48
// If we are within {ScrapeResponseCacheDurationMilliseconds} of the
46
49
// last successful collect, return the previous view.
47
- if ( this . previousDataViewGeneratedAtUtc . HasValue
50
+ var previousDataViewGeneratedAtUtc = openMetricsRequested
51
+ ? this . previousOpenMetricsDataViewGeneratedAtUtc
52
+ : this . previousPlainTextDataViewGeneratedAtUtc ;
53
+
54
+ if ( previousDataViewGeneratedAtUtc . HasValue
48
55
&& this . scrapeResponseCacheDurationMilliseconds > 0
49
- && this . previousDataViewGeneratedAtUtc . Value . AddMilliseconds ( this . scrapeResponseCacheDurationMilliseconds ) >= DateTime . UtcNow )
56
+ && previousDataViewGeneratedAtUtc . Value . AddMilliseconds ( this . scrapeResponseCacheDurationMilliseconds ) >= DateTime . UtcNow )
50
57
{
51
58
Interlocked . Increment ( ref this . readerCount ) ;
52
59
this . ExitGlobalLock ( ) ;
53
60
#if NET6_0_OR_GREATER
54
- return new ValueTask < CollectionResponse > ( new CollectionResponse ( this . previousDataView , this . previousDataViewGeneratedAtUtc . Value , fromCache : true ) ) ;
61
+ return new ValueTask < CollectionResponse > ( new CollectionResponse ( this . previousOpenMetricsDataView , this . previousPlainTextDataView , previousDataViewGeneratedAtUtc . Value , fromCache : true ) ) ;
55
62
#else
56
- return Task . FromResult ( new CollectionResponse ( this . previousDataView , this . previousDataViewGeneratedAtUtc . Value , fromCache : true ) ) ;
63
+ return Task . FromResult ( new CollectionResponse ( this . previousOpenMetricsDataView , this . previousPlainTextDataView , previousDataViewGeneratedAtUtc . Value , fromCache : true ) ) ;
57
64
#endif
58
65
}
59
66
@@ -78,16 +85,37 @@ public Task<CollectionResponse> EnterCollect(bool openMetricsRequested)
78
85
79
86
// Start a collection on the current thread.
80
87
this . collectionRunning = true ;
81
- this . previousDataViewGeneratedAtUtc = null ;
88
+
89
+ if ( openMetricsRequested )
90
+ {
91
+ this . previousOpenMetricsDataViewGeneratedAtUtc = null ;
92
+ }
93
+ else
94
+ {
95
+ this . previousPlainTextDataViewGeneratedAtUtc = null ;
96
+ }
97
+
82
98
Interlocked . Increment ( ref this . readerCount ) ;
83
99
this . ExitGlobalLock ( ) ;
84
100
85
101
CollectionResponse response ;
86
102
var result = this . ExecuteCollect ( openMetricsRequested ) ;
87
103
if ( result )
88
104
{
89
- this . previousDataViewGeneratedAtUtc = DateTime . UtcNow ;
90
- response = new CollectionResponse ( this . previousDataView , this . previousDataViewGeneratedAtUtc . Value , fromCache : false ) ;
105
+ if ( openMetricsRequested )
106
+ {
107
+ this . previousOpenMetricsDataViewGeneratedAtUtc = DateTime . UtcNow ;
108
+ }
109
+ else
110
+ {
111
+ this . previousPlainTextDataViewGeneratedAtUtc = DateTime . UtcNow ;
112
+ }
113
+
114
+ previousDataViewGeneratedAtUtc = openMetricsRequested
115
+ ? this . previousOpenMetricsDataViewGeneratedAtUtc
116
+ : this . previousPlainTextDataViewGeneratedAtUtc ;
117
+
118
+ response = new CollectionResponse ( this . previousOpenMetricsDataView , this . previousPlainTextDataView , previousDataViewGeneratedAtUtc . Value , fromCache : false ) ;
91
119
}
92
120
else
93
121
{
@@ -170,6 +198,7 @@ private bool ExecuteCollect(bool openMetricsRequested)
170
198
private ExportResult OnCollect ( Batch < Metric > metrics )
171
199
{
172
200
var cursor = 0 ;
201
+ var buffer = this . exporter . OpenMetricsRequested ? this . openMetricsBuffer : this . plainTextBuffer ;
173
202
174
203
try
175
204
{
@@ -192,13 +221,13 @@ private ExportResult OnCollect(Batch<Metric> metrics)
192
221
{
193
222
try
194
223
{
195
- cursor = PrometheusSerializer . WriteScopeInfo ( this . buffer , cursor , metric . MeterName ) ;
224
+ cursor = PrometheusSerializer . WriteScopeInfo ( buffer , cursor , metric . MeterName ) ;
196
225
197
226
break ;
198
227
}
199
228
catch ( IndexOutOfRangeException )
200
229
{
201
- if ( ! this . IncreaseBufferSize ( ) )
230
+ if ( ! this . IncreaseBufferSize ( ref buffer ) )
202
231
{
203
232
// there are two cases we might run into the following condition:
204
233
// 1. we have many metrics to be exported - in this case we probably want
@@ -226,7 +255,7 @@ private ExportResult OnCollect(Batch<Metric> metrics)
226
255
try
227
256
{
228
257
cursor = PrometheusSerializer . WriteMetric (
229
- this . buffer ,
258
+ buffer ,
230
259
cursor ,
231
260
metric ,
232
261
this . GetPrometheusMetric ( metric ) ,
@@ -236,7 +265,7 @@ private ExportResult OnCollect(Batch<Metric> metrics)
236
265
}
237
266
catch ( IndexOutOfRangeException )
238
267
{
239
- if ( ! this . IncreaseBufferSize ( ) )
268
+ if ( ! this . IncreaseBufferSize ( ref buffer ) )
240
269
{
241
270
throw ;
242
271
}
@@ -248,24 +277,40 @@ private ExportResult OnCollect(Batch<Metric> metrics)
248
277
{
249
278
try
250
279
{
251
- cursor = PrometheusSerializer . WriteEof ( this . buffer , cursor ) ;
280
+ cursor = PrometheusSerializer . WriteEof ( buffer , cursor ) ;
252
281
break ;
253
282
}
254
283
catch ( IndexOutOfRangeException )
255
284
{
256
- if ( ! this . IncreaseBufferSize ( ) )
285
+ if ( ! this . IncreaseBufferSize ( ref buffer ) )
257
286
{
258
287
throw ;
259
288
}
260
289
}
261
290
}
262
291
263
- this . previousDataView = new ArraySegment < byte > ( this . buffer , 0 , cursor ) ;
292
+ if ( this . exporter . OpenMetricsRequested )
293
+ {
294
+ this . previousOpenMetricsDataView = new ArraySegment < byte > ( this . openMetricsBuffer , 0 , cursor ) ;
295
+ }
296
+ else
297
+ {
298
+ this . previousPlainTextDataView = new ArraySegment < byte > ( this . plainTextBuffer , 0 , cursor ) ;
299
+ }
300
+
264
301
return ExportResult . Success ;
265
302
}
266
303
catch ( Exception )
267
304
{
268
- this . previousDataView = new ArraySegment < byte > ( Array . Empty < byte > ( ) , 0 , 0 ) ;
305
+ if ( this . exporter . OpenMetricsRequested )
306
+ {
307
+ this . previousOpenMetricsDataView = new ArraySegment < byte > ( Array . Empty < byte > ( ) , 0 , 0 ) ;
308
+ }
309
+ else
310
+ {
311
+ this . previousPlainTextDataView = new ArraySegment < byte > ( Array . Empty < byte > ( ) , 0 , 0 ) ;
312
+ }
313
+
269
314
return ExportResult . Failure ;
270
315
}
271
316
}
@@ -278,13 +323,13 @@ private int WriteTargetInfo()
278
323
{
279
324
try
280
325
{
281
- this . targetInfoBufferLength = PrometheusSerializer . WriteTargetInfo ( this . buffer , 0 , this . exporter . Resource ) ;
326
+ this . targetInfoBufferLength = PrometheusSerializer . WriteTargetInfo ( this . openMetricsBuffer , 0 , this . exporter . Resource ) ;
282
327
283
328
break ;
284
329
}
285
330
catch ( IndexOutOfRangeException )
286
331
{
287
- if ( ! this . IncreaseBufferSize ( ) )
332
+ if ( ! this . IncreaseBufferSize ( ref this . openMetricsBuffer ) )
288
333
{
289
334
throw ;
290
335
}
@@ -295,18 +340,18 @@ private int WriteTargetInfo()
295
340
return this . targetInfoBufferLength ;
296
341
}
297
342
298
- private bool IncreaseBufferSize ( )
343
+ private bool IncreaseBufferSize ( ref byte [ ] buffer )
299
344
{
300
- var newBufferSize = this . buffer . Length * 2 ;
345
+ var newBufferSize = buffer . Length * 2 ;
301
346
302
347
if ( newBufferSize > 100 * 1024 * 1024 )
303
348
{
304
349
return false ;
305
350
}
306
351
307
352
var newBuffer = new byte [ newBufferSize ] ;
308
- this . buffer . CopyTo ( newBuffer , 0 ) ;
309
- this . buffer = newBuffer ;
353
+ buffer . CopyTo ( newBuffer , 0 ) ;
354
+ buffer = newBuffer ;
310
355
311
356
return true ;
312
357
}
@@ -331,14 +376,17 @@ private PrometheusMetric GetPrometheusMetric(Metric metric)
331
376
332
377
public readonly struct CollectionResponse
333
378
{
334
- public CollectionResponse ( ArraySegment < byte > view , DateTime generatedAtUtc , bool fromCache )
379
+ public CollectionResponse ( ArraySegment < byte > openMetricsView , ArraySegment < byte > plainTextView , DateTime generatedAtUtc , bool fromCache )
335
380
{
336
- this . View = view ;
381
+ this . OpenMetricsView = openMetricsView ;
382
+ this . PlainTextView = plainTextView ;
337
383
this . GeneratedAtUtc = generatedAtUtc ;
338
384
this . FromCache = fromCache ;
339
385
}
340
386
341
- public ArraySegment < byte > View { get ; }
387
+ public ArraySegment < byte > OpenMetricsView { get ; }
388
+
389
+ public ArraySegment < byte > PlainTextView { get ; }
342
390
343
391
public DateTime GeneratedAtUtc { get ; }
344
392
0 commit comments