Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (c) 2010 Yahoo! Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/
package org.apache.oozie.util;
import org.apache.hadoop.conf.Configuration;
import org.apache.oozie.service.ConfigurationService;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Instrumentation framework that supports Timers, Counters, Variables and Sampler instrumentation elements. All
* instrumentation elements have a group and a name.
*/
public class Instrumentation {
private ScheduledExecutorService scheduler;
private Lock counterLock;
private Lock timerLock;
private Lock variableLock;
private Lock samplerLock;
private Configuration configuration;
private Map>> all;
private Map>> counters;
private Map>> timers;
private Map>> variables;
private Map>> samplers;
/**
* Instrumentation constructor.
*/
@SuppressWarnings("unchecked")
public Instrumentation() {
counterLock = new ReentrantLock();
timerLock = new ReentrantLock();
variableLock = new ReentrantLock();
samplerLock = new ReentrantLock();
all = new LinkedHashMap>>();
counters = new ConcurrentHashMap>>();
timers = new ConcurrentHashMap>>();
variables = new ConcurrentHashMap>>();
samplers = new ConcurrentHashMap>>();
all.put("variables", (Map>) (Object) variables);
all.put("samplers", (Map>) (Object) samplers);
all.put("counters", (Map>) (Object) counters);
all.put("timers", (Map>) (Object) timers);
}
/**
* Set the scheduler instance to handle the samplers.
*
* @param scheduler scheduler instance.
*/
public void setScheduler(ScheduledExecutorService scheduler) {
this.scheduler = scheduler;
}
/**
* Cron is a stopwatch that can be started/stopped several times. This class is not thread safe, it does not
* need to be. It keeps track of the total time (first start to last stop) and the running time (total time
* minus the stopped intervals). Once a Cron is complete it must be added to the corresponding group/name in a
* Instrumentation instance.
*/
public static class Cron {
private long start;
private long end;
private long lapStart;
private long own;
private long total;
private boolean running;
/**
* Creates new Cron, stopped, in zero.
*/
public Cron() {
running = false;
}
/**
* Start the cron. It cannot be already started.
*/
public void start() {
if (!running) {
if (lapStart == 0) {
lapStart = System.currentTimeMillis();
if (start == 0) {
start = lapStart;
end = start;
}
}
running = true;
}
}
/**
* Stops the cron. It cannot be already stopped.
*/
public void stop() {
if (running) {
end = System.currentTimeMillis();
if (start == 0) {
start = end;
}
total = end - start;
if (lapStart > 0) {
own += end - lapStart;
lapStart = 0;
}
running = false;
}
}
/**
* Return the start time of the cron. It must be stopped.
*
* @return the start time of the cron.
*/
public long getStart() {
if (running) {
throw new IllegalStateException("Timer running");
}
return start;
}
/**
* Return the end time of the cron. It must be stopped.
*
* @return the end time of the cron.
*/
public long getEnd() {
if (running) {
throw new IllegalStateException("Timer running");
}
return end;
}
/**
* Return the total time of the cron. It must be stopped.
*
* @return the total time of the cron.
*/
public long getTotal() {
if (running) {
throw new IllegalStateException("Timer running");
}
return total;
}
/**
* Return the own time of the cron. It must be stopped.
*
* @return the own time of the cron.
*/
public long getOwn() {
if (running) {
throw new IllegalStateException("Timer running");
}
return own;
}
}
/**
* Gives access to a snapshot of an Instrumentation element (Counter, Timer). Instrumentation element snapshots
* are returned by the {@link Instrumentation#getCounters()} and {@link Instrumentation#getTimers()} ()} methods.
*/
public interface Element {
/**
* Return the snapshot value of the Intrumentation element.
*
* @return the snapshot value of the Intrumentation element.
*/
T getValue();
}
/**
* Counter Instrumentation element.
*/
private static class Counter extends AtomicLong implements Element {
/**
* Return the counter snapshot.
*
* @return the counter snapshot.
*/
public Long getValue() {
return get();
}
/**
* Return the String representation of the counter value.
*
* @return the String representation of the counter value.
*/
public String toString() {
return Long.toString(get());
}
}
/**
* Timer Instrumentation element.
*/
public static class Timer implements Element {
Lock lock = new ReentrantLock();
private long ownTime;
private long totalTime;
private long ticks;
private long ownSquareTime;
private long totalSquareTime;
private long ownMinTime;
private long ownMaxTime;
private long totalMinTime;
private long totalMaxTime;
/**
* Timer constructor. It is project private for test purposes.
*/
Timer() {
}
/**
* Return the String representation of the timer value.
*
* @return the String representation of the timer value.
*/
public String toString() {
return XLog.format("ticks[{0}] totalAvg[{1}] ownAvg[{2}]", ticks, getTotalAvg(), getOwnAvg());
}
/**
* Return the timer snapshot.
*
* @return the timer snapshot.
*/
public Timer getValue() {
try {
lock.lock();
Timer timer = new Timer();
timer.ownTime = ownTime;
timer.totalTime = totalTime;
timer.ticks = ticks;
timer.ownSquareTime = ownSquareTime;
timer.totalSquareTime = totalSquareTime;
timer.ownMinTime = ownMinTime;
timer.ownMaxTime = ownMaxTime;
timer.totalMinTime = totalMinTime;
timer.totalMaxTime = totalMaxTime;
return timer;
}
finally {
lock.unlock();
}
}
/**
* Add a cron to a timer. It is project private for test purposes.
*
* @param cron Cron to add.
*/
void addCron(Cron cron) {
try {
lock.lock();
long own = cron.getOwn();
long total = cron.getTotal();
ownTime += own;
totalTime += total;
ticks++;
ownSquareTime += own * own;
totalSquareTime += total * total;
if (ticks == 1) {
ownMinTime = own;
ownMaxTime = own;
totalMinTime = total;
totalMaxTime = total;
}
else {
ownMinTime = Math.min(ownMinTime, own);
ownMaxTime = Math.max(ownMaxTime, own);
totalMinTime = Math.min(totalMinTime, total);
totalMaxTime = Math.max(totalMaxTime, total);
}
}
finally {
lock.unlock();
}
}
/**
* Return the own accumulated computing time by the timer.
*
* @return own accumulated computing time by the timer.
*/
public long getOwn() {
return ownTime;
}
/**
* Return the total accumulated computing time by the timer.
*
* @return total accumulated computing time by the timer.
*/
public long getTotal() {
return totalTime;
}
/**
* Return the number of times a cron was added to the timer.
*
* @return the number of times a cron was added to the timer.
*/
public long getTicks() {
return ticks;
}
/**
* Return the sum of the square own times. It can be used to calculate the standard deviation.
*
* @return the sum of the square own timer.
*/
public long getOwnSquareSum() {
return ownSquareTime;
}
/**
* Return the sum of the square total times. It can be used to calculate the standard deviation.
*
* @return the sum of the square own timer.
*/
public long getTotalSquareSum() {
return totalSquareTime;
}
/**
* Returns the own minimum time.
*
* @return the own minimum time.
*/
public long getOwnMin() {
return ownMinTime;
}
/**
* Returns the own maximum time.
*
* @return the own maximum time.
*/
public long getOwnMax() {
return ownMaxTime;
}
/**
* Returns the total minimum time.
*
* @return the total minimum time.
*/
public long getTotalMin() {
return totalMinTime;
}
/**
* Returns the total maximum time.
*
* @return the total maximum time.
*/
public long getTotalMax() {
return totalMaxTime;
}
/**
* Returns the own average time.
*
* @return the own average time.
*/
public long getOwnAvg() {
return (ticks != 0) ? ownTime / ticks : 0;
}
/**
* Returns the total average time.
*
* @return the total average time.
*/
public long getTotalAvg() {
return (ticks != 0) ? totalTime / ticks : 0;
}
/**
* Returns the total time standard deviation.
*
* @return the total time standard deviation.
*/
public double getTotalStdDev() {
return evalStdDev(ticks, totalTime, totalSquareTime);
}
/**
* Returns the own time standard deviation.
*
* @return the own time standard deviation.
*/
public double getOwnStdDev() {
return evalStdDev(ticks, ownTime, ownSquareTime);
}
private double evalStdDev(long n, long sn, long ssn) {
return (n < 2) ? -1 : Math.sqrt((n * ssn - sn * sn) / (n * (n - 1)));
}
}
/**
* Add a cron to an instrumentation timer. The timer is created if it does not exists. This method is thread
* safe.
*
* @param group timer group.
* @param name timer name.
* @param cron cron to add to the timer.
*/
public void addCron(String group, String name, Cron cron) {
Map> map = timers.get(group);
if (map == null) {
try {
timerLock.lock();
map = timers.get(group);
if (map == null) {
map = new HashMap>();
timers.put(group, map);
}
}
finally {
timerLock.unlock();
}
}
Timer timer = (Timer) map.get(name);
if (timer == null) {
try {
timerLock.lock();
timer = (Timer) map.get(name);
if (timer == null) {
timer = new Timer();
map.put(name, timer);
}
}
finally {
timerLock.unlock();
}
}
timer.addCron(cron);
}
/**
* Increment an instrumentation counter. The counter is created if it does not exists. This method is thread
* safe.
*
* @param group counter group.
* @param name counter name.
* @param count increment to add to the counter.
*/
public void incr(String group, String name, long count) {
Map> map = counters.get(group);
if (map == null) {
try {
counterLock.lock();
map = counters.get(group);
if (map == null) {
map = new HashMap>();
counters.put(group, map);
}
}
finally {
counterLock.unlock();
}
}
Counter counter = (Counter) map.get(name);
if (counter == null) {
try {
counterLock.lock();
counter = (Counter) map.get(name);
if (counter == null) {
counter = new Counter();
map.put(name, counter);
}
}
finally {
counterLock.unlock();
}
}
counter.addAndGet(count);
}
/**
* Interface for instrumentation variables. For example a the database service could expose the number of
* currently active connections.
*/
public interface Variable extends Element {
}
/**
* Add an instrumentation variable. The variable must not exist. This method is thread safe.
*
* @param group counter group.
* @param name counter name.
* @param variable variable to add.
*/
@SuppressWarnings("unchecked")
public void addVariable(String group, String name, Variable variable) {
Map> map = variables.get(group);
if (map == null) {
try {
variableLock.lock();
map = variables.get(group);
if (map == null) {
map = new HashMap>();
variables.put(group, map);
}
}
finally {
variableLock.unlock();
}
}
if (map.containsKey(name)) {
throw new RuntimeException(XLog.format("Variable group=[{0}] name=[{1}] already defined", group, name));
}
map.put(name, variable);
}
/**
* Set the system configuration.
*
* @param configuration system configuration.
*/
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
/**
* Return the JVM system properties.
*
* @return JVM system properties.
*/
@SuppressWarnings("unchecked")
public Map getJavaSystemProperties() {
return (Map) (Object) System.getProperties();
}
/**
* Return the OS environment used to start Oozie.
*
* @return the OS environment used to start Oozie.
*/
public Map getOSEnv() {
return System.getenv();
}
/**
* Return the current system configuration as a Map.
*
* @return the current system configuration as a Map.
*/
public Map getConfiguration() {
final Configuration maskedConf = ConfigurationService.maskPasswords(configuration);
return new Map() {
public int size() {
return maskedConf.size();
}
public boolean isEmpty() {
return maskedConf.size() == 0;
}
public boolean containsKey(Object o) {
return maskedConf.get((String) o) != null;
}
public boolean containsValue(Object o) {
throw new UnsupportedOperationException();
}
public String get(Object o) {
return maskedConf.get((String) o);
}
public String put(String s, String s1) {
throw new UnsupportedOperationException();
}
public String remove(Object o) {
throw new UnsupportedOperationException();
}
public void putAll(Map extends String, ? extends String> map) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
public Set keySet() {
Set set = new LinkedHashSet();
for (Entry entry : maskedConf) {
set.add(entry.getKey());
}
return set;
}
public Collection values() {
Set set = new LinkedHashSet();
for (Entry entry : maskedConf) {
set.add(entry.getValue());
}
return set;
}
public Set> entrySet() {
Set> set = new LinkedHashSet>();
for (Entry entry : maskedConf) {
set.add(entry);
}
return set;
}
};
}
/**
* Return all the counters. This method is thread safe. The counters are live. The counter value is a
* snapshot at the time the {@link Instrumentation.Element#getValue()} is invoked.
*
* @return all counters.
*/
public Map>> getCounters() {
return counters;
}
/**
* Return all the timers. This method is thread safe. The timers are live. Once a timer is obtained, all
* its values are consistent (they are snapshot at the time the {@link Instrumentation.Element#getValue()} is
* invoked.
*
* @return all counters.
*/
public Map>> getTimers() {
return timers;
}
/**
* Return all the variables. This method is thread safe. The variables are live. The variable value is a
* snapshot at the time the {@link Instrumentation.Element#getValue()} is invoked.
*
* @return all counters.
*/
public Map>> getVariables() {
return variables;
}
/**
* Return a map containing all variables, counters and timers.
*
* @return a map containing all variables, counters and timers.
*/
public Map>> getAll() {
return all;
}
/**
* Return the string representation of the instrumentation.
*
* @return the string representation of the instrumentation.
*/
public String toString() {
String E = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder(4096);
for (String element : all.keySet()) {
sb.append(element).append(':').append(E);
List groups = new ArrayList(all.get(element).keySet());
Collections.sort(groups);
for (String group : groups) {
sb.append(" ").append(group).append(':').append(E);
List names = new ArrayList(all.get(element).get(group).keySet());
Collections.sort(names);
for (String name : names) {
sb.append(" ").append(name).append(": ").append(((Element) all.get(element).
get(group).get(name)).getValue()).append(E);
}
}
}
return sb.toString();
}
private static class Sampler implements Element, Runnable {
private Lock lock = new ReentrantLock();
private int samplingInterval;
private Variable variable;
private long[] values;
private int current;
private long valuesSum;
private double rate;
public Sampler(int samplingPeriod, int samplingInterval, Variable variable) {
this.samplingInterval = samplingInterval;
this.variable = variable;
values = new long[samplingPeriod / samplingInterval];
valuesSum = 0;
current = -1;
}
public int getSamplingInterval() {
return samplingInterval;
}
public void run() {
try {
lock.lock();
long newValue = variable.getValue();
if (current == -1) {
valuesSum = newValue;
current = 0;
values[current] = newValue;
}
else {
current = (current + 1) % values.length;
valuesSum = valuesSum - values[current] + newValue;
values[current] = newValue;
}
rate = ((double) valuesSum) / values.length;
}
finally {
lock.unlock();
}
}
public Double getValue() {
return rate;
}
}
/**
* Add a sampling variable. This method is thread safe.
*
* @param group timer group.
* @param name timer name.
* @param period sampling period to compute rate.
* @param interval sampling frequency, how often the variable is probed.
* @param variable variable to sample.
*/
public void addSampler(String group, String name, int period, int interval, Variable variable) {
if (scheduler == null) {
throw new IllegalStateException("scheduler not set, cannot sample");
}
try {
samplerLock.lock();
Map> map = samplers.get(group);
if (map == null) {
map = samplers.get(group);
if (map == null) {
map = new HashMap>();
samplers.put(group, map);
}
}
if (map.containsKey(name)) {
throw new RuntimeException(XLog.format("Sampler group=[{0}] name=[{1}] already defined", group, name));
}
Sampler sampler = new Sampler(period, interval, variable);
map.put(name, sampler);
scheduler.scheduleAtFixedRate(sampler, 0, sampler.getSamplingInterval(), TimeUnit.SECONDS);
}
finally {
samplerLock.unlock();
}
}
/**
* Return all the samplers. This method is thread safe. The samplers are live. The sampler value is a
* snapshot at the time the {@link Instrumentation.Element#getValue()} is invoked.
*
* @return all counters.
*/
public Map>> getSamplers() {
return samplers;
}
}