001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     * 
010     *      http://www.apache.org/licenses/LICENSE-2.0
011     * 
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.oozie.service;
019    
020    import org.apache.oozie.util.Instrumentation;
021    import org.apache.oozie.util.XLog;
022    import org.apache.oozie.ErrorCode;
023    
024    import java.util.Map;
025    
026    
027    /**
028     * This service provides an {@link Instrumentation} instance configured to support samplers. <p/> This service depends
029     * on the {@link SchedulerService}. <p/> The {@link #CONF_LOGGING_INTERVAL} configuration property indicates how often
030     * snapshots of the instrumentation should be logged.
031     */
032    public class InstrumentationService implements Service {
033        private static final String JVM_INSTRUMENTATION_GROUP = "jvm";
034    
035        public static final String CONF_PREFIX = Service.CONF_PREFIX + "InstrumentationService.";
036    
037        public static final String CONF_LOGGING_INTERVAL = CONF_PREFIX + "logging.interval";
038    
039        private final XLog log = XLog.getLog("oozieinstrumentation");
040    
041        private Instrumentation instrumentation;
042    
043        /**
044         * Initialize the instrumentation service.
045         *
046         * @param services services instance.
047         */
048        public void init(Services services) throws ServiceException {
049            instrumentation = new Instrumentation();
050            log.info("*********** Startup ***********");
051            log.info("Java System Properties: {E}{0}", mapToString(instrumentation.getJavaSystemProperties()));
052            log.info("OS Env: {E}{0}", mapToString(instrumentation.getOSEnv()));
053            SchedulerService schedulerService = services.get(SchedulerService.class);
054            if (schedulerService != null) {
055                instrumentation.setScheduler(schedulerService.getScheduler());
056                int interval = services.getConf().getInt(CONF_LOGGING_INTERVAL, 60);
057                if (interval > 0) {
058                    Runnable instrumentationLogger = new Runnable() {
059                        public void run() {
060                            try {
061                                log.info("\n" + instrumentation.toString());
062                            }
063                            catch (Throwable ex) {
064                                log.warn("Instrumentation logging error", ex);
065                            }
066                        }
067                    };
068                    schedulerService.schedule(instrumentationLogger, interval, interval, SchedulerService.Unit.SEC);
069                }
070            }
071            else {
072                throw new ServiceException(ErrorCode.E0100, getClass().getName(), "SchedulerService unavailable");
073            }
074            instrumentation.addVariable(JVM_INSTRUMENTATION_GROUP, "free.memory", new Instrumentation.Variable<Long>() {
075                public Long getValue() {
076                    return Runtime.getRuntime().freeMemory();
077                }
078            });
079            instrumentation.addVariable(JVM_INSTRUMENTATION_GROUP, "max.memory", new Instrumentation.Variable<Long>() {
080                public Long getValue() {
081                    return Runtime.getRuntime().maxMemory();
082                }
083            });
084            instrumentation.addVariable(JVM_INSTRUMENTATION_GROUP, "total.memory", new Instrumentation.Variable<Long>() {
085                public Long getValue() {
086                    return Runtime.getRuntime().totalMemory();
087                }
088            });
089        }
090    
091        private String mapToString(Map<String, String> map) {
092            String E = System.getProperty("line.separator");
093            StringBuilder sb = new StringBuilder();
094            for (Map.Entry<String, String> entry : map.entrySet()) {
095                sb.append("    ").append(entry.getKey()).append(" = ").append(entry.getValue()).append(E);
096            }
097            return sb.toString();
098        }
099    
100        /**
101         * Destroy the instrumentation service.
102         */
103        public void destroy() {
104            instrumentation = null;
105        }
106    
107        /**
108         * Return the public interface for instrumentation service.
109         *
110         * @return {@link InstrumentationService}.
111         */
112        public Class<? extends Service> getInterface() {
113            return InstrumentationService.class;
114        }
115    
116        /**
117         * Return the instrumentation instance used by the service.
118         *
119         * @return the instrumentation instance.
120         */
121        public Instrumentation get() {
122            return instrumentation;
123        }
124    
125    }