View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.monitoring.reporting;
19  
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Comparator;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.LinkedList;
27  import java.util.List;
28  import java.util.Set;
29  
30  import org.apache.commons.monitoring.Counter;
31  import org.apache.commons.monitoring.Monitor;
32  import org.apache.commons.monitoring.Role;
33  import org.apache.commons.monitoring.StatValue;
34  import org.apache.commons.monitoring.Unit;
35  import org.apache.commons.monitoring.Monitor.Key;
36  import org.apache.commons.monitoring.listeners.Detachable;
37  
38  /**
39   * Render a collection of monitor for reporting
40   *
41   * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
42   */
43  public abstract class AbstractRenderer
44      implements Renderer
45  {
46      private String contentType;
47  
48  
49      protected static final String MONITORS = "monitors";
50  
51      protected static final String ROLES = "roles";
52  
53      public AbstractRenderer( String contentType )
54      {
55          super();
56          this.contentType = contentType;
57      }
58  
59      public void render( Context ctx, Collection<Monitor> monitors, Options options )
60      {
61          int count = 0;
62          prepareRendering( ctx, monitors, options );
63          for ( Monitor monitor : monitors )
64          {
65              if ( options.render( monitor ) )
66              {
67                  if ( count > 0 )
68                  {
69                      hasNext( ctx, Monitor.class );
70                  }
71                  render( ctx, monitor, options );
72                  count++;
73              }
74          }
75      }
76  
77      protected void prepareRendering( Context ctx, Collection<Monitor> monitors, Options options )
78      {
79          ctx.put( ROLES, getRoles( monitors, options ) );
80          ctx.put( MONITORS, monitors );
81      }
82  
83      protected void hasNext( Context ctx, Class<?> type )
84      {
85          // Nop
86      }
87  
88      protected void render( Context ctx, Monitor monitor, Options options, List<String> roles )
89      {
90          render( ctx, monitor, options );
91      }
92  
93      protected void render( Context ctx, Monitor monitor, Options options )
94      {
95          if ( isDetatched( monitor ) )
96          {
97              renderDetached( ctx, (Detachable) monitor, options );
98          }
99          render( ctx, monitor.getKey() );
100         renderStatValues( ctx, monitor, options );
101     }
102 
103     protected boolean isDetatched( Monitor monitor )
104     {
105         return monitor instanceof Detachable && ( (Detachable) monitor ).isDetached();
106     }
107 
108     protected abstract void renderDetached( Context ctx, Detachable detached, Options options );
109 
110     @SuppressWarnings( "unchecked" )
111     protected void renderStatValues( Context ctx, Monitor monitor, Options options )
112     {
113         List<Role> roles = (List<Role>) ctx.get( ROLES );
114         renderStatValues( ctx, monitor, options, roles );
115     }
116 
117     @SuppressWarnings("unchecked")
118     protected void renderStatValues( Context ctx, Monitor monitor, Options options, List<Role> roles )
119     {
120         for ( Iterator<Role> iterator = roles.iterator(); iterator.hasNext(); )
121         {
122             Role role = iterator.next();
123             StatValue value = monitor.getValue( role );
124             if ( value != null )
125             {
126                 render( ctx, value, options );
127             }
128             else
129             {
130                 renderMissingValue( ctx, role );
131             }
132             if ( iterator.hasNext() )
133             {
134                 hasNext( ctx, StatValue.class );
135             }
136         }
137     }
138 
139     /**
140      * Render an expected value not supported by the current monitor
141      *
142      * @param ctx
143      * @param role
144      */
145     @SuppressWarnings("unchecked")
146     protected void renderMissingValue( Context ctx, Role role )
147     {
148         // Nop
149     }
150 
151     protected List<StatValue> getOrderedStatValues( Monitor monitor, Options options )
152     {
153         List<StatValue> values = new LinkedList<StatValue>( monitor.getValues() );
154         for ( Iterator<StatValue> iterator = values.iterator(); iterator.hasNext(); )
155         {
156             StatValue value = (StatValue) iterator.next();
157             if ( !options.renderRole( value.getRole() ) )
158             {
159                 iterator.remove();
160             }
161         }
162         Collections.sort( values, new Comparator<StatValue>()
163         {
164             public int compare( StatValue value1, StatValue value2 )
165             {
166                 return value1.getRole().compareTo( value2.getRole() );
167             }
168         } );
169         return values;
170     }
171 
172     @SuppressWarnings("unchecked")
173     protected void render( Context ctx, StatValue value, Options options )
174     {
175         Role role = value.getRole();
176         if ( value instanceof Counter )
177         {
178             Counter counter = (Counter) value;
179             if ( options.render( role, "hits" ) )
180             {
181                 render( ctx, value, "hits", counter.getHits(), options, 0 );
182             }
183             if ( options.render( role, "sum" ) )
184             {
185                 render( ctx, value, "sum", counter.getSum(), options );
186             }
187         }
188         if ( options.render( role, "min" ) )
189         {
190             render( ctx, value, "min", value.getMin(), options );
191         }
192         if ( options.render( role, "max" ) )
193         {
194             render( ctx, value, "max", value.getMax(), options );
195         }
196         if ( options.render( role, "mean" ) )
197         {
198             render( ctx, value, "mean", value.getMean(), options );
199         }
200         if ( options.render( role, "deviation" ) )
201         {
202             render( ctx, value, "deviation", value.getStandardDeviation(), options, 1 );
203         }
204         if ( options.render( role, "value" ) )
205         {
206             render( ctx, value, "value", value.get(), options, 1 );
207         }
208     }
209 
210     protected abstract void render( Context ctx, Key key );
211 
212     protected void render( Context ctx, StatValue value, String attribute, Number number, Options options )
213     {
214         render( ctx, value, attribute, number, options, 1 );
215     }
216 
217     /**
218      * Render a StatValue attribute
219      *
220      * @param ctx output
221      * @param value the StatValue that hold data to be rendered
222      * @param attribute the StatValue attribute name to be rendered
223      * @param number the the StatValue attribute value to be rendered
224      * @param ratio the ratio between attribute unit and statValue unit (in
225      * power of 10)
226      * @param options the rendering options
227      */
228     protected void render( Context ctx, StatValue value, String attribute, Number number, Options options, int ratio )
229     {
230         if ( number instanceof Double )
231         {
232             renderInternal( ctx, value, attribute, number.doubleValue(), options, ratio );
233         }
234         else
235         {
236             renderInternal( ctx, value, attribute, number.longValue(), options, ratio );
237         }
238     }
239 
240     private void renderInternal( Context ctx, StatValue value, String attribute, long l, Options options, int ratio )
241     {
242         Unit unit = options.unitFor( value.getRole() );
243         if ( unit != null )
244         {
245             while ( ratio-- > 0 )
246             {
247                 l = l / unit.getScale();
248             }
249         }
250 
251         ctx.print( options.getNumberFormat().format( l ) );
252     }
253 
254     private void renderInternal( Context ctx, StatValue value, String attribute, double d, Options options, int ratio )
255     {
256         if ( Double.isNaN( d ) )
257         {
258             renderNaN( ctx );
259             return;
260         }
261         Unit unit = options.unitFor( value.getRole() );
262         if ( unit != null )
263         {
264             while ( ratio-- > 0 )
265             {
266                 d = d / unit.getScale();
267             }
268         }
269 
270         ctx.print( options.getDecimalFormat().format( d ) );
271     }
272 
273     protected void renderNaN( Context ctx )
274     {
275         ctx.print( "-" );
276     }
277 
278     /**
279      * @param monitors
280      * @return
281      */
282     @SuppressWarnings("unchecked")
283     protected List<Role> getRoles( Collection<Monitor> monitors, Options options )
284     {
285         Set<Role> roles = new HashSet<Role>();
286         for ( Monitor monitor : monitors )
287         {
288             if ( options.render( monitor ) )
289             {
290                 for ( Role role : monitor.getRoles() )
291                 {
292                     if ( options.renderRole( role ) )
293                     {
294                         roles.add( role );
295                     }
296                 }
297             }
298         }
299         List<Role> sorted = new ArrayList<Role>( roles );
300         Collections.<Role>sort( sorted );
301         return sorted;
302     }
303 
304     public String getContentType()
305     {
306         return contentType;
307     }
308 }