/* Copyright (c) 2008-2009 HomeAway, Inc. * All rights reserved. http://www.perf4j.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.perf4j.logback; import junit.framework.TestCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; import org.perf4j.StopWatch; import org.perf4j.helpers.StatisticsExposingMBean; import javax.management.MBeanInfo; import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; import java.lang.management.ManagementFactory; /** * Tests the JmxAttributeStatisticsAppender */ public class JmxAppenderTest extends TestCase { public void testJmxAppender() throws Exception { LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); // the context was probably already configured by default configuration // rules lc.reset(); configurator.doConfigure(getClass().getResource("logbackWJmx.xml")); MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName statisticsMBeanName = new ObjectName(StatisticsExposingMBean.DEFAULT_MBEAN_NAME); //add a notification listener so we can check for notifications DummyNotificationListener notificationListener = new DummyNotificationListener(); server.addNotificationListener(statisticsMBeanName, notificationListener, null, null); //log a bunch of messages Logger logger = LoggerFactory.getLogger(StopWatch.DEFAULT_LOGGER_NAME); for (int i = 0; i < 20; i++) { long time = (i % 2) == 0 ? 100L : 200L; logger.info("{}", new StopWatch(System.currentTimeMillis(), time, "tag" + (i % 2), "logging")); Thread.sleep(110); } //check that the mbean attributes are accessible assertTrue(((Integer) server.getAttribute(statisticsMBeanName, "tag0Count")) > 0); assertEquals(0.0, server.getAttribute(statisticsMBeanName, "tag0StdDev")); assertEquals(100.0, server.getAttribute(statisticsMBeanName, "tag0Mean")); assertEquals(100L, server.getAttribute(statisticsMBeanName, "tag0Min")); assertEquals(100L, server.getAttribute(statisticsMBeanName, "tag0Max")); assertTrue(((Double) server.getAttribute(statisticsMBeanName, "tag0TPS")) > 1); assertTrue(((Integer) server.getAttribute(statisticsMBeanName, "tag1Count")) > 0); assertEquals(0.0, server.getAttribute(statisticsMBeanName, "tag1StdDev")); assertEquals(200.0, server.getAttribute(statisticsMBeanName, "tag1Mean")); assertEquals(200L, server.getAttribute(statisticsMBeanName, "tag1Min")); assertEquals(200L, server.getAttribute(statisticsMBeanName, "tag1Max")); assertTrue(((Double) server.getAttribute(statisticsMBeanName, "tag1TPS")) > 1); //invoke exposeTag, insure that it makes a tag accessible server.invoke(statisticsMBeanName, "exposeTag", new Object[]{"tagFoo"}, new String[0]); assertEquals(0, server.getAttribute(statisticsMBeanName, "tagFooCount")); //invoke removeTag, which should return true assertTrue((Boolean) server.invoke(statisticsMBeanName, "removeTag", new Object[]{"tagFoo"}, new String[] {String.class.getName()})); //now at a stopwatch that should trigger a notification logger.info("{}", new StopWatch(System.currentTimeMillis(), 20000L, "tag0", "logging")); Thread.sleep(1100L); //go over the next time slice boundary logger.info("{}", new StopWatch(System.currentTimeMillis(), 20000L, "tag0", "logging")); //check for the notification - need the wait loop as it takes time for the notification to appear for (int i = 0; i <= 200; i++) { Thread.sleep(10); if (notificationListener.lastReceivedNotification != null) { assertEquals(StatisticsExposingMBean.OUT_OF_RANGE_NOTIFICATION_TYPE, notificationListener.lastReceivedNotification.getType()); break; } if (i == 200) { fail("Notification not received after 2 seconds"); } } } public void testCollisionDonothing() throws Exception { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName statisticsMBeanName = new ObjectName(StatisticsExposingMBean.DEFAULT_MBEAN_NAME); initJmxMBean(); assertTrue(server.isRegistered(statisticsMBeanName)); MBeanInfo mbeanInfo = server.getMBeanInfo(statisticsMBeanName); assertTrue(mbeanInfo.toString(), mbeanInfo.getAttributes().length == 1 * 6); try { JmxAttributeStatisticsAppender appender = new JmxAttributeStatisticsAppender(); appender.setTagNamesToExpose("donothing1,donothing2,donothing3"); appender.start(); fail("should cause an exception"); } catch(Exception ex) { assertTrue(true); } mbeanInfo = server.getMBeanInfo(statisticsMBeanName); // if mbean had bean replaced, the count of attrs should be 18. assertTrue(mbeanInfo.toString(), mbeanInfo.getAttributes().length == 1 * 6); } public void testCollisionReplace() throws Exception { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName statisticsMBeanName = new ObjectName(StatisticsExposingMBean.DEFAULT_MBEAN_NAME); initJmxMBean(); assertTrue(server.isRegistered(statisticsMBeanName)); MBeanInfo mbeanInfo = server.getMBeanInfo(statisticsMBeanName); assertTrue(mbeanInfo.toString(), mbeanInfo.getAttributes().length == 1 * 6); JmxAttributeStatisticsAppender appender = new JmxAttributeStatisticsAppender(); appender.setTagNamesToExpose("replace1,replace2,replace3,replace4"); appender.setCollision(StatisticsExposingMBean.COLLISION_REPLACE); appender.start(); mbeanInfo = server.getMBeanInfo(statisticsMBeanName); // if mbean had bean replaced, the count of attrs should be 24. assertTrue(mbeanInfo.toString(), mbeanInfo.getAttributes().length == 4 * 6); } public void testCollisionIgnore() throws Exception { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName statisticsMBeanName = new ObjectName(StatisticsExposingMBean.DEFAULT_MBEAN_NAME); initJmxMBean(); assertTrue(server.isRegistered(statisticsMBeanName)); MBeanInfo mbeanInfo = server.getMBeanInfo(statisticsMBeanName); assertTrue(mbeanInfo.toString(), mbeanInfo.getAttributes().length == 1 * 6); JmxAttributeStatisticsAppender appender = new JmxAttributeStatisticsAppender(); appender.setTagNamesToExpose("ignore1,ignore2,ignore3,ignore4,ignore5"); appender.setCollision(StatisticsExposingMBean.COLLISION_IGNORE); appender.start(); mbeanInfo = server.getMBeanInfo(statisticsMBeanName); // if mbean had bean replaced, the count of attrs should be 30. assertTrue(mbeanInfo.toString(), mbeanInfo.getAttributes().length == 1 * 6); } protected void initJmxMBean() { JmxAttributeStatisticsAppender appender = new JmxAttributeStatisticsAppender(); appender.setTagNamesToExpose("x"); appender.setCollision(StatisticsExposingMBean.COLLISION_REPLACE); appender.start(); } protected static class DummyNotificationListener implements NotificationListener { public Notification lastReceivedNotification; public void handleNotification(Notification notification, Object handback) { lastReceivedNotification = notification; } } }