1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 package org.apache.hadoop.lib.service.instrumentation;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25 
26 import java.io.StringWriter;
27 import java.util.Arrays;
28 import java.util.Map;
29 import java.util.concurrent.atomic.AtomicInteger;
30 
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.lib.server.Server;
33 import org.apache.hadoop.lib.service.Instrumentation;
34 import org.apache.hadoop.lib.service.scheduler.SchedulerService;
35 import org.apache.hadoop.test.HTestCase;
36 import org.apache.hadoop.test.TestDir;
37 import org.apache.hadoop.test.TestDirHelper;
38 import org.apache.hadoop.util.StringUtils;
39 import org.apache.hadoop.util.Time;
40 import org.json.simple.JSONObject;
41 import org.json.simple.parser.JSONParser;
42 import org.junit.Test;
43 
44 public class TestInstrumentationService extends HTestCase {
45 
46   @Override
getWaitForRatio()47   protected float getWaitForRatio() {
48     return 1;
49   }
50 
51   @Test
cron()52   public void cron() {
53     InstrumentationService.Cron cron = new InstrumentationService.Cron();
54     assertEquals(cron.start, 0);
55     assertEquals(cron.lapStart, 0);
56     assertEquals(cron.own, 0);
57     assertEquals(cron.total, 0);
58     long begin = Time.now();
59     assertEquals(cron.start(), cron);
60     assertEquals(cron.start(), cron);
61     assertEquals(cron.start, begin, 20);
62     assertEquals(cron.start, cron.lapStart);
63     sleep(100);
64     assertEquals(cron.stop(), cron);
65     long end = Time.now();
66     long delta = end - begin;
67     assertEquals(cron.own, delta, 20);
68     assertEquals(cron.total, 0);
69     assertEquals(cron.lapStart, 0);
70     sleep(100);
71     long reStart = Time.now();
72     cron.start();
73     assertEquals(cron.start, begin, 20);
74     assertEquals(cron.lapStart, reStart, 20);
75     sleep(100);
76     cron.stop();
77     long reEnd = Time.now();
78     delta += reEnd - reStart;
79     assertEquals(cron.own, delta, 20);
80     assertEquals(cron.total, 0);
81     assertEquals(cron.lapStart, 0);
82     cron.end();
83     assertEquals(cron.total, reEnd - begin, 20);
84 
85     try {
86       cron.start();
87       fail();
88     } catch (IllegalStateException ex) {
89     } catch (Exception ex) {
90       fail();
91     }
92 
93     try {
94       cron.stop();
95       fail();
96     } catch (IllegalStateException ex) {
97     } catch (Exception ex) {
98       fail();
99     }
100   }
101 
102   @Test
timer()103   public void timer() throws Exception {
104     InstrumentationService.Timer timer = new InstrumentationService.Timer(2);
105     InstrumentationService.Cron cron = new InstrumentationService.Cron();
106 
107     long ownStart;
108     long ownEnd;
109     long totalStart;
110     long totalEnd;
111     long ownDelta;
112     long totalDelta;
113     long avgTotal;
114     long avgOwn;
115 
116     cron.start();
117     ownStart = Time.now();
118     totalStart = ownStart;
119     ownDelta = 0;
120     sleep(100);
121 
122     cron.stop();
123     ownEnd = Time.now();
124     ownDelta += ownEnd - ownStart;
125     sleep(100);
126 
127     cron.start();
128     ownStart = Time.now();
129     sleep(100);
130 
131     cron.stop();
132     ownEnd = Time.now();
133     ownDelta += ownEnd - ownStart;
134     totalEnd = ownEnd;
135     totalDelta = totalEnd - totalStart;
136 
137     avgTotal = totalDelta;
138     avgOwn = ownDelta;
139 
140     timer.addCron(cron);
141     long[] values = timer.getValues();
142     assertEquals(values[InstrumentationService.Timer.LAST_TOTAL], totalDelta, 20);
143     assertEquals(values[InstrumentationService.Timer.LAST_OWN], ownDelta, 20);
144     assertEquals(values[InstrumentationService.Timer.AVG_TOTAL], avgTotal, 20);
145     assertEquals(values[InstrumentationService.Timer.AVG_OWN], avgOwn, 20);
146 
147     cron = new InstrumentationService.Cron();
148 
149     cron.start();
150     ownStart = Time.now();
151     totalStart = ownStart;
152     ownDelta = 0;
153     sleep(200);
154 
155     cron.stop();
156     ownEnd = Time.now();
157     ownDelta += ownEnd - ownStart;
158     sleep(200);
159 
160     cron.start();
161     ownStart = Time.now();
162     sleep(200);
163 
164     cron.stop();
165     ownEnd = Time.now();
166     ownDelta += ownEnd - ownStart;
167     totalEnd = ownEnd;
168     totalDelta = totalEnd - totalStart;
169 
170     avgTotal = (avgTotal * 1 + totalDelta) / 2;
171     avgOwn = (avgOwn * 1 + ownDelta) / 2;
172 
173     timer.addCron(cron);
174     values = timer.getValues();
175     assertEquals(values[InstrumentationService.Timer.LAST_TOTAL], totalDelta, 20);
176     assertEquals(values[InstrumentationService.Timer.LAST_OWN], ownDelta, 20);
177     assertEquals(values[InstrumentationService.Timer.AVG_TOTAL], avgTotal, 20);
178     assertEquals(values[InstrumentationService.Timer.AVG_OWN], avgOwn, 20);
179 
180     avgTotal = totalDelta;
181     avgOwn = ownDelta;
182 
183     cron = new InstrumentationService.Cron();
184 
185     cron.start();
186     ownStart = Time.now();
187     totalStart = ownStart;
188     ownDelta = 0;
189     sleep(300);
190 
191     cron.stop();
192     ownEnd = Time.now();
193     ownDelta += ownEnd - ownStart;
194     sleep(300);
195 
196     cron.start();
197     ownStart = Time.now();
198     sleep(300);
199 
200     cron.stop();
201     ownEnd = Time.now();
202     ownDelta += ownEnd - ownStart;
203     totalEnd = ownEnd;
204     totalDelta = totalEnd - totalStart;
205 
206     avgTotal = (avgTotal * 1 + totalDelta) / 2;
207     avgOwn = (avgOwn * 1 + ownDelta) / 2;
208 
209     cron.stop();
210     timer.addCron(cron);
211     values = timer.getValues();
212     assertEquals(values[InstrumentationService.Timer.LAST_TOTAL], totalDelta, 20);
213     assertEquals(values[InstrumentationService.Timer.LAST_OWN], ownDelta, 20);
214     assertEquals(values[InstrumentationService.Timer.AVG_TOTAL], avgTotal, 20);
215     assertEquals(values[InstrumentationService.Timer.AVG_OWN], avgOwn, 20);
216 
217     JSONObject json = (JSONObject) new JSONParser().parse(timer.toJSONString());
218     assertEquals(json.size(), 4);
219     assertEquals(json.get("lastTotal"), values[InstrumentationService.Timer.LAST_TOTAL]);
220     assertEquals(json.get("lastOwn"), values[InstrumentationService.Timer.LAST_OWN]);
221     assertEquals(json.get("avgTotal"), values[InstrumentationService.Timer.AVG_TOTAL]);
222     assertEquals(json.get("avgOwn"), values[InstrumentationService.Timer.AVG_OWN]);
223 
224     StringWriter writer = new StringWriter();
225     timer.writeJSONString(writer);
226     writer.close();
227     json = (JSONObject) new JSONParser().parse(writer.toString());
228     assertEquals(json.size(), 4);
229     assertEquals(json.get("lastTotal"), values[InstrumentationService.Timer.LAST_TOTAL]);
230     assertEquals(json.get("lastOwn"), values[InstrumentationService.Timer.LAST_OWN]);
231     assertEquals(json.get("avgTotal"), values[InstrumentationService.Timer.AVG_TOTAL]);
232     assertEquals(json.get("avgOwn"), values[InstrumentationService.Timer.AVG_OWN]);
233   }
234 
235   @Test
sampler()236   public void sampler() throws Exception {
237     final long value[] = new long[1];
238     Instrumentation.Variable<Long> var = new Instrumentation.Variable<Long>() {
239       @Override
240       public Long getValue() {
241         return value[0];
242       }
243     };
244 
245     InstrumentationService.Sampler sampler = new InstrumentationService.Sampler();
246     sampler.init(4, var);
247     assertEquals(sampler.getRate(), 0f, 0.0001);
248     sampler.sample();
249     assertEquals(sampler.getRate(), 0f, 0.0001);
250     value[0] = 1;
251     sampler.sample();
252     assertEquals(sampler.getRate(), (0d + 1) / 2, 0.0001);
253     value[0] = 2;
254     sampler.sample();
255     assertEquals(sampler.getRate(), (0d + 1 + 2) / 3, 0.0001);
256     value[0] = 3;
257     sampler.sample();
258     assertEquals(sampler.getRate(), (0d + 1 + 2 + 3) / 4, 0.0001);
259     value[0] = 4;
260     sampler.sample();
261     assertEquals(sampler.getRate(), (4d + 1 + 2 + 3) / 4, 0.0001);
262 
263     JSONObject json = (JSONObject) new JSONParser().parse(sampler.toJSONString());
264     assertEquals(json.size(), 2);
265     assertEquals(json.get("sampler"), sampler.getRate());
266     assertEquals(json.get("size"), 4L);
267 
268     StringWriter writer = new StringWriter();
269     sampler.writeJSONString(writer);
270     writer.close();
271     json = (JSONObject) new JSONParser().parse(writer.toString());
272     assertEquals(json.size(), 2);
273     assertEquals(json.get("sampler"), sampler.getRate());
274     assertEquals(json.get("size"), 4L);
275   }
276 
277   @Test
variableHolder()278   public void variableHolder() throws Exception {
279     InstrumentationService.VariableHolder<String> variableHolder =
280       new InstrumentationService.VariableHolder<String>();
281 
282     variableHolder.var = new Instrumentation.Variable<String>() {
283       @Override
284       public String getValue() {
285         return "foo";
286       }
287     };
288 
289     JSONObject json = (JSONObject) new JSONParser().parse(variableHolder.toJSONString());
290     assertEquals(json.size(), 1);
291     assertEquals(json.get("value"), "foo");
292 
293     StringWriter writer = new StringWriter();
294     variableHolder.writeJSONString(writer);
295     writer.close();
296     json = (JSONObject) new JSONParser().parse(writer.toString());
297     assertEquals(json.size(), 1);
298     assertEquals(json.get("value"), "foo");
299   }
300 
301   @Test
302   @TestDir
303   @SuppressWarnings("unchecked")
service()304   public void service() throws Exception {
305     String dir = TestDirHelper.getTestDir().getAbsolutePath();
306     String services = StringUtils.join(",", Arrays.asList(InstrumentationService.class.getName()));
307     Configuration conf = new Configuration(false);
308     conf.set("server.services", services);
309     Server server = new Server("server", dir, dir, dir, dir, conf);
310     server.init();
311 
312     Instrumentation instrumentation = server.get(Instrumentation.class);
313     assertNotNull(instrumentation);
314     instrumentation.incr("g", "c", 1);
315     instrumentation.incr("g", "c", 2);
316     instrumentation.incr("g", "c1", 2);
317 
318     Instrumentation.Cron cron = instrumentation.createCron();
319     cron.start();
320     sleep(100);
321     cron.stop();
322     instrumentation.addCron("g", "t", cron);
323     cron = instrumentation.createCron();
324     cron.start();
325     sleep(200);
326     cron.stop();
327     instrumentation.addCron("g", "t", cron);
328 
329     Instrumentation.Variable<String> var = new Instrumentation.Variable<String>() {
330       @Override
331       public String getValue() {
332         return "foo";
333       }
334     };
335     instrumentation.addVariable("g", "v", var);
336 
337     Instrumentation.Variable<Long> varToSample = new Instrumentation.Variable<Long>() {
338       @Override
339       public Long getValue() {
340         return 1L;
341       }
342     };
343     instrumentation.addSampler("g", "s", 10, varToSample);
344 
345     Map<String, ?> snapshot = instrumentation.getSnapshot();
346     assertNotNull(snapshot.get("os-env"));
347     assertNotNull(snapshot.get("sys-props"));
348     assertNotNull(snapshot.get("jvm"));
349     assertNotNull(snapshot.get("counters"));
350     assertNotNull(snapshot.get("timers"));
351     assertNotNull(snapshot.get("variables"));
352     assertNotNull(snapshot.get("samplers"));
353     assertNotNull(((Map<String, String>) snapshot.get("os-env")).get("PATH"));
354     assertNotNull(((Map<String, String>) snapshot.get("sys-props")).get("java.version"));
355     assertNotNull(((Map<String, ?>) snapshot.get("jvm")).get("free.memory"));
356     assertNotNull(((Map<String, ?>) snapshot.get("jvm")).get("max.memory"));
357     assertNotNull(((Map<String, ?>) snapshot.get("jvm")).get("total.memory"));
358     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("counters")).get("g"));
359     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("timers")).get("g"));
360     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("variables")).get("g"));
361     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("samplers")).get("g"));
362     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("counters")).get("g").get("c"));
363     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("counters")).get("g").get("c1"));
364     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("timers")).get("g").get("t"));
365     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("variables")).get("g").get("v"));
366     assertNotNull(((Map<String, Map<String, Object>>) snapshot.get("samplers")).get("g").get("s"));
367 
368     StringWriter writer = new StringWriter();
369     JSONObject.writeJSONString(snapshot, writer);
370     writer.close();
371     server.destroy();
372   }
373 
374   @Test
375   @TestDir
376   @SuppressWarnings("unchecked")
sampling()377   public void sampling() throws Exception {
378     String dir = TestDirHelper.getTestDir().getAbsolutePath();
379     String services = StringUtils.join(",", Arrays.asList(InstrumentationService.class.getName(),
380                                                           SchedulerService.class.getName()));
381     Configuration conf = new Configuration(false);
382     conf.set("server.services", services);
383     Server server = new Server("server", dir, dir, dir, dir, conf);
384     server.init();
385     Instrumentation instrumentation = server.get(Instrumentation.class);
386 
387     final AtomicInteger count = new AtomicInteger();
388 
389     Instrumentation.Variable<Long> varToSample = new Instrumentation.Variable<Long>() {
390       @Override
391       public Long getValue() {
392         return (long) count.incrementAndGet();
393       }
394     };
395     instrumentation.addSampler("g", "s", 10, varToSample);
396 
397     sleep(2000);
398     int i = count.get();
399     assertTrue(i > 0);
400 
401     Map<String, Map<String, ?>> snapshot = instrumentation.getSnapshot();
402     Map<String, Map<String, Object>> samplers = (Map<String, Map<String, Object>>) snapshot.get("samplers");
403     InstrumentationService.Sampler sampler = (InstrumentationService.Sampler) samplers.get("g").get("s");
404     assertTrue(sampler.getRate() > 0);
405 
406     server.destroy();
407   }
408 
409 }
410