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     */
017    package org.apache.activemq.broker.jmx;
018    
019    import java.io.File;
020    import java.util.ArrayList;
021    import java.util.List;
022    import java.util.Map;
023    
024    import javax.management.ObjectName;
025    import javax.management.openmbean.CompositeDataSupport;
026    import javax.management.openmbean.CompositeType;
027    import javax.management.openmbean.TabularData;
028    import javax.management.openmbean.TabularDataSupport;
029    import javax.management.openmbean.TabularType;
030    import org.apache.activemq.broker.BrokerService;
031    import org.apache.activemq.broker.scheduler.JobSchedulerStore;
032    import org.apache.activemq.store.PersistenceAdapter;
033    import org.apache.activemq.usage.SystemUsage;
034    
035    public class HealthView implements HealthViewMBean {
036    
037        ManagedRegionBroker broker;
038        String currentState = "Good";
039    
040        public HealthView(ManagedRegionBroker broker) {
041            this.broker = broker;
042        }
043    
044        @Override
045        public TabularData health() throws Exception {
046            OpenTypeSupport.OpenTypeFactory factory = OpenTypeSupport.getFactory(HealthStatus.class);
047            CompositeType ct = factory.getCompositeType();
048            TabularType tt = new TabularType("HealthStatus", "HealthStatus", ct, new String[]{"healthId", "level", "message", "resource"});
049            TabularDataSupport rc = new TabularDataSupport(tt);
050    
051            List<HealthStatus> list = healthList();
052            for (HealthStatus healthStatus : list) {
053                rc.put(new CompositeDataSupport(ct, factory.getFields(healthStatus)));
054            }
055            return rc;
056        }
057    
058        @Override
059        public List<HealthStatus> healthList() throws Exception {
060            List<HealthStatus> answer = new ArrayList<HealthStatus>();
061            Map<ObjectName, DestinationView> queueViews = broker.getQueueViews();
062            for (Map.Entry<ObjectName, DestinationView> entry : queueViews.entrySet()) {
063                DestinationView queue = entry.getValue();
064                if (queue.getConsumerCount() == 0 && queue.getProducerCount() > 0) {
065                    ObjectName key = entry.getKey();
066                    String message = "Queue " + queue.getName() + " has no consumers";
067                    answer.add(new HealthStatus("org.apache.activemq.noConsumer", "WARNING", message, key.toString()));
068                }
069            }
070    
071            /**
072             * Check persistence store directory limits
073             *
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    
088                        while (dir != null && !dir.isDirectory()) {
089                            dir = dir.getParentFile();
090                        }
091                        long storeSize = adapter.size();
092                        long storeLimit = usage.getStoreUsage().getLimit();
093                        long dirFreeSpace = dir.getUsableSpace();
094    
095                        if (storeSize != 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", adapter.toString()));
099                            }
100                        }
101    
102    
103                        if ((storeLimit - storeSize) > dirFreeSpace) {
104                            String message = "Store limit is " + storeLimit / (1024 * 1024) +
105                                    " mb, whilst the data directory: " + dir.getAbsolutePath() +
106                                    " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space";
107                            answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, adapter.toString()));
108                        }
109    
110    
111                    }
112                    File tmpDir = brokerService.getTmpDataDirectory();
113                    if (tmpDir != null) {
114    
115                        String tmpDirPath = tmpDir.getAbsolutePath();
116                        if (!tmpDir.isAbsolute()) {
117                            tmpDir = new File(tmpDirPath);
118                        }
119    
120                        long storeSize = usage.getTempUsage().getUsage();
121                        long storeLimit = usage.getTempUsage().getLimit();
122                        while (tmpDir != null && !tmpDir.isDirectory()) {
123                            tmpDir = tmpDir.getParentFile();
124                        }
125    
126                        int val = (int) ((storeSize * 100) / storeLimit);
127                        if (val > 90) {
128                            answer.add(new HealthStatus("org.apache.activemq.TempStoreLimit", "WARNING", "TempMessage Store size is within " + val + "% of its limit", adapter.toString()));
129                        }
130    
131    
132                    }
133    
134    
135                }
136            }
137    
138            if (brokerService != null && brokerService.getJobSchedulerStore() != null) {
139                JobSchedulerStore scheduler = brokerService.getJobSchedulerStore();
140                File dir = scheduler.getDirectory();
141                if (brokerService.isPersistent()) {
142                    SystemUsage usage = brokerService.getSystemUsage();
143                    if (dir != null && usage != null) {
144                        String dirPath = dir.getAbsolutePath();
145                        if (!dir.isAbsolute()) {
146                            dir = new File(dirPath);
147                        }
148    
149    
150                        while (dir != null && !dir.isDirectory()) {
151                            dir = dir.getParentFile();
152                        }
153                        long storeSize = scheduler.size();
154                        long storeLimit = usage.getJobSchedulerUsage().getLimit();
155                        long dirFreeSpace = dir.getUsableSpace();
156    
157                        if (storeSize != 0) {
158                            int val = (int) ((storeSize * 100) / storeLimit);
159                            if (val > 90) {
160                                answer.add(new HealthStatus("org.apache.activemq.JobSchedulerLimit", "WARNING", "JobSchedulerMessage Store size is within " + val + "% of its limit", scheduler.toString()));
161                            }
162                        }
163    
164    
165                        if ((storeLimit - storeSize) > dirFreeSpace) {
166                            String message = "JobSchedulerStore limit is " + storeLimit / (1024 * 1024) +
167                                    " mb, whilst the data directory: " + dir.getAbsolutePath() +
168                                    " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space";
169                            answer.add(new HealthStatus("org.apache.activemq.FreeDiskSpaceLeft", "WARNING", message, scheduler.toString()));
170                        }
171    
172                    }
173                }
174            }
175    
176        if (answer != null && !answer.isEmpty()){
177             this.currentState = "Feeling Ill {";
178            for (HealthStatus hs: answer){
179                currentState += hs + " , ";
180            }
181            currentState += " }";
182        } else{
183            this.currentState="Good";
184        }
185            return answer;
186        }
187    
188        /**
189         * @return String representation of the current Broker state
190         */
191        @Override
192        public String getCurrentStatus() {
193            return this.currentState;
194        }
195    
196    }