001/*
002 *  Copyright 2012 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.runtime.plugins.admin.jvmstatus.monitoring.sample;
017
018import java.awt.Color;
019import java.io.IOException;
020import java.util.Date;
021import java.util.Map;
022
023import org.apache.avalon.framework.configuration.Configurable;
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.avalon.framework.logger.LogEnabled;
027import org.apache.avalon.framework.logger.Logger;
028import org.apache.avalon.framework.thread.ThreadSafe;
029import org.apache.commons.lang.StringUtils;
030import org.rrd4j.ConsolFun;
031import org.rrd4j.DsType;
032import org.rrd4j.core.RrdDef;
033import org.rrd4j.core.Sample;
034import org.rrd4j.core.Util;
035import org.rrd4j.graph.RrdGraphConstants;
036import org.rrd4j.graph.RrdGraphDef;
037
038import org.ametys.runtime.i18n.I18nizableText;
039import org.ametys.runtime.plugin.component.PluginAware;
040import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.MonitoringConstants;
041import org.ametys.runtime.plugins.admin.jvmstatus.monitoring.SampleManager;
042
043/**
044 * AbstractSampleManager gives you the infrastructure for easily
045 * deploying a {@link SampleManager}.
046 */
047public abstract class AbstractSampleManager implements SampleManager, MonitoringConstants, ThreadSafe, LogEnabled, Configurable, PluginAware
048{
049    /** Logger available to subclasses. */
050    protected Logger _logger;
051    
052    /** The name of the plugin that has declared this component */
053    protected String _pluginName;
054    /** The name of the feature that has declared this component */
055    protected String _featureName;
056    /** id */
057    protected String _id;
058    /** label */
059    protected I18nizableText _label;
060    /** description */
061    protected I18nizableText _description;
062    
063    @Override
064    public String getId()
065    {
066        return _id;
067    }
068    
069    @Override
070    public I18nizableText getLabel()
071    {
072        return _label;
073    }
074    
075    @Override
076    public I18nizableText getDescription()
077    {
078        return _description;
079    }
080 
081    /* (non-Javadoc)
082     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
083     */
084    @Override
085    public void configure(Configuration configuration) throws ConfigurationException
086    {
087        boolean isLabelI18n = configuration.getChild("label").getAttributeAsBoolean("i18n", false);
088        String label =  configuration.getChild("label").getValue(null);
089        boolean isDescriptionI18n = configuration.getChild("description").getAttributeAsBoolean("i18n", false);
090        String description =  configuration.getChild("description").getValue(null);
091        
092        if (StringUtils.isEmpty(label) || StringUtils.isEmpty(description))
093        {
094            throw new ConfigurationException("Missing <label> or <description>", configuration);
095        }
096        
097        if (isLabelI18n)
098        {
099            _label = new I18nizableText("plugin." + _pluginName, label);
100        }
101        else
102        {
103            _label = new I18nizableText(label);
104        }
105
106        if (isDescriptionI18n)
107        {
108            _description = new I18nizableText("plugin." + _pluginName, description);
109        }
110        else
111        {
112            _description = new I18nizableText(description);
113        }
114    }
115    
116    /* (non-Javadoc)
117     * @see org.ametys.runtime.plugin.component.PluginAware#setPluginInfo(java.lang.String, java.lang.String)
118     */
119    @Override
120    public void setPluginInfo(String pluginName, String featureName, String id)
121    {
122        _pluginName = pluginName;
123        _featureName = featureName;
124        _id = id;
125    }
126    
127    public void enableLogging(Logger logger)
128    {
129        _logger = logger;
130    }
131    
132    public void configureRRDDef(RrdDef rrdDef)
133    {
134        if (_logger.isDebugEnabled())
135        {
136            _logger.debug("Configuring RRD definition for sample manager: " + getId());
137        }
138        
139        rrdDef.setStartTime(new Date());
140        
141        _configureDatasources(rrdDef);
142        
143        // Every minute for 24 hours
144        rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 1, 60 * 24);
145        rrdDef.addArchive(ConsolFun.MAX, 0.5, 1, 60 * 24);
146        // Every 10 minutes for 7 days
147        rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 10, 6 * 24 * 7);
148        rrdDef.addArchive(ConsolFun.MAX, 0.5, 10, 6 * 24 * 7);
149        // Every 2 hours for a month
150        rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 2 * 60, 12 * 30);
151        rrdDef.addArchive(ConsolFun.MAX, 0.5, 2 * 60, 12 * 30);
152        // Every 6 hours for 3 months
153        rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 6 * 60, 4 * 30 * 3);
154        rrdDef.addArchive(ConsolFun.MAX, 0.5, 6 * 60, 4 * 30 * 3);
155        // Every 24 hours for a year
156        rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 24 * 60, 365);
157        rrdDef.addArchive(ConsolFun.MAX, 0.5, 24 * 60, 365);
158        // Every week for 5 years
159        rrdDef.addArchive(ConsolFun.AVERAGE, 0.5, 24 * 60 * 7, 52 * 5);
160        rrdDef.addArchive(ConsolFun.MAX, 0.5, 24 * 60 * 7, 52 * 5);
161    }
162
163    /**
164     * Provides the data sources.
165     * @param rrdDef the Round Robin Database definition.
166     */
167    protected abstract void _configureDatasources(RrdDef rrdDef);
168    
169    /**
170     * Register a new data source where heartbeat property is set internally.
171     * @param rrdDef the Round Robin Database definition.
172     * @param dsName the data source name.
173     * @param dsType the data source type.
174     * @param minValue the minimal acceptable value. Use <code>Double.NaN</code> if unknown.
175     * @param maxValue the maximal acceptable value. Use <code>Double.NaN</code> if unknown.
176     */
177    protected void _registerDatasources(RrdDef rrdDef, String dsName, DsType dsType, double minValue, double maxValue)
178    {
179        rrdDef.addDatasource(dsName, dsType, FEEDING_PERIOD * 2, minValue, maxValue);
180    }
181
182    public Map<String, Object> collect(Sample sample) throws IOException
183    {
184        sample.setTime(Util.getTime());
185        
186        Map<String, Object> collectedValues = _internalCollect(sample);
187        
188        if (_logger.isDebugEnabled())
189        {
190            _logger.debug("Data collected: " + sample.dump());
191        }
192        
193        sample.update();
194        return collectedValues;
195    }
196    
197    /**
198     * Collect data into the Round Robin Database.
199     * @param sample the sample to collect.
200     * @return The collected values for each datasource name.
201     * @throws IOException thrown in case of I/O error.
202     */
203    protected abstract Map<String, Object> _internalCollect(Sample sample) throws IOException;
204
205    /**
206     * Set common graph definition parameters (graph style, ...)
207     * @param graphDef the prepared graph definition.
208     */
209    protected void _setCommonParameters(RrdGraphDef graphDef)
210    {
211        // Common style.
212        graphDef.setColor(RrdGraphConstants.COLOR_BACK, new Color(255, 255, 255));
213        graphDef.setColor(RrdGraphConstants.COLOR_CANVAS, new Color(255, 255, 255));
214        graphDef.setColor(RrdGraphConstants.COLOR_FRAME, new Color(255, 255, 255));
215        graphDef.setColor(RrdGraphConstants.COLOR_MGRID, new Color(128, 128, 128));
216        graphDef.setColor(RrdGraphConstants.COLOR_GRID, new Color(220, 220, 220));
217        graphDef.setColor(RrdGraphConstants.COLOR_SHADEA, new Color(220, 220, 220));
218        graphDef.setColor(RrdGraphConstants.COLOR_SHADEB, new Color(220, 220, 220));
219    }
220    
221    /**
222     * Configure the value range to be displayed.<br>
223     * Default implementation set min value to <code>0</code>.
224     * @param graphDef the graph definition.
225     */
226    protected void _configureValueRange(RrdGraphDef graphDef)
227    {
228        graphDef.setMinValue(0d);
229    }
230
231    /**
232     * Provide the graph title.
233     * @return the graph title.
234     */
235    protected abstract String _getGraphTitle();
236}