/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* 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.
*/
package scouter.agent.trace;
import scouter.agent.Configure;
import scouter.util.KeyGen;
import scouter.util.LongKeyMap;
import java.util.Enumeration;
public class TraceContextManager {
private static Configure conf = Configure.getInstance();
private static LongKeyMap<TraceContext> entry = new LongKeyMap<TraceContext>();
private static ThreadLocal<TraceContext> local = new ThreadLocal<TraceContext>();
private static LongKeyMap<TraceContext> deferredEntry = new LongKeyMap<TraceContext>();
//pass = 1, discard = 2, end-processing-with-path = -1, end-processing-with-path = -2
private static ThreadLocal<Integer> forceDiscard = new ThreadLocal<Integer>();
public static int size() {
return entry.size();
}
public static int[] getActiveCount() {
int[] act = new int[3];
try {
long now = System.currentTimeMillis();
Enumeration<TraceContext> en = entry.values();
while (en.hasMoreElements()) {
TraceContext ctx = en.nextElement();
long tm = now - ctx.startTime;
if (tm < conf.trace_activeserivce_yellow_time) {
act[0]++;
} else if (tm < conf.trace_activeservice_red_time) {
act[1]++;
} else {
act[2]++;
}
}
Enumeration<TraceContext> enDeferred = deferredEntry.values();
while (enDeferred.hasMoreElements()) {
TraceContext ctx = enDeferred.nextElement();
long tm = now - ctx.startTime;
if (tm < conf.trace_activeserivce_yellow_time) {
act[0]++;
} else if (tm < conf.trace_activeservice_red_time) {
act[1]++;
} else {
act[2]++;
}
}
} catch (Throwable t) {
}
return act;
}
public static Enumeration<TraceContext> getContextEnumeration() {
return entry.values();
}
public static Enumeration<TraceContext> getDeferredContextEnumeration() {
return deferredEntry.values();
}
public static TraceContext getContext(long key) {
return entry.get(key);
}
public static TraceContext getDeferredContext(long key) {
return deferredEntry.get(key);
}
public static TraceContext getContext() {
return local.get();
}
public static void clearForceDiscard() {
if(!conf._xlog_hard_sampling_enabled) {
return;
}
Integer num = forceDiscard.get();
if(num == null) {
forceDiscard.set(-1);
} else {
if(num == 1) {
forceDiscard.set(-1);
} else if(num == 2) {
forceDiscard.set(-2);
}
}
}
public static boolean isForceDiscarded() {
if(!conf._xlog_hard_sampling_enabled) {
return false;
}
boolean discard = false;
Integer num = forceDiscard.get();
if(num == null) {
return false;
}
if(num == 2 || num == -2) {
discard = true;
}
return discard;
}
public static boolean startForceDiscard() {
if(!conf._xlog_hard_sampling_enabled) {
return false;
}
boolean discard = false;
Integer num = forceDiscard.get();
if(num == null || num == -1 || num == -2) {
if(Math.abs(KeyGen.next()%100) >= conf._xlog_hard_sampling_rate_pct) {
discard = true;
forceDiscard.set(2); //discard
} else {
forceDiscard.set(1); //pass
}
} else {
if(num == 2) { //discard
discard = true;
}
}
return discard;
}
public static long start(Thread thread, TraceContext o) {
long key = thread.getId();
local.set(o);
entry.put(key, o);
return key;
}
public static void end(long key) {
local.set(null);
entry.remove(key);
clearForceDiscard();
}
public static void toDeferred(TraceContext o) {
deferredEntry.put(o.txid, o);
}
public static void completeDeferred(TraceContext o) {
deferredEntry.remove(o.txid);
}
}