001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.broker.jmx; 018 019import java.io.File; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Map; 023 024import javax.management.ObjectName; 025import javax.management.openmbean.CompositeDataSupport; 026import javax.management.openmbean.CompositeType; 027import javax.management.openmbean.TabularData; 028import javax.management.openmbean.TabularDataSupport; 029import javax.management.openmbean.TabularType; 030 031import org.apache.activemq.broker.BrokerService; 032import org.apache.activemq.broker.scheduler.JobSchedulerStore; 033import org.apache.activemq.store.PersistenceAdapter; 034import org.apache.activemq.usage.SystemUsage; 035 036public class HealthView implements HealthViewMBean { 037 038 ManagedRegionBroker broker; 039 String currentState = "Good"; 040 041 public HealthView(ManagedRegionBroker broker) { 042 this.broker = broker; 043 } 044 045 @Override 046 public TabularData health() throws Exception { 047 OpenTypeSupport.OpenTypeFactory factory = OpenTypeSupport.getFactory(HealthStatus.class); 048 CompositeType ct = factory.getCompositeType(); 049 TabularType tt = new TabularType("HealthStatus", "HealthStatus", ct, new String[] { "healthId", "level", "message", "resource" }); 050 TabularDataSupport rc = new TabularDataSupport(tt); 051 052 List<HealthStatus> list = healthList(); 053 for (HealthStatus healthStatus : list) { 054 rc.put(new CompositeDataSupport(ct, factory.getFields(healthStatus))); 055 } 056 return rc; 057 } 058 059 @Override 060 public List<HealthStatus> healthList() throws Exception { 061 List<HealthStatus> answer = new ArrayList<HealthStatus>(); 062 Map<ObjectName, DestinationView> queueViews = broker.getQueueViews(); 063 for (Map.Entry<ObjectName, DestinationView> entry : queueViews.entrySet()) { 064 DestinationView queue = entry.getValue(); 065 if (queue.getConsumerCount() == 0 && queue.getProducerCount() > 0) { 066 ObjectName key = entry.getKey(); 067 String message = "Queue " + queue.getName() + " has no consumers"; 068 answer.add(new HealthStatus("org.apache.activemq.noConsumer", "WARNING", message, key.toString())); 069 } 070 } 071 072 /** 073 * Check persistence store directory limits 074 */ 075 BrokerService brokerService = broker.getBrokerService(); 076 if (brokerService != null && brokerService.getPersistenceAdapter() != null) { 077 PersistenceAdapter adapter = brokerService.getPersistenceAdapter(); 078 File dir = adapter.getDirectory(); 079 if (brokerService.isPersistent()) { 080 SystemUsage usage = brokerService.getSystemUsage(); 081 if (dir != null && usage != null) { 082 String dirPath = dir.getAbsolutePath(); 083 if (!dir.isAbsolute()) { 084 dir = new File(dirPath); 085 } 086 087 while (dir != null && !dir.isDirectory()) { 088 dir = dir.getParentFile(); 089 } 090 long storeSize = adapter.size(); 091 long storeLimit = usage.getStoreUsage().getLimit(); 092 long dirFreeSpace = dir.getUsableSpace(); 093 094 if (storeSize != 0 && storeLimit != 0) { 095 int val = (int) ((storeSize * 100) / storeLimit); 096 if (val > 90) { 097 answer.add(new HealthStatus("org.apache.activemq.StoreLimit", "WARNING", "Message Store size is within " + val + "% of its limit", 098 adapter.toString())); 099 } 100 } 101 102 if ((storeLimit - storeSize) > dirFreeSpace) { 103 String message = "Store limit is " + storeLimit / (1024 * 1024) + " mb, whilst the data directory: " + dir.getAbsolutePath() 104 + " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space"; 105 answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, adapter.toString())); 106 } 107 } 108 109 File tmpDir = brokerService.getTmpDataDirectory(); 110 if (tmpDir != null) { 111 112 String tmpDirPath = tmpDir.getAbsolutePath(); 113 if (!tmpDir.isAbsolute()) { 114 tmpDir = new File(tmpDirPath); 115 } 116 117 long storeSize = usage.getTempUsage().getUsage(); 118 long storeLimit = usage.getTempUsage().getLimit(); 119 while (tmpDir != null && !tmpDir.isDirectory()) { 120 tmpDir = tmpDir.getParentFile(); 121 } 122 123 if (storeLimit != 0) { 124 int val = (int) ((storeSize * 100) / storeLimit); 125 if (val > 90) { 126 answer.add(new HealthStatus("org.apache.activemq.TempStoreLimit", "WARNING", "TempMessage Store size is within " + val 127 + "% of its limit", adapter.toString())); 128 } 129 } 130 } 131 } 132 } 133 134 if (brokerService != null && brokerService.getJobSchedulerStore() != null) { 135 JobSchedulerStore scheduler = brokerService.getJobSchedulerStore(); 136 File dir = scheduler.getDirectory(); 137 if (brokerService.isPersistent()) { 138 SystemUsage usage = brokerService.getSystemUsage(); 139 if (dir != null && usage != null) { 140 String dirPath = dir.getAbsolutePath(); 141 if (!dir.isAbsolute()) { 142 dir = new File(dirPath); 143 } 144 145 while (dir != null && !dir.isDirectory()) { 146 dir = dir.getParentFile(); 147 } 148 long storeSize = scheduler.size(); 149 long storeLimit = usage.getJobSchedulerUsage().getLimit(); 150 long dirFreeSpace = dir.getUsableSpace(); 151 152 if (storeSize != 0 && storeLimit != 0) { 153 int val = (int) ((storeSize * 100) / storeLimit); 154 if (val > 90) { 155 answer.add(new HealthStatus("org.apache.activemq.JobSchedulerLimit", "WARNING", "JobSchedulerMessage Store size is within " + val 156 + "% of its limit", scheduler.toString())); 157 } 158 } 159 160 if ((storeLimit - storeSize) > dirFreeSpace) { 161 String message = "JobSchedulerStore limit is " + storeLimit / (1024 * 1024) + " mb, whilst the data directory: " 162 + dir.getAbsolutePath() + " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space"; 163 answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, scheduler.toString())); 164 } 165 } 166 } 167 } 168 169 if (answer != null && !answer.isEmpty()) { 170 this.currentState = "Getting Worried {"; 171 for (HealthStatus hs : answer) { 172 currentState += hs + " , "; 173 } 174 currentState += " }"; 175 } else { 176 this.currentState = "Good"; 177 } 178 return answer; 179 } 180 181 /** 182 * @return String representation of the current Broker state 183 */ 184 @Override 185 public String getCurrentStatus() { 186 return this.currentState; 187 } 188}