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 private ManagedRegionBroker broker; 039 private volatile 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 091 long storeSize = adapter.size(); 092 long storeLimit = usage.getStoreUsage().getLimit(); 093 long dirFreeSpace = dir.getUsableSpace(); 094 095 if (storeSize != 0 && storeLimit != 0) { 096 int val = (int) ((storeSize * 100) / storeLimit); 097 if (val > 90) { 098 answer.add(new HealthStatus("org.apache.activemq.StoreLimit", "WARNING", "Message Store size is within " + val + "% of its limit", 099 adapter.toString())); 100 } 101 } 102 103 if ((storeLimit - storeSize) > dirFreeSpace) { 104 String message = "Store limit is " + storeLimit / (1024 * 1024) + " mb, whilst the data directory: " + dir.getAbsolutePath() 105 + " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space"; 106 answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, adapter.toString())); 107 } 108 } 109 110 File tmpDir = brokerService.getTmpDataDirectory(); 111 if (tmpDir != null) { 112 113 String tmpDirPath = tmpDir.getAbsolutePath(); 114 if (!tmpDir.isAbsolute()) { 115 tmpDir = new File(tmpDirPath); 116 } 117 118 long storeSize = usage.getTempUsage().getUsage(); 119 long storeLimit = usage.getTempUsage().getLimit(); 120 while (tmpDir != null && !tmpDir.isDirectory()) { 121 tmpDir = tmpDir.getParentFile(); 122 } 123 124 if (storeLimit != 0) { 125 int val = (int) ((storeSize * 100) / storeLimit); 126 if (val > 90) { 127 answer.add(new HealthStatus("org.apache.activemq.TempStoreLimit", "WARNING", "TempMessage Store size is within " + val 128 + "% of its limit", adapter.toString())); 129 } 130 } 131 } 132 } 133 } 134 135 if (brokerService != null && brokerService.getJobSchedulerStore() != null) { 136 JobSchedulerStore scheduler = brokerService.getJobSchedulerStore(); 137 File dir = scheduler.getDirectory(); 138 if (brokerService.isPersistent()) { 139 SystemUsage usage = brokerService.getSystemUsage(); 140 if (dir != null && usage != null) { 141 String dirPath = dir.getAbsolutePath(); 142 if (!dir.isAbsolute()) { 143 dir = new File(dirPath); 144 } 145 146 while (dir != null && !dir.isDirectory()) { 147 dir = dir.getParentFile(); 148 } 149 long storeSize = scheduler.size(); 150 long storeLimit = usage.getJobSchedulerUsage().getLimit(); 151 long dirFreeSpace = dir.getUsableSpace(); 152 153 if (storeSize != 0 && storeLimit != 0) { 154 int val = (int) ((storeSize * 100) / storeLimit); 155 if (val > 90) { 156 answer.add(new HealthStatus("org.apache.activemq.JobSchedulerLimit", "WARNING", "JobSchedulerMessage Store size is within " + val 157 + "% of its limit", scheduler.toString())); 158 } 159 } 160 161 if ((storeLimit - storeSize) > dirFreeSpace) { 162 String message = "JobSchedulerStore limit is " + storeLimit / (1024 * 1024) + " mb, whilst the data directory: " 163 + dir.getAbsolutePath() + " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space"; 164 answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, scheduler.toString())); 165 } 166 } 167 } 168 } 169 170 StringBuilder currentState = new StringBuilder(); 171 if (answer != null && !answer.isEmpty()) { 172 currentState.append("Getting Worried {"); 173 for (HealthStatus hs : answer) { 174 currentState.append(hs).append(" , "); 175 } 176 currentState.append(" }"); 177 } else { 178 currentState.append("Good"); 179 } 180 181 this.currentState = currentState.toString(); 182 183 return answer; 184 } 185 186 @Override 187 public String healthStatus() throws Exception { 188 // Must invoke healthList in order to update state. 189 healthList(); 190 191 return getCurrentStatus(); 192 } 193 194 /** 195 * @return String representation of the current Broker state 196 */ 197 @Override 198 public String getCurrentStatus() { 199 return this.currentState; 200 } 201}