Skip to content

Commit

Permalink
Allow specifying a comma separated list of extensions (#6137)
Browse files Browse the repository at this point in the history
* Allow specifying a comma separated list of extensions

* update doc

* typo

* Update examples/extension/README.md

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
  • Loading branch information
laurit and trask authored Jun 8, 2022
1 parent 532e08f commit 091197a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 8 deletions.
3 changes: 2 additions & 1 deletion examples/extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ To add the extension to the instrumentation agent:
-Dotel.javaagent.extensions=build/libs/opentelemetry-java-instrumentation-extension-demo-1.0-all.jar
-jar myapp.jar
```
Note: to load multiple extensions, you can specify a directory path for the `otel.javaagent.extensions` value.
Note: to load multiple extensions, you can specify a comma-separated list of extension jars or directories (that
contain extension jars) for the `otel.javaagent.extensions` value.

## Embed extensions in the OpenTelemetry Agent

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
Expand Down Expand Up @@ -114,27 +115,38 @@ private static URLClassLoader getDelegate(ClassLoader parent, URL extensionUrl)
return new ExtensionClassLoader(new URL[] {extensionUrl}, parent);
}

private static List<URL> parseLocation(String locationName, File javaagentFile) {
// visible for testing
static List<URL> parseLocation(String locationName, File javaagentFile) {
if (locationName == null) {
return Collections.emptyList();
}

List<URL> result = new ArrayList<>();
for (String location : locationName.split(",")) {
parseLocation(location, javaagentFile, result);
}

if (locationName == null) {
return result;
return result;
}

private static void parseLocation(String locationName, File javaagentFile, List<URL> locations) {
if (locationName.isEmpty()) {
return;
}

File location = new File(locationName);
if (isJar(location)) {
addFileUrl(result, location);
addFileUrl(locations, location);
} else if (location.isDirectory()) {
File[] files = location.listFiles(ExtensionClassLoader::isJar);
if (files != null) {
for (File file : files) {
if (!file.getAbsolutePath().equals(javaagentFile.getAbsolutePath())) {
addFileUrl(result, file);
if (isJar(file) && !file.getAbsolutePath().equals(javaagentFile.getAbsolutePath())) {
addFileUrl(locations, file);
}
}
}
}
return result;
}

private static boolean isJar(File f) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.tooling;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

public class ExtensionClassLoaderTest {
private static final File AGENT_FILE = new File("/agent.jar");

@Test
void testParseLocation(@TempDir Path outputDir) throws Exception {
String jarPath1 = createJar("test-1.jar", outputDir);
String jarPath2 = createJar("test-2.jar", outputDir);
// test that non-jar file is skipped
Files.createFile(outputDir.resolve("test.txt"));
{
List<URL> result = ExtensionClassLoader.parseLocation(jarPath1, AGENT_FILE);
assertEquals(1, result.size());
}
{
// empty paths are ignored
List<URL> result = ExtensionClassLoader.parseLocation("," + jarPath1 + ",,,", AGENT_FILE);
assertEquals(1, result.size());
}
{
List<URL> result = ExtensionClassLoader.parseLocation(jarPath1 + "," + jarPath2, AGENT_FILE);
assertEquals(2, result.size());
}
{
List<URL> result = ExtensionClassLoader.parseLocation(outputDir.toString(), AGENT_FILE);
assertEquals(2, result.size());
}
{
List<URL> result =
ExtensionClassLoader.parseLocation(
outputDir + "," + jarPath1 + "," + jarPath2, AGENT_FILE);
assertEquals(4, result.size());
}
{
List<URL> result = ExtensionClassLoader.parseLocation("/anydir", AGENT_FILE);
assertEquals(0, result.size());
}
{
List<URL> result = ExtensionClassLoader.parseLocation("/anyfile.jar", AGENT_FILE);
assertEquals(0, result.size());
}
{
List<URL> result = ExtensionClassLoader.parseLocation(jarPath1 + ",/anyfile.jar", AGENT_FILE);
assertEquals(1, result.size());
}
}

private static String createJar(String name, Path directory) throws Exception {
Path jarPath = directory.resolve(name);
createJar(jarPath);
return jarPath.toAbsolutePath().toString();
}

private static void createJar(Path path) throws Exception {
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
try (JarOutputStream jar = new JarOutputStream(Files.newOutputStream(path), manifest)) {
// empty jar
}
}
}

0 comments on commit 091197a

Please sign in to comment.