View Javadoc

1   /**
2    * Copyright (c) 2002-2011 "Neo Technology,"
3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
4    *
5    * This file is part of Neo4j.
6    *
7    * Neo4j is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation, either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.neo4j.server.webadmin.rest;
21  
22  import java.util.Date;
23  
24  import javax.ws.rs.GET;
25  import javax.ws.rs.Path;
26  import javax.ws.rs.PathParam;
27  import javax.ws.rs.core.Context;
28  import javax.ws.rs.core.Response;
29  
30  import org.neo4j.server.rest.repr.OutputFormat;
31  import org.neo4j.server.rrd.RrdFactory;
32  import org.neo4j.server.webadmin.rest.representations.RrdDataRepresentation;
33  import org.neo4j.server.webadmin.rest.representations.ServiceDefinitionRepresentation;
34  import org.rrd4j.ConsolFun;
35  import org.rrd4j.core.FetchRequest;
36  import org.rrd4j.core.RrdDb;
37  
38  /**
39   * This exposes data from an internal round-robin database that tracks various
40   * system KPIs over time.
41   */
42  @Path( MonitorService.ROOT_PATH )
43  public class MonitorService implements AdvertisableService
44  {
45      private final RrdDb rrdDb;
46      private final OutputFormat output;
47  
48      public String getName()
49      {
50          return "monitor";
51      }
52  
53      public String getServerPath()
54      {
55          return ROOT_PATH;
56      }
57  
58      public MonitorService( @Context RrdDb rrdDb, @Context OutputFormat output )
59      {
60          this.rrdDb = rrdDb;
61          this.output = output;
62      }
63  
64      public static final String ROOT_PATH = "server/monitor";
65      public static final String DATA_PATH = "/fetch";
66      public static final String DATA_FROM_PATH = DATA_PATH + "/{start}";
67      public static final String DATA_SPAN_PATH = DATA_PATH + "/{start}/{stop}";
68  
69      public static final long MAX_TIMESPAN = 1000l * 60l * 60l * 24l * 365l * 5;
70      public static final long DEFAULT_TIMESPAN = 1000 * 60 * 60 * 24;
71  
72  
73      @GET
74      public Response getServiceDefinition()
75      {
76          ServiceDefinitionRepresentation sdr = new ServiceDefinitionRepresentation( ROOT_PATH );
77          sdr.resourceTemplate( "data_from", MonitorService.DATA_FROM_PATH );
78          sdr.resourceTemplate( "data_period", MonitorService.DATA_SPAN_PATH );
79          sdr.resourceUri( "latest_data", MonitorService.DATA_PATH );
80  
81          return output.ok( sdr );
82      }
83  
84      @GET
85      @Path( DATA_PATH )
86      public Response getData()
87      {
88          long time = new Date().getTime();
89          return getData( time - DEFAULT_TIMESPAN, time );
90      }
91  
92      @GET
93      @Path( DATA_FROM_PATH )
94      public Response getData( @PathParam( "start" ) long start )
95      {
96          return getData( start, new Date().getTime() );
97      }
98  
99      @GET
100     @Path( DATA_SPAN_PATH )
101     public Response getData( @PathParam( "start" ) long start,
102                              @PathParam( "stop" ) long stop )
103     {
104         if ( start >= stop || ( stop - start ) > MAX_TIMESPAN )
105         {
106             String message = String.format( "Start time must be before stop time, and the total time span can be no bigger than %dms. Time span was %dms.", MAX_TIMESPAN, ( stop - start ) );
107             return output.badRequest( new IllegalArgumentException( message ) );
108         }
109 
110         try
111         {
112 
113             FetchRequest request = rrdDb.createFetchRequest(
114                     ConsolFun.AVERAGE, start, stop,
115                     getResolutionFor( stop - start ) );
116 
117             return output.ok( new RrdDataRepresentation( request.fetchData() ) );
118         } catch ( Exception e )
119         {
120             return output.serverError( e );
121         }
122     }
123 
124     private long getResolutionFor( long timespan )
125     {
126         long preferred = (long)Math.floor( timespan / ( RrdFactory.STEPS_PER_ARCHIVE * 2 ) );
127 
128         // Don't allow resolutions smaller than the actual minimum resolution
129         return preferred > RrdFactory.STEP_SIZE ? preferred : RrdFactory.STEP_SIZE;
130     }
131 }