Skip to content

Commit c596457

Browse files
1 parent 77c3c55 commit c596457

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/Metrics.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import io.micrometer.core.instrument.noop.NoopTimer
66

77
val noopTimer = NoopTimer(Meter.Id("", Tags.empty(), null, null, Meter.Type.TIMER))
88
const val REACTOR_METRIC = "reactor.stats"
9-
const val REACTOR_TOTAL_METRIC = "reactor.stats.total"
9+
const val REACTOR_DISCARDED_METRIC = "reactor.discarded"
1010
const val SERVICES_STATE_METRIC = "services.state"
1111
const val SERVICES_STATE_ERRORS_METRIC = "services.state.errors.total"
1212
const val SNAPSHOT_METRIC = "snapshot"

envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/ReactorUtils.kt

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package pl.allegro.tech.servicemesh.envoycontrol.utils
22

33
import io.micrometer.core.instrument.MeterRegistry
4+
import io.micrometer.core.instrument.Tags
45
import org.reactivestreams.Subscription
56
import org.slf4j.LoggerFactory
67
import reactor.core.Disposable
@@ -11,6 +12,7 @@ import reactor.core.scheduler.Scheduler
1112
import reactor.core.scheduler.Schedulers
1213
import java.time.Duration
1314
import java.util.concurrent.TimeUnit
15+
import kotlin.streams.asSequence
1416

1517
private val logger = LoggerFactory.getLogger("pl.allegro.tech.servicemesh.envoycontrol.utils.ReactorUtils")
1618
private val defaultScheduler by lazy { Schedulers.newSingle("reactor-utils-scheduler") }
@@ -50,8 +52,7 @@ fun <T> Flux<T>.measureBuffer(
5052
fun <T> Flux<T>.measureDiscardedItems(name: String, meterRegistry: MeterRegistry): Flux<T> = this
5153
.doOnDiscard(Any::class.java) {
5254
meterRegistry.counter(
53-
REACTOR_METRIC,
54-
METRIC_TYPE_TAG, "discarded-items",
55+
REACTOR_DISCARDED_METRIC,
5556
METRIC_EMITTER_TAG, name
5657
).increment()
5758
}
@@ -110,7 +111,12 @@ private fun measureQueueSubscriptionBuffer(
110111
name: String,
111112
meterRegistry: MeterRegistry
112113
) {
113-
logger.info("subscription $subscription name: $name meterRegistry: $meterRegistry")
114+
meterRegistry.gauge(
115+
REACTOR_METRIC,
116+
Tags.of(METRIC_TYPE_TAG, "buffer-size", METRIC_EMITTER_TAG, name),
117+
subscription,
118+
queueSubscriptionBufferExtractor
119+
)
114120
}
115121

116122
private fun measureScannableBuffer(
@@ -119,7 +125,49 @@ private fun measureScannableBuffer(
119125
innerSources: Int,
120126
meterRegistry: MeterRegistry
121127
) {
122-
logger.info("scannable $scannable name: $name innerSources: $innerSources meterRegistry: $meterRegistry")
128+
val buffered = scannable.scan(Scannable.Attr.BUFFERED)
129+
if (buffered == null) {
130+
logger.error(
131+
"Cannot register metric $REACTOR_METRIC 'with $METRIC_EMITTER_TAG: $name'. Buffer size not available. " +
132+
"Use measureBuffer() only on supported reactor operators"
133+
)
134+
return
135+
}
136+
137+
meterRegistry.gauge(
138+
REACTOR_METRIC,
139+
Tags.of(METRIC_TYPE_TAG, "buffer-size", METRIC_EMITTER_TAG, name),
140+
scannable,
141+
scannableBufferExtractor
142+
)
143+
144+
/**
145+
* Special case for FlatMap derived operators like merge(). The main buffer attribute doesn't return actual
146+
* buffer (that is controlled by `prefetch` parameter) size. Instead it returns simply number of connected sources.
147+
*
148+
* To access actual buffer size, we need to extract it from inners(). We don't know how many sources will
149+
* be available, so it must be stated explicitly as innerSources parameter.
150+
*/
151+
for (i in 0 until innerSources) {
152+
meterRegistry.gauge(
153+
REACTOR_METRIC,
154+
Tags.of(METRIC_TYPE_TAG, "buffer-size", METRIC_EMITTER_TAG, "${(name)}_$i"),
155+
scannable,
156+
innerBufferExtractor(i)
157+
)
158+
}
159+
}
160+
161+
private val scannableBufferExtractor = { s: Scannable -> s.scan(Scannable.Attr.BUFFERED)?.toDouble() ?: -1.0 }
162+
private fun innerBufferExtractor(index: Int) = { s: Scannable ->
163+
s.inners().asSequence()
164+
.elementAtOrNull(index)
165+
?.let(scannableBufferExtractor)
166+
?: -1.0
167+
}
168+
169+
private val queueSubscriptionBufferExtractor = { s: Fuseable.QueueSubscription<*> ->
170+
s.size.toDouble()
123171
}
124172

125173
sealed class ParallelizableScheduler

envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/ReactorUtilsTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package pl.allegro.tech.servicemesh.envoycontrol.utils
33
import io.micrometer.core.instrument.Tags
44
import io.micrometer.core.instrument.simple.SimpleMeterRegistry
55
import org.assertj.core.api.Assertions.assertThat
6-
import org.junit.jupiter.api.Disabled
76
import org.junit.jupiter.api.Test
87
import org.junit.jupiter.api.fail
98
import org.testcontainers.shaded.org.awaitility.Awaitility
@@ -13,7 +12,6 @@ import java.util.concurrent.CountDownLatch
1312
import java.util.concurrent.TimeUnit
1413
import java.util.function.BiFunction
1514

16-
@Disabled
1715
class ReactorUtilsTest {
1816

1917
@Test

0 commit comments

Comments
 (0)