Skip to content

Commit 4064745

Browse files
authored
Merge branch 'main' into close-bridged-instruments
2 parents 72ebbb8 + bc8deee commit 4064745

768 files changed

Lines changed: 8277 additions & 6370 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.fossa.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,9 @@ targets:
10691069
- type: gradle
10701070
path: ./
10711071
target: ':instrumentation:zio:zio-2.0:javaagent'
1072+
- type: gradle
1073+
path: ./
1074+
target: ':instrumentation:zio:zio-http-3.0:javaagent'
10721075
- type: gradle
10731076
path: ./
10741077
target: ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-annotations:javaagent'

.github/copilot-instructions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ Never use the `--rerun-tasks` flag unless explicitly asked to use this option.
2828
Gradle automatically detects changes and re-runs tasks automatically when needed. Using `--rerun-tasks`
2929
is wasteful and slows down builds unnecessarily.
3030

31+
Builds and tests in this repository genuinely take a long time (often several minutes).
32+
When running Gradle commands, use a timeout of 0 (no timeout) and wait for them to complete.
33+
Do not assume a build has hung or failed just because it takes a while.
34+
3135
## Throwing exceptions
3236

3337
When writing instrumentation, you have to be really careful about throwing exceptions. For library

benchmark-jfr-analyzer/src/main/java/io/opentelemetry/javaagent/benchmark/jfr/Analyzer.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55

66
package io.opentelemetry.javaagent.benchmark.jfr;
77

8+
import static java.util.stream.Collectors.toList;
9+
import static java.util.stream.Collectors.toSet;
10+
811
import java.io.File;
912
import java.util.Comparator;
1013
import java.util.HashMap;
1114
import java.util.List;
1215
import java.util.Map;
1316
import java.util.Objects;
1417
import java.util.Set;
15-
import java.util.stream.Collectors;
1618
import javax.annotation.Nullable;
1719
import jdk.jfr.consumer.RecordedEvent;
1820
import jdk.jfr.consumer.RecordedFrame;
@@ -31,7 +33,7 @@ public static void main(String[] args) throws Exception {
3133
List<RecordedEvent> events =
3234
RecordingFile.readAllEvents(jfrFile.toPath()).stream()
3335
.filter(e -> e.getEventType().getName().equals("jdk.ExecutionSample"))
34-
.collect(Collectors.toList());
36+
.collect(toList());
3537

3638
Set<String> agentCallers = getAgentCallers(events);
3739

@@ -59,7 +61,7 @@ private static Set<String> getAgentCallers(List<RecordedEvent> events) {
5961
return events.stream()
6062
.map(e -> getAgentCaller(e.getStackTrace()))
6163
.filter(Objects::nonNull)
62-
.collect(Collectors.toSet());
64+
.collect(toSet());
6365
}
6466

6567
@Nullable
@@ -171,7 +173,7 @@ private Node recordChildSample(String stackTraceElement) {
171173
private List<Node> getOrderedChildNodes() {
172174
return childNodes.values().stream()
173175
.sorted(Comparator.comparingInt(Node::getCount).reversed())
174-
.collect(Collectors.toList());
176+
.collect(toList());
175177
}
176178

177179
private int getCount() {

benchmark-overhead-jmh/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ otelJava {
1212
}
1313

1414
dependencies {
15-
jmhImplementation("org.springframework.boot:spring-boot-starter-web:4.0.2")
15+
jmhImplementation("org.springframework.boot:spring-boot-starter-web:4.0.3")
1616
}
1717

1818
tasks {

benchmark-overhead/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ dependencies {
2525
testImplementation("org.junit.jupiter:junit-jupiter-params")
2626
testImplementation("com.squareup.okhttp3:okhttp:5.3.2")
2727
testImplementation("org.jooq:joox:2.0.1")
28-
testImplementation("com.jayway.jsonpath:json-path:2.10.0")
28+
testImplementation("com.jayway.jsonpath:json-path:3.0.0")
2929
testImplementation("org.slf4j:slf4j-simple:2.0.17")
3030
testImplementation("org.assertj:assertj-core:3.27.7")
3131

benchmark-overhead/src/test/java/io/opentelemetry/results/CsvPersister.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.results;
77

8+
import static java.util.stream.Collectors.toList;
89
import static java.util.concurrent.TimeUnit.NANOSECONDS;
910

1011
import java.io.IOException;
@@ -14,7 +15,6 @@
1415
import java.util.Arrays;
1516
import java.util.List;
1617
import java.util.function.Function;
17-
import java.util.stream.Collectors;
1818

1919
class CsvPersister implements ResultsPersister {
2020

@@ -88,7 +88,7 @@ private String createHeaderLine(List<AppPerfResults> results) {
8888
// line so that we can create a columnar structure that allows us to more easily compare agent
8989
// to agent for a given run.
9090

91-
List<String> agents = results.stream().map(r -> r.agent.getName()).collect(Collectors.toList());
91+
List<String> agents = results.stream().map(r -> r.agent.getName()).collect(toList());
9292
for (FieldSpec field : FIELDS) {
9393
for (String agent : agents) {
9494
sb.append(",").append(agent).append(':').append(field.name);

benchmark-overhead/src/test/java/io/opentelemetry/results/ResultsCollector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.results;
77

8+
import static java.util.stream.Collectors.toList;
89
import com.jayway.jsonpath.JsonPath;
910
import io.opentelemetry.agents.Agent;
1011
import io.opentelemetry.config.TestConfig;
@@ -16,7 +17,6 @@
1617
import java.nio.file.Path;
1718
import java.util.List;
1819
import java.util.Map;
19-
import java.util.stream.Collectors;
2020

2121
public class ResultsCollector {
2222

@@ -31,7 +31,7 @@ public ResultsCollector(NamingConvention namingConvention, Map<String, Long> run
3131
public List<AppPerfResults> collect(TestConfig config) {
3232
return config.getAgents().stream()
3333
.map(a -> readAgentResults(a, config))
34-
.collect(Collectors.toList());
34+
.collect(toList());
3535
}
3636

3737
private AppPerfResults readAgentResults(Agent agent, TestConfig config) {

buildscripts/checkstyle.xml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,6 @@
5050
-->
5151

5252
<module name="TreeWalker">
53-
<!-- Enforce static imports for OpenTelemetryAssertions methods (lowercase), but allow inner
54-
classes (uppercase). The negative lookahead is needed so we don't match import lines. -->
55-
<module name="RegexpSinglelineJava">
56-
<property name="format"
57-
value="^(?!.*import).*OpenTelemetryAssertions\.[a-z]"/>
58-
<property name="message"
59-
value="Please statically import methods from OpenTelemetryAssertions"/>
60-
</module>
61-
<module name="RegexpSinglelineJava">
62-
<property name="format"
63-
value="(?&lt;!import static org.assertj.core.api.|OpenTelemetry)Assertions.assertThat"/>
64-
<property name="message"
65-
value="Please statically import methods from Assertions (OpenTelemetryAssertions extends Assertions)"/>
66-
</module>
6753
<module name="OuterTypeFilename"/>
6854
<module name="IllegalTokenText">
6955
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.gradle
7+
8+
import com.diffplug.spotless.FormatterFunc
9+
import java.io.Serializable
10+
11+
/**
12+
* Spotless custom step that rewrites qualified references (e.g. {@code Objects.requireNonNull})
13+
* into unqualified references and adds the corresponding static import. Runs before
14+
* googleJavaFormat so that imports are sorted and any newly-unused regular imports are removed.
15+
*/
16+
class StaticImportFormatter : FormatterFunc, Serializable {
17+
18+
override fun apply(input: String): String {
19+
// (className, fullyQualifiedName, memberPattern)
20+
val rules = listOf(
21+
Triple("Objects", "java.util.Objects", "requireNonNull"),
22+
Triple(
23+
"ElementMatchers",
24+
"net.bytebuddy.matcher.ElementMatchers",
25+
"[a-z][a-zA-Z0-9]*"
26+
),
27+
Triple(
28+
"AgentElementMatchers",
29+
"io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers",
30+
"[a-z][a-zA-Z0-9]*"
31+
),
32+
Triple("TimeUnit", "java.util.concurrent.TimeUnit", "[A-Z][A-Z_0-9]*"),
33+
Triple(
34+
"StandardCharsets",
35+
"java.nio.charset.StandardCharsets",
36+
"[A-Z][A-Z_0-9]*"
37+
),
38+
Triple(
39+
"Collections",
40+
"java.util.Collections",
41+
"singleton[a-zA-Z0-9]*|empty[a-zA-Z0-9]*"
42+
),
43+
Triple(
44+
"ArgumentMatchers",
45+
"org.mockito.ArgumentMatchers",
46+
"[a-z][a-zA-Z0-9]*"
47+
),
48+
Triple(
49+
"Mockito",
50+
"org.mockito.Mockito",
51+
"mock|mockStatic|spy|when|verify|verifyNoInteractions|verifyNoMoreInteractions|doAnswer|doReturn|doThrow|lenient|never|times|atLeastOnce|withSettings"
52+
),
53+
Triple("Assertions", "org.assertj.core.api.Assertions", "assertThat"),
54+
Triple(
55+
"OpenTelemetryAssertions",
56+
"io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions",
57+
"[a-z][a-zA-Z0-9]*"
58+
),
59+
Triple(
60+
"SemconvStability",
61+
"io.opentelemetry.instrumentation.api.internal.SemconvStability",
62+
"emit[a-zA-Z0-9]*"
63+
),
64+
)
65+
66+
var content = input
67+
val importsToAdd = mutableSetOf<String>()
68+
69+
for ((className, pkg, memberPattern) in rules) {
70+
val regex = Regex("\\b${className}\\.(${memberPattern})\\b")
71+
val lines = content.lines().toMutableList()
72+
for (i in lines.indices) {
73+
if (lines[i].trimStart().startsWith("import ")) continue
74+
for (match in regex.findAll(lines[i])) {
75+
importsToAdd.add("import static ${pkg}.${match.groupValues[1]};")
76+
}
77+
lines[i] = regex.replace(lines[i], "$1")
78+
}
79+
content = lines.joinToString("\n")
80+
}
81+
82+
// Handle semconv classes: find all imported semconv classes (except SchemaUrls) and convert
83+
// qualified constant references (e.g. HttpAttributes.HTTP_METHOD) to static imports.
84+
// Also handles nested value classes (e.g. DbIncubatingAttributes.DbSystemNameIncubatingValues).
85+
val semconvImportRegex =
86+
Regex(
87+
"""^import (io\.opentelemetry\.semconv\.(?:[a-z][a-z.]*\.)?([A-Z][a-zA-Z0-9]+)(?:\.([A-Z][a-zA-Z0-9]+))?);"""
88+
)
89+
val semconvRules =
90+
content
91+
.lines()
92+
.mapNotNull { line -> semconvImportRegex.find(line.trim()) }
93+
.filter { it.groupValues[2] != "SchemaUrls" }
94+
.map { m ->
95+
// If there is a nested class (group 3), use the nested class as the className so that
96+
// references like `DbSystemNameIncubatingValues.COUCHBASE` are rewritten correctly.
97+
val className = if (m.groupValues[3].isNotEmpty()) m.groupValues[3] else m.groupValues[2]
98+
Triple(className, m.groupValues[1], "[A-Z][A-Z_0-9]*")
99+
}
100+
for ((className, pkg, memberPattern) in semconvRules) {
101+
val regex = Regex("\\b${className}\\.(${memberPattern})\\b")
102+
val lines = content.lines().toMutableList()
103+
var inBlockComment = false
104+
for (i in lines.indices) {
105+
val trimmed = lines[i].trimStart()
106+
if (trimmed.startsWith("/*")) inBlockComment = true
107+
if (inBlockComment) {
108+
if (trimmed.contains("*/")) inBlockComment = false
109+
continue
110+
}
111+
if (trimmed.startsWith("import ")) continue
112+
for (match in regex.findAll(lines[i])) {
113+
importsToAdd.add("import static ${pkg}.${match.groupValues[1]};")
114+
}
115+
lines[i] = regex.replace(lines[i], "$1")
116+
}
117+
content = lines.joinToString("\n")
118+
}
119+
120+
if (importsToAdd.isNotEmpty()) {
121+
val lines = content.lines().toMutableList()
122+
val firstImportIndex = lines.indexOfFirst { it.trimStart().startsWith("import ") }
123+
if (firstImportIndex >= 0) {
124+
for ((offset, imp) in importsToAdd.sorted().withIndex()) {
125+
lines.add(firstImportIndex + offset, imp)
126+
}
127+
content = lines.joinToString("\n")
128+
}
129+
}
130+
131+
return content
132+
}
133+
134+
companion object {
135+
private const val serialVersionUID = 1L
136+
}
137+
}

conventions/src/main/kotlin/otel.errorprone-conventions.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ tasks {
5858
// Suggests using Guava types for fields but we don't use Guava
5959
disable("ImmutableMemberCollection")
6060

61-
// Fully qualified names may be necessary when deprecating a class to avoid
62-
// deprecation warning.
61+
// Replaced by custom OtelUnnecessarilyFullyQualified check which handles
62+
// application.* and other repo-specific conventions
6363
disable("UnnecessarilyFullyQualified")
6464

6565
// TODO (trask) use animal sniffer

0 commit comments

Comments
 (0)