Skip to content

Send initial telemetry in separate thread to reduce start-up latency. #8818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
14d6ea5
Send initial telemetry in separate thread to reduce start-up latency.
AlexeyKuznetsov-DD May 13, 2025
ed8e136
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 13, 2025
bf64a9a
Added missing annotation and fixed typo.
AlexeyKuznetsov-DD May 13, 2025
256e138
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 14, 2025
ad558a2
Added support for emulating some work in main() function.
AlexeyKuznetsov-DD May 14, 2025
1c91268
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 16, 2025
851721a
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 16, 2025
9dd2394
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 19, 2025
b52031c
Minor cleanup.
AlexeyKuznetsov-DD May 19, 2025
a64bd08
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 19, 2025
5e8be4c
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 20, 2025
5d13771
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 20, 2025
74f6236
Fixed test.
AlexeyKuznetsov-DD May 20, 2025
92e3778
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 20, 2025
528ee68
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 21, 2025
6f3ccce
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 23, 2025
6af9b95
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 23, 2025
f55e93b
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 23, 2025
6ceb1cb
Merge branch 'master' into alexeyk/do-not-wait-on-telemetry-fowarder-…
AlexeyKuznetsov-DD May 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package datadog.trace.bootstrap;

import datadog.json.JsonWriter;
import java.io.IOException;
import de.thetaphi.forbiddenapis.SuppressForbidden;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/** Thread safe telemetry class used to relay information about tracer activation. */
public abstract class BootstrapInitializationTelemetry {
Expand Down Expand Up @@ -179,7 +178,7 @@ public void finish() {
}

public interface JsonSender {
void send(byte[] payload) throws IOException;
void send(byte[] payload);
}

public static final class ForwarderJsonSender implements JsonSender {
Expand All @@ -190,19 +189,36 @@ public static final class ForwarderJsonSender implements JsonSender {
}

@Override
public void send(byte[] payload) throws IOException {
ProcessBuilder builder = new ProcessBuilder(forwarderPath, "library_entrypoint");
public void send(byte[] payload) {
ForwarderJsonSenderThread t = new ForwarderJsonSenderThread(forwarderPath, payload);
t.setDaemon(true);
t.start();
}
}

Process process = builder.start();
try (OutputStream out = process.getOutputStream()) {
out.write(payload);
}
public static final class ForwarderJsonSenderThread extends Thread {
private final String forwarderPath;
private final byte[] payload;

public ForwarderJsonSenderThread(String forwarderPath, byte[] payload) {
super("dd-forwarder-json-sender");
this.forwarderPath = forwarderPath;
this.payload = payload;
}

@SuppressForbidden
@Override
public void run() {
ProcessBuilder builder = new ProcessBuilder(forwarderPath, "library_entrypoint");

try {
process.waitFor(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// just for hygiene, reset the interrupt status
Thread.currentThread().interrupt();
Process process = builder.start();
try (OutputStream out = process.getOutputStream()) {
out.write(payload);
}
} catch (Throwable e) {
// We don't have a log manager here, so just print.
System.err.println("Failed to send telemetry: " + e.getMessage());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class InitializationTelemetryTest extends Specification {

def "normal start-up"() {
when:
def result = InitializationTelemetryCheck.runTestJvm(null)
def result = InitializationTelemetryCheck.runTestJvm(null, false, "sleep")

then:
result.exitCode == 0
Expand All @@ -33,7 +33,7 @@ class InitializationTelemetryTest extends Specification {
// agent initialization to fail. However, we should catch the exception allowing the application
// to run normally.
when:
def result = InitializationTelemetryCheck.runTestJvm(InitializationTelemetryCheck.BlockByteBuddy)
def result = InitializationTelemetryCheck.runTestJvm(InitializationTelemetryCheck.BlockByteBuddy, false, "sleep")

then:
result.exitCode == 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@
* <p>Checks edge cases where InitializationTelemetry is blocked by SecurityManagers
*/
public class InitializationTelemetryCheck {
public static void main(String[] args) {}
public static void main(String[] args) throws InterruptedException {
// Emulates the real application performing work in main().
// That should give enough time to send initial telemetry from daemon thread.
if (args.length > 0 && "sleep".equals(args[0])) {
Thread.sleep(1000);
}
}

/** Blocks the loading of the agent bootstrap */
public static class BlockAgentLoading extends TestSecurityManager {
Expand Down Expand Up @@ -71,12 +77,20 @@ protected boolean checkFileExecutePermission(FilePermission perm, Object ctx, St

public static final Result runTestJvm(Class<? extends TestSecurityManager> securityManagerClass)
throws Exception {
return runTestJvm(securityManagerClass, false);
return runTestJvm(securityManagerClass, false, null);
}

public static final Result runTestJvm(
Class<? extends TestSecurityManager> securityManagerClass, boolean printStreams)
throws Exception {
return runTestJvm(securityManagerClass, printStreams, null);
}

public static final Result runTestJvm(
Class<? extends TestSecurityManager> securityManagerClass,
boolean printStreams,
String mainArgs)
throws Exception {

File jarFile =
IntegrationTestUtils.createJarFileWithClasses(requiredClasses(securityManagerClass));
Expand All @@ -95,7 +109,7 @@ public static final Result runTestJvm(
IntegrationTestUtils.runOnSeparateJvm(
InitializationTelemetryCheck.class.getName(),
InitializationTelemetryCheck.jvmArgs(securityManagerClass),
InitializationTelemetryCheck.mainArgs(),
InitializationTelemetryCheck.mainArgs(mainArgs),
InitializationTelemetryCheck.envVars(forwarderFile),
jarFile,
printStreams);
Expand Down Expand Up @@ -162,8 +176,12 @@ public static final String[] jvmArgs(Class<? extends TestSecurityManager> securi
}
}

public static final String[] mainArgs() {
return new String[] {};
public static final String[] mainArgs(String args) {
if (args == null) {
return new String[] {};
} else {
return args.split(",");
}
}

public static final Map<String, String> envVars(File forwarderFile) {
Expand Down
2 changes: 1 addition & 1 deletion gradle/forbiddenApiFilters/main.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ net.bytebuddy.matcher.ElementMatchers#isInterface()
net.bytebuddy.matcher.ElementMatchers#isAbstract()

# avoid System.out/err methods to prevent debug logging in production
@defaultMessage Avoid using System.out/err to prevent excess logging. To override, add @SuppressMethod.
@defaultMessage Avoid using System.out/err to prevent excess logging. To override, add @SuppressForbidden.
java.lang.System#out
java.lang.System#err
Loading