in apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/SamplingProfiler.java [503:566]
public void processTraces() throws IOException {
if (jfrParser == null) {
jfrParser = new JfrParser();
}
if (Thread.currentThread().isInterrupted()) {
return;
}
createFilesIfRequired();
long eof = startProcessingActivationEventsFile();
if (eof == 0 && activationEventsBuffer.limit() == 0 && profiledThreads.isEmpty()) {
logger.debug("No activation events during this period. Skip processing stack traces.");
return;
}
long start = System.nanoTime();
List<WildcardMatcher> excludedClasses = config.getExcludedClasses();
List<WildcardMatcher> includedClasses = config.getIncludedClasses();
if (config.isBackupDiagnosticFiles()) {
backupDiagnosticFiles(eof);
}
try {
jfrParser.parse(jfrFile, excludedClasses, includedClasses);
final List<StackTraceEvent> stackTraceEvents = getSortedStackTraceEvents(jfrParser);
if (logger.isDebugEnabled()) {
logger.debug("Processing {} stack traces", stackTraceEvents.size());
}
List<StackFrame> stackFrames = new ArrayList<>();
ElasticApmTracer tracer = this.tracer;
ActivationEvent event = new ActivationEvent();
long inferredSpansMinDuration = getInferredSpansMinDurationNs();
for (StackTraceEvent stackTrace : stackTraceEvents) {
processActivationEventsUpTo(stackTrace.nanoTime, event, eof);
CallTree.Root root = profiledThreads.get(stackTrace.threadId);
if (root != null) {
jfrParser.resolveStackTrace(stackTrace.stackTraceId, true, stackFrames, MAX_STACK_DEPTH);
if (stackFrames.size() == MAX_STACK_DEPTH) {
logger.debug("Max stack depth reached. Set profiling_included_classes or profiling_excluded_classes.");
}
// stack frames may not contain any Java frames
// see https://github.com/jvm-profiling-tools/async-profiler/issues/271#issuecomment-582430233
if (!stackFrames.isEmpty()) {
try {
root.addStackTrace(tracer, stackFrames, stackTrace.nanoTime, callTreePool, inferredSpansMinDuration);
} catch (Exception e) {
logger.warn("Removing call tree for thread {} because of exception while adding a stack trace: {} {}",
stackTrace.threadId, e.getClass(), e.getMessage());
logger.debug(e.getMessage(), e);
profiledThreads.remove(stackTrace.threadId);
}
}
}
stackFrames.clear();
}
// process all activation events that happened after the last stack trace event
// otherwise we may miss root deactivations
processActivationEventsUpTo(System.nanoTime(), event, eof);
} finally {
if (logger.isDebugEnabled()) {
logger.debug("Processing traces took {}µs", (System.nanoTime() - start) / 1000);
}
jfrParser.resetState();
resetActivationEventBuffer();
}
}