GaugeCollector extends ScheduledRunnable { @VisibleForTesting @RequiresNonNull("priorRawCounterValues") List<GaugeValue> collectGaugeValues(GaugeConfig gaugeConfig, List<MBeanServer> mbeanServers) throws Exception { String mbeanObjectName = gaugeConfig.mbeanObjectName(); ObjectName objectName; try { objectName = ObjectName.getInstance(mbeanObjectName); } catch (MalformedObjectNameException e) { logger.debug(e.getMessage(), e); logFirstTimeMBeanException(mbeanObjectName, e); return ImmutableList.of(); } if (!objectName.isPattern()) { return collectGaugeValues(objectName, gaugeConfig.mbeanAttributes(), mbeanObjectName, mbeanServers); } Set<ObjectName> matchingObjectNames = lazyPlatformMBeanServer.queryNames(objectName, null, mbeanServers); if (matchingObjectNames.isEmpty()) { logFirstTimeMBeanNotMatchedOrFound(mbeanObjectName); return ImmutableList.of(); } pendingLoggedMBeanGauges.remove(mbeanObjectName); List<GaugeValue> gaugeValues = Lists.newArrayList(); for (ObjectName matchingObjectName : matchingObjectNames) { gaugeValues.addAll(collectGaugeValues(matchingObjectName, gaugeConfig.mbeanAttributes(), matchingObjectName.getDomain() + ":" + matchingObjectName.getKeyPropertyListString(), mbeanServers)); } return gaugeValues; } GaugeCollector(ConfigService configService, Collector collector,
            LazyPlatformMBeanServer lazyPlatformMBeanServer,
            final @Nullable Instrumentation instrumentation, Clock clock, Ticker ticker);   }
@Test public void shouldCaptureNonCounterGauge() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("test:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenReturn(555); List<GaugeValue> gaugeValues = collectGaugeValues(gaugeConfig); assertThat(gaugeValues).hasSize(1); assertThat(gaugeValues.get(0).getValue()).isEqualTo(555); assertThat(gaugeValues.get(0).getWeight()).isEqualTo(1); }
@Test public void shouldNotCaptureCounterGauge() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("test:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", true)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenReturn(555); gaugeCollector.run(); List<GaugeValue> gaugeValues = collectGaugeValues(gaugeConfig); assertThat(gaugeValues).isEmpty(); }
@Test public void shouldCaptureCounterGauge() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("test:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", true)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenReturn(555, 565); when(ticker.read()).thenReturn(SECONDS.toNanos(1), SECONDS.toNanos(3)); gaugeCollector.run(); collectGaugeValues(gaugeConfig); List<GaugeValue> gaugeValues = collectGaugeValues(gaugeConfig); assertThat(gaugeValues).hasSize(1); assertThat(gaugeValues.get(0).getValue()).isEqualTo(5); assertThat(gaugeValues.get(0).getWeight()).isEqualTo(SECONDS.toNanos(2)); }
@Test public void shouldHandleInvalidMBeanObjectName() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("invalid mbean object name") .build(); List<GaugeValue> gaugeValues = collectGaugeValues(gaugeConfig); assertThat(gaugeValues).isEmpty(); verify(logger).debug(anyString(), any(Exception.class)); verify(logger).warn(eq("error accessing mbean: {}"), eq("invalid mbean object name"), any(MalformedObjectNameException.class)); }
@Test public void shouldHandleMBeanInstanceNotFoundBeforeLoggingDelay() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(clock.currentTimeMillis()).thenReturn(59999L); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenThrow(InstanceNotFoundException.class); List<GaugeValue> gaugeValues = collectGaugeValues(gaugeConfig); assertThat(gaugeValues).isEmpty(); verify(logger).debug(nullable(String.class), any(Exception.class)); }
@Test public void shouldHandleMBeanInstanceNotFoundAfterLoggingDelay() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(clock.currentTimeMillis()).thenReturn(60000L); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenThrow(InstanceNotFoundException.class); List<GaugeValue> gaugeValues = collectGaugeValues(gaugeConfig); assertThat(gaugeValues).isEmpty(); verify(logger).debug(nullable(String.class), any(Exception.class)); verify(logger).warn("mbean not {}: {}", "found", "xyz:aaa=bbb"); }
@Test public void shouldHandleMBeanInstanceNotFoundBeforeAndAfterLoggingDelay() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(clock.currentTimeMillis()).thenReturn(0L).thenReturn(30000L).thenReturn(60000L); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenThrow(InstanceNotFoundException.class); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); verify(logger, times(5)).debug(nullable(String.class), any(Exception.class)); verify(logger) .warn("mbean not {}: {} (waited {} seconds after jvm startup before logging this" + " warning to allow time for mbean registration - this wait time can be" + " changed under Configuration > Advanced)", "found", "xyz:aaa=bbb", 60); }
@Test public void shouldHandleMBeanAttributeNotFound() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenThrow(AttributeNotFoundException.class); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); verify(logger, times(10)).debug(nullable(String.class), any(Exception.class)); verify(logger).warn("mbean attribute {} not found in {}", "ccc", "xyz:aaa=bbb"); verify(logger).warn("mbean attribute {} not found in {}", "ddd", "xyz:aaa=bbb"); }
@Test public void shouldHandleMBeanAttributeOtherException() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenThrow(new RuntimeException("A msg")); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); verify(logger, times(10)).debug(anyString(), any(Exception.class)); verify(logger).warn(eq("error accessing mbean attribute: {} {}"), eq("xyz:aaa=bbb"), eq("ccc"), any(RuntimeException.class)); verify(logger).warn(eq("error accessing mbean attribute: {} {}"), eq("xyz:aaa=bbb"), eq("ddd"), any(RuntimeException.class)); }
@Test public void shouldHandleMBeanAttributeNotANumber() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenReturn("not a number"); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); verify(logger).warn("error accessing mbean attribute {} {}: {}", "xyz:aaa=bbb", "ccc", "MBean attribute value is not a valid number: \"not a number\""); verify(logger).warn("error accessing mbean attribute {} {}: {}", "xyz:aaa=bbb", "ddd", "MBean attribute value is not a valid number: \"not a number\""); }
@Test public void shouldHandleMBeanAttributeNotANumberOrString() throws Exception { GaugeConfig gaugeConfig = ImmutableGaugeConfig.builder() .mbeanObjectName("xyz:aaa=bbb") .addMbeanAttributes(ImmutableMBeanAttribute.of("ccc", false)) .addMbeanAttributes(ImmutableMBeanAttribute.of("ddd", false)) .build(); when(lazyPlatformMBeanServer.getAttribute(any(ObjectName.class), anyString(), anyMBeanServerList())).thenReturn(new Object()); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); collectGaugeValues(gaugeConfig); verify(logger).warn("error accessing mbean attribute {} {}: {}", "xyz:aaa=bbb", "ccc", "MBean attribute value is not a number or string"); verify(logger).warn("error accessing mbean attribute {} {}: {}", "xyz:aaa=bbb", "ddd", "MBean attribute value is not a number or string"); }