1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
40
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
129 return preferred > RrdFactory.STEP_SIZE ? preferred : RrdFactory.STEP_SIZE;
130 }
131 }