.builder(FluxMetrics.METER_FLOW_DURATION) .tags(commonTags) .tag(FluxMetrics.TAG_STATUS, FluxMetrics.TAGVALUE_ON_COMPLETE) .tag(FluxMetrics.TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the onComplete termination of the sequence") .register(registry); .builder(FluxMetrics.METER_FLOW_DURATION) .tags(commonTags) .tag(FluxMetrics.TAG_STATUS, FluxMetrics.TAGVALUE_CANCEL) .tag(FluxMetrics.TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the cancellation of the sequence") .register(registry); .builder(FluxMetrics.METER_FLOW_DURATION) .tags(commonTags) .tag(FluxMetrics.TAG_STATUS, FluxMetrics.TAGVALUE_ON_ERROR) .description("Times the duration elapsed between a subscription and the onError termination of the sequence, with the exception name as a tag."); this.subscribeToErrorTimerFactory = e -> { return subscribeToErrorTimerBuilder .tag(FluxMetrics.TAG_EXCEPTION, e.getClass().getName()) .register(registry); };
.builder(METER_FLOW_DURATION) .tags(commonTags) .tag(TAG_STATUS, TAGVALUE_ON_COMPLETE) .tag(TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the onComplete termination of the sequence") .register(registry); .builder(METER_FLOW_DURATION) .tags(commonTags) .tag(TAG_STATUS, TAGVALUE_CANCEL) .tag(TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the cancellation of the sequence") .register(registry); .builder(METER_FLOW_DURATION) .tags(commonTags) .tag(TAG_STATUS, TAGVALUE_ON_ERROR) .description("Times the duration elapsed between a subscription and the onError termination of the sequence, with the exception name as a tag"); this.subscribeToErrorTimerFactory = e -> { return subscribeToErrorTimerBuilder .tag(TAG_EXCEPTION, e.getClass().getName()) .register(registry); };
/** * Creates a new timer function using the given template. This method initializes the default timers. * * @param timerTemplate The template to create the instances from. * @return The newly created function that returns a timer for a given code. */ protected Function<Code, Timer> asTimerFunction(final Supplier<Timer.Builder> timerTemplate) { final Map<Code, Timer> cache = new EnumMap<>(Code.class); final Function<Code, Timer> creator = code -> timerTemplate.get() .tag(TAG_STATUS_CODE, code.name()) .register(this.registry); final Function<Code, Timer> cacheResolver = code -> cache.computeIfAbsent(code, creator); // Eager initialize for (final Code code : this.eagerInitializedCodes) { cacheResolver.apply(code); } return cacheResolver; }
.builder(METER_FLOW_DURATION) .tags(commonTags) .tag(TAG_STATUS, TAGVALUE_ON_COMPLETE) .tag(TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the onComplete termination of the sequence") .register(registry); .builder(METER_FLOW_DURATION) .tags(commonTags) .tag(TAG_STATUS, TAGVALUE_CANCEL) .tag(TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the cancellation of the sequence") .register(registry); .builder(METER_FLOW_DURATION) .tags(commonTags) .tag(TAG_STATUS, TAGVALUE_ON_ERROR) .description("Times the duration elapsed between a subscription and the onError termination of the sequence, with the exception name as a tag"); this.subscribeToErrorTimerFactory = e -> { return subscribeToErrorTimerBuilder .tag(TAG_EXCEPTION, e.getClass().getName()) .register(registry); };
.tag(tagKey, tagValue);
.builder(FluxMetrics.METER_FLOW_DURATION) .tags(commonTags) .tag(FluxMetrics.TAG_STATUS, FluxMetrics.TAGVALUE_ON_COMPLETE) .tag(FluxMetrics.TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the onComplete termination of the sequence") .register(registry); .builder(FluxMetrics.METER_FLOW_DURATION) .tags(commonTags) .tag(FluxMetrics.TAG_STATUS, FluxMetrics.TAGVALUE_CANCEL) .tag(FluxMetrics.TAG_EXCEPTION, "") .description("Times the duration elapsed between a subscription and the cancellation of the sequence") .register(registry); .builder(FluxMetrics.METER_FLOW_DURATION) .tags(commonTags) .tag(FluxMetrics.TAG_STATUS, FluxMetrics.TAGVALUE_ON_ERROR) .description("Times the duration elapsed between a subscription and the onError termination of the sequence, with the exception name as a tag."); this.subscribeToErrorTimerFactory = e -> { return subscribeToErrorTimerBuilder .tag(FluxMetrics.TAG_EXCEPTION, e.getClass().getName()) .register(registry); };
/** * Creates a new timer function using the given template. This method initializes the default timers. * * @param timerTemplate The template to create the instances from. * @return The newly created function that returns a timer for a given code. */ protected Function<Code, Timer> asTimerFunction(final Supplier<Timer.Builder> timerTemplate) { final Map<Code, Timer> cache = new EnumMap<>(Code.class); final Function<Code, Timer> creator = code -> timerTemplate.get() .tag(TAG_STATUS_CODE, code.name()) .register(this.registry); final Function<Code, Timer> cacheResolver = code -> cache.computeIfAbsent(code, creator); // Eager initialize for (final Code code : this.eagerInitializedCodes) { cacheResolver.apply(code); } return cacheResolver; }
/** * Creates a new timer builder for the given method. * * @param method The method the timer will be created for. * @param name The name of the timer to use. * @param description The description of the timer to use. * @return The newly created timer builder. */ public static Timer.Builder prepareTimerFor(final MethodDescriptor<?, ?> method, final String name, final String description) { return Timer.builder(name) .description(description) .tag(TAG_SERVICE_NAME, extractServiceName(method)) .tag(TAG_METHOD_NAME, extractMethodName(method)); }
@Override public MicroTimerBuilder tag(String key, String value) { this.builder.tag(key, value); return this; }
@Test public void testServerCustomization() { log.info("--- Starting tests with server customization ---"); final MeterRegistry meterRegistry = new SimpleMeterRegistry(); assertEquals(0, meterRegistry.getMeters().size()); final MetricCollectingServerInterceptor mcsi = new MetricCollectingServerInterceptor(meterRegistry, counter -> counter.tag("type", "counter"), timer -> timer.tag("type", "timer").publishPercentiles(0.5, 0.9, 0.99), OK, UNKNOWN); mcsi.preregisterService(new TestServiceImpl()); MetricTestHelper.logMeters(meterRegistry.getMeters()); assertEquals(METHOD_COUNT * 10, meterRegistry.getMeters().size()); final Counter counter = meterRegistry.find(METRIC_NAME_SERVER_REQUESTS_RECEIVED).counter(); assertNotNull(counter); assertEquals("counter", counter.getId().getTag("type")); final Timer timer = meterRegistry.find(METRIC_NAME_SERVER_PROCESSING_DURATION).timer(); assertNotNull(timer); assertEquals("timer", timer.getId().getTag("type")); log.info("--- Test completed ---"); }
@Test public void testClientCustomization() { log.info("--- Starting tests with client customization ---"); final MeterRegistry meterRegistry = new SimpleMeterRegistry(); assertEquals(0, meterRegistry.getMeters().size()); final MetricCollectingClientInterceptor mcci = new MetricCollectingClientInterceptor(meterRegistry, counter -> counter.tag("type", "counter"), timer -> timer.tag("type", "timer").publishPercentiles(0.5, 0.9, 0.99), OK, UNKNOWN); mcci.preregisterService(TestServiceGrpc.getServiceDescriptor()); MetricTestHelper.logMeters(meterRegistry.getMeters()); assertEquals(METHOD_COUNT * 10, meterRegistry.getMeters().size()); final Counter counter = meterRegistry.find(METRIC_NAME_CLIENT_REQUESTS_SENT).counter(); assertNotNull(counter); assertEquals("counter", counter.getId().getTag("type")); final Timer timer = meterRegistry.find(METRIC_NAME_CLIENT_PROCESSING_DURATION).timer(); assertNotNull(timer); assertEquals("timer", timer.getId().getTag("type")); log.info("--- Test completed ---"); }
/** * Creates a new timer builder for the given method. * * @param method The method the timer will be created for. * @param name The name of the timer to use. * @param description The description of the timer to use. * @return The newly created timer builder. */ public static Timer.Builder prepareTimerFor(final MethodDescriptor<?, ?> method, final String name, final String description) { return Timer.builder(name) .description(description) .tag(TAG_SERVICE_NAME, extractServiceName(method)) .tag(TAG_METHOD_NAME, extractMethodName(method)); }
@Bean public MetricCollectingServerInterceptor metricCollectingServerInterceptor(final MeterRegistry registry, final Collection<BindableService> services) { final MetricCollectingServerInterceptor metricCollector = new MetricCollectingServerInterceptor(registry, counter -> counter.tag("type", "counter"), timer -> timer.tag("type", "timer").publishPercentiles(0.5, 0.9, 0.99), OK, UNKNOWN); log.debug("Pre-Registering custom service metrics"); for (final BindableService service : services) { log.debug("- {}", service); metricCollector.preregisterService(service); } return metricCollector; }
@Override public MicroTimerBuilder tag(String key, String value) { this.builder.tag(key, value); return this; }