/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.activemq.broker.jmx; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.management.ObjectName; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeType; import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; import org.apache.activemq.broker.BrokerService; import org.apache.activemq.broker.scheduler.JobSchedulerStore; import org.apache.activemq.store.PersistenceAdapter; import org.apache.activemq.usage.SystemUsage; public class HealthView implements HealthViewMBean { private ManagedRegionBroker broker; private volatile String currentState = "Good"; public HealthView(ManagedRegionBroker broker) { this.broker = broker; } @Override public TabularData health() throws Exception { OpenTypeSupport.OpenTypeFactory factory = OpenTypeSupport.getFactory(HealthStatus.class); CompositeType ct = factory.getCompositeType(); TabularType tt = new TabularType("HealthStatus", "HealthStatus", ct, new String[] { "healthId", "level", "message", "resource" }); TabularDataSupport rc = new TabularDataSupport(tt); List<HealthStatus> list = healthList(); for (HealthStatus healthStatus : list) { rc.put(new CompositeDataSupport(ct, factory.getFields(healthStatus))); } return rc; } @Override public List<HealthStatus> healthList() throws Exception { List<HealthStatus> answer = new ArrayList<HealthStatus>(); Map<ObjectName, DestinationView> queueViews = broker.getQueueViews(); for (Map.Entry<ObjectName, DestinationView> entry : queueViews.entrySet()) { DestinationView queue = entry.getValue(); if (queue.getConsumerCount() == 0 && queue.getProducerCount() > 0) { ObjectName key = entry.getKey(); String message = "Queue " + queue.getName() + " has no consumers"; answer.add(new HealthStatus("org.apache.activemq.noConsumer", "WARNING", message, key.toString())); } } /** * Check persistence store directory limits */ BrokerService brokerService = broker.getBrokerService(); if (brokerService != null && brokerService.getPersistenceAdapter() != null) { PersistenceAdapter adapter = brokerService.getPersistenceAdapter(); File dir = adapter.getDirectory(); if (brokerService.isPersistent()) { SystemUsage usage = brokerService.getSystemUsage(); if (dir != null && usage != null) { String dirPath = dir.getAbsolutePath(); if (!dir.isAbsolute()) { dir = new File(dirPath); } while (dir != null && !dir.isDirectory()) { dir = dir.getParentFile(); } long storeSize = adapter.size(); long storeLimit = usage.getStoreUsage().getLimit(); long dirFreeSpace = dir.getUsableSpace(); if (storeSize != 0 && storeLimit != 0) { int val = (int) ((storeSize * 100) / storeLimit); if (val > 90) { answer.add(new HealthStatus("org.apache.activemq.StoreLimit", "WARNING", "Message Store size is within " + val + "% of its limit", adapter.toString())); } } if ((storeLimit - storeSize) > dirFreeSpace) { String message = "Store limit is " + storeLimit / (1024 * 1024) + " mb, whilst the data directory: " + dir.getAbsolutePath() + " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space"; answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, adapter.toString())); } } File tmpDir = brokerService.getTmpDataDirectory(); if (tmpDir != null) { String tmpDirPath = tmpDir.getAbsolutePath(); if (!tmpDir.isAbsolute()) { tmpDir = new File(tmpDirPath); } long storeSize = usage.getTempUsage().getUsage(); long storeLimit = usage.getTempUsage().getLimit(); while (tmpDir != null && !tmpDir.isDirectory()) { tmpDir = tmpDir.getParentFile(); } if (storeLimit != 0) { int val = (int) ((storeSize * 100) / storeLimit); if (val > 90) { answer.add(new HealthStatus("org.apache.activemq.TempStoreLimit", "WARNING", "TempMessage Store size is within " + val + "% of its limit", adapter.toString())); } } } } } if (brokerService != null && brokerService.getJobSchedulerStore() != null) { JobSchedulerStore scheduler = brokerService.getJobSchedulerStore(); File dir = scheduler.getDirectory(); if (brokerService.isPersistent()) { SystemUsage usage = brokerService.getSystemUsage(); if (dir != null && usage != null) { String dirPath = dir.getAbsolutePath(); if (!dir.isAbsolute()) { dir = new File(dirPath); } while (dir != null && !dir.isDirectory()) { dir = dir.getParentFile(); } long storeSize = scheduler.size(); long storeLimit = usage.getJobSchedulerUsage().getLimit(); long dirFreeSpace = dir.getUsableSpace(); if (storeSize != 0 && storeLimit != 0) { int val = (int) ((storeSize * 100) / storeLimit); if (val > 90) { answer.add(new HealthStatus("org.apache.activemq.JobSchedulerLimit", "WARNING", "JobSchedulerMessage Store size is within " + val + "% of its limit", scheduler.toString())); } } if ((storeLimit - storeSize) > dirFreeSpace) { String message = "JobSchedulerStore limit is " + storeLimit / (1024 * 1024) + " mb, whilst the data directory: " + dir.getAbsolutePath() + " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space"; answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, scheduler.toString())); } } } } StringBuilder currentState = new StringBuilder(); if (answer != null && !answer.isEmpty()) { currentState.append("Getting Worried {"); for (HealthStatus hs : answer) { currentState.append(hs).append(" , "); } currentState.append(" }"); } else { currentState.append("Good"); } this.currentState = currentState.toString(); return answer; } @Override public String healthStatus() throws Exception { // Must invoke healthList in order to update state. healthList(); return getCurrentStatus(); } /** * @return String representation of the current Broker state */ @Override public String getCurrentStatus() { return this.currentState; } }