import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.GlobalMeterProvider;
import io.opentelemetry.api.metrics.LongTaskResult;
import io.opentelemetry.api.metrics.LongTaskUpdate;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.LongTaskStart;
import io.opentelemetry.api.metrics.common.Labels;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BinaryTree {
private static final Lock lock = new ReentrantLock();
private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
private Node root;
// Initialize OpenTelemetry components
private static final Tracer tracer = OpenTelemetry.getGlobalTracer("com.example.BinaryTree");
private static final Meter meter = GlobalMeterProvider.getMeter("com.example.BinaryTree");
// Register a long task to compute CPU usage during the add operation
private final LongTaskResult addCpuUsageResult = meter.longTaskBuilder("add_cpu_usage")
.setDescription("CPU usage of the add method")
.setUnit("ns")
.build()
.start();
// Define the LongTaskStart and LongTaskUpdate functions outside of the add() method
private final LongTaskUpdate addCpuUsageUpdate = new LongTaskUpdate() {
@Override
public void update(long durationNanos, LongTaskResult result) {
Labels labels = Labels.of("thread_name", Thread.currentThread().getName());
result.observe(durationNanos, labels);
}
};
private final LongTaskStart addCpuUsageStart = new LongTaskStart() {
@Override
public void start(Attributes attributes, LongTaskResult result) {
// Do nothing
}
};
public BinaryTree() {}
public void add(int value) {
Span span = tracer.spanBuilder("add").startSpan();
try (Scope scope = span.makeCurrent()) {
span.addEvent("Starting add method");
long taskId = addCpuUsageResult.getTaskId();
long startCpuTime = threadMXBean.getCurrentThreadCpuTime();
lock.lock();
try {
// Perform the actual addition of the element
root = addRecursive(root, value);
// Store the result of the long task in an attribute
addCpuUsageResult.stop();
meter.longTaskBuilder("add_cpu_usage_callback")
.setDescription("CPU usage of the add method with a callback")
.setUnit("ns")
.build()
.observe(addCpuUsageUpdate, addCpuUsageStart, addCpuUsageResult);
Attributes attributes = Attributes.of("long_task", addCpuUsageResult);
span.addEvent("Element added successfully", attributes);
} finally {
lock.unlock();
}
long endCpuTime = threadMXBean.getCurrentThreadCpuTime();
long duration = endCpuTime - startCpuTime;
Attributes attributes = Attributes.of("cpu_time", duration);
span.addEvent("Ending add method", attributes);
span.setStatus(Span.Status.OK);
} catch (Exception e) {
span.setStatus(Span.Status.ERROR);
span.recordException(e);
} finally {
span.end();
}
}
private Node addRecursive(Node current, int value) {
if (current == null) {
return new Node