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