Skip to content

Commit 3bb2043

Browse files
committed
Merge remote-tracking branch 'upstream/master' into logging-custom-facade
2 parents 2b99fbf + bdbf401 commit 3bb2043

File tree

34 files changed

+362
-87
lines changed

34 files changed

+362
-87
lines changed

CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ endif::[]
2727
===== Features
2828
* Exceptions that are logged using the fatal log level are now captured (log4j2 only) - {pull}2377[#2377]
2929
* Replaced `authorization` in the default value of `sanitize_field_names` with `*auth*` - {pull}2326[#2326]
30+
* Unsampled transactions are dropped and not sent to the APM-Server if the APM-Server version is 8.0+ - {pull}2329[#2329]
3031
* Adding agent logging capabilities to our SDK, making it available for external plugins - {pull}2390[#2390]
3132
3233
[float]

Jenkinsfile

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ pipeline {
3535
parameters {
3636
string(name: 'MAVEN_CONFIG', defaultValue: '-V -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dhttps.protocols=TLSv1.2 -Dmaven.wagon.http.retryHandler.count=3 -Dmaven.wagon.httpconnectionManager.ttlSeconds=25', description: 'Additional maven options.')
3737
booleanParam(name: 'test_ci', defaultValue: true, description: 'Enable Unit tests')
38-
booleanParam(name: 'smoketests_ci', defaultValue: true, description: 'Enable Smoke tests')
39-
booleanParam(name: 'integrationtests_ci', defaultValue: true, description: 'Enable Integration tests')
38+
booleanParam(name: 'agent_integration_tests_ci', defaultValue: true, description: 'Enable Agent Integration tests')
39+
booleanParam(name: 'endtoend_tests_ci', defaultValue: true, description: 'Enable APM End-to-End Integration tests')
4040
booleanParam(name: 'bench_ci', defaultValue: true, description: 'Enable benchmarks')
4141
booleanParam(name: 'compatibility_ci', defaultValue: false, description: 'Enable JDK compatibility tests')
4242
}
@@ -153,10 +153,7 @@ pipeline {
153153
}
154154
}
155155
}
156-
/**
157-
Run smoke tests for different servers and databases.
158-
*/
159-
stage('Smoke Tests 01') {
156+
stage('Non-Application Server integration tests') {
160157
agent { label 'linux && immutable' }
161158
options { skipDefaultCheckout() }
162159
environment {
@@ -166,15 +163,15 @@ pipeline {
166163
}
167164
when {
168165
beforeAgent true
169-
expression { return params.smoketests_ci }
166+
expression { return params.agent_integration_tests_ci }
170167
}
171168
steps {
172-
withGithubNotify(context: 'Smoke Tests 01', tab: 'tests') {
169+
withGithubNotify(context: 'Non-Application Server integration tests', tab: 'tests') {
173170
deleteDir()
174171
unstashV2(name: 'build', bucket: "${JOB_GCS_BUCKET_STASH}", credentialsId: "${JOB_GCS_CREDENTIALS}")
175172
dir("${BASE_DIR}"){
176173
withOtelEnv() {
177-
sh './scripts/jenkins/smoketests-01.sh'
174+
sh './mvnw -q -P ci-non-application-server-integration-tests verify'
178175
}
179176
}
180177
}
@@ -185,10 +182,7 @@ pipeline {
185182
}
186183
}
187184
}
188-
/**
189-
Run smoke tests for different servers and databases.
190-
*/
191-
stage('Smoke Tests 02') {
185+
stage('Application Server integration tests') {
192186
agent { label 'linux && immutable' }
193187
options { skipDefaultCheckout() }
194188
environment {
@@ -198,15 +192,15 @@ pipeline {
198192
}
199193
when {
200194
beforeAgent true
201-
expression { return params.smoketests_ci }
195+
expression { return params.agent_integration_tests_ci }
202196
}
203197
steps {
204-
withGithubNotify(context: 'Smoke Tests 02', tab: 'tests') {
198+
withGithubNotify(context: 'Application Server integration tests', tab: 'tests') {
205199
deleteDir()
206200
unstashV2(name: 'build', bucket: "${JOB_GCS_BUCKET_STASH}", credentialsId: "${JOB_GCS_CREDENTIALS}")
207201
dir("${BASE_DIR}"){
208202
withOtelEnv() {
209-
sh './scripts/jenkins/smoketests-02.sh'
203+
sh './mvnw -q -P ci-application-server-integration-tests verify'
210204
}
211205
}
212206
}
@@ -295,14 +289,14 @@ pipeline {
295289
}
296290
}
297291
}
298-
stage('Integration Tests') {
292+
stage('End-To-End Integration Tests') {
299293
agent none
300294
when {
301295
allOf {
302296
expression { return env.ONLY_DOCS == "false" }
303297
anyOf {
304298
changeRequest()
305-
expression { return params.integrationtests_ci }
299+
expression { return params.endtoend_tests_ci }
306300
expression { return env.GITHUB_COMMENT?.contains('integration tests') }
307301
}
308302
}

apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,8 @@ public void endTransaction(Transaction transaction) {
368368
new RuntimeException("this exception is just used to record where the transaction has been ended from"));
369369
}
370370
}
371-
if (!transaction.isNoop()) {
371+
if (!transaction.isNoop() &&
372+
(transaction.isSampled() || apmServerClient.supportsKeepingUnsampledTransaction())) {
372373
// we do report non-sampled transactions (without the context)
373374
reporter.report(transaction);
374375
} else {

apm-agent-core/src/main/java/co/elastic/apm/agent/report/ApmServerClient.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public class ApmServerClient {
7171
private static final Version VERSION_7_0 = Version.of("7.0.0");
7272
private static final Version VERSION_7_4 = Version.of("7.4.0");
7373
private static final Version VERSION_7_9 = Version.of("7.9.0");
74+
private static final Version VERSION_8_0 = Version.of("8.0.0");
7475

7576
private final ReporterConfiguration reporterConfiguration;
7677
@Nullable
@@ -338,6 +339,15 @@ public boolean supportsLogsEndpoint() {
338339
return isAtLeast(VERSION_7_9);
339340
}
340341

342+
public boolean supportsKeepingUnsampledTransaction() {
343+
// supportsKeepingUnsampledTransaction is called from application threads
344+
// return true instead of blocking the thread
345+
if (apmServerVersion != null && !apmServerVersion.isDone()) {
346+
return true;
347+
}
348+
return isLowerThan(VERSION_8_0);
349+
}
350+
341351
@Nullable
342352
Version getApmServerVersion(long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
343353
if (apmServerVersion != null) {
@@ -346,6 +356,10 @@ Version getApmServerVersion(long timeout, TimeUnit timeUnit) throws InterruptedE
346356
return null;
347357
}
348358

359+
public boolean isLowerThan(Version apmServerVersion) {
360+
return !isAtLeast(apmServerVersion);
361+
}
362+
349363
public boolean isAtLeast(Version apmServerVersion) {
350364
if (this.apmServerVersion == null) {
351365
throw new IllegalStateException("Called before init event");
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package co.elastic.apm.agent.impl;
20+
21+
import co.elastic.apm.agent.AbstractInstrumentationTest;
22+
import co.elastic.apm.agent.MockReporter;
23+
import co.elastic.apm.agent.configuration.CoreConfiguration;
24+
import co.elastic.apm.agent.configuration.SpyConfiguration;
25+
import co.elastic.apm.agent.impl.metadata.MetaData;
26+
import co.elastic.apm.agent.objectpool.TestObjectPoolFactory;
27+
import co.elastic.apm.agent.report.ApmServerClient;
28+
import org.junit.jupiter.api.AfterAll;
29+
import org.junit.jupiter.api.AfterEach;
30+
import org.junit.jupiter.api.BeforeAll;
31+
import org.junit.jupiter.api.Test;
32+
import org.stagemonitor.configuration.ConfigurationRegistry;
33+
34+
35+
import java.io.IOException;
36+
37+
import static org.assertj.core.api.Assertions.assertThat;
38+
import static org.mockito.Mockito.mock;
39+
import static org.mockito.Mockito.when;
40+
41+
class DropUnsampledTransactionsTest extends AbstractInstrumentationTest {
42+
43+
private static ApmServerClient apmServerClient = mock(ApmServerClient.class);
44+
45+
private static MockReporter reporter = new MockReporter();
46+
47+
private static ElasticApmTracer tracer;
48+
49+
@BeforeAll
50+
static void startTracer() {
51+
ConfigurationRegistry configurationRegistry = SpyConfiguration.createSpyConfig();
52+
tracer = new ElasticApmTracer(configurationRegistry, reporter, new TestObjectPoolFactory(), apmServerClient, "ephemeralId", MetaData.create(configurationRegistry, "ephemeralId"));
53+
tracer.start(false);
54+
}
55+
56+
@AfterAll
57+
static void stopTracer() {
58+
tracer.stop();
59+
}
60+
61+
@AfterEach
62+
void resetReporter() {
63+
reporter.reset();
64+
}
65+
66+
@Test
67+
void whenTheAPMServerSupportsKeepingUnsampledTransactionsUnsampledTransactionsShouldBeReported() throws IOException {
68+
when(apmServerClient.supportsKeepingUnsampledTransaction()).thenReturn(true);
69+
tracer.getConfig(CoreConfiguration.class).getSampleRate().update(0.0, SpyConfiguration.CONFIG_SOURCE_NAME);
70+
71+
tracer.startRootTransaction(null).end();
72+
73+
assertThat(reporter.getTransactions().size()).isEqualTo(1);
74+
}
75+
76+
@Test
77+
void whenTheAPMServerSupportsKeepingUnsampledTransactionsSampledTransactionsShouldBeReported() throws IOException {
78+
when(apmServerClient.supportsKeepingUnsampledTransaction()).thenReturn(true);
79+
tracer.getConfig(CoreConfiguration.class).getSampleRate().update(1.0, SpyConfiguration.CONFIG_SOURCE_NAME);
80+
81+
tracer.startRootTransaction(null).end();
82+
83+
assertThat(reporter.getTransactions().size()).isEqualTo(1);
84+
}
85+
86+
@Test
87+
void whenTheAPMServerDoesNotSupportsKeepingUnsampledTransactionsUnsampledTransactionsShouldNotBeReported() throws IOException {
88+
when(apmServerClient.supportsKeepingUnsampledTransaction()).thenReturn(false);
89+
tracer.getConfig(CoreConfiguration.class).getSampleRate().update(0.0, SpyConfiguration.CONFIG_SOURCE_NAME);
90+
91+
tracer.startRootTransaction(null).end();
92+
93+
assertThat(reporter.getTransactions().size()).isEqualTo(0);
94+
}
95+
96+
@Test
97+
void whenTheAPMServerDoesNotSupportsKeepingUnsampledTransactionsSampledTransactionsShouldBeReported() throws IOException {
98+
when(apmServerClient.supportsKeepingUnsampledTransaction()).thenReturn(false);
99+
tracer.getConfig(CoreConfiguration.class).getSampleRate().update(1.0, SpyConfiguration.CONFIG_SOURCE_NAME);
100+
101+
tracer.startRootTransaction(null).end();
102+
103+
assertThat(reporter.getTransactions().size()).isEqualTo(1);
104+
}
105+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@
4848
import static org.mockito.Mockito.doReturn;
4949

5050
// Using a separate test class for proxy support
51-
public class ApmServerClientProxySupportTest {
51+
public class ApmServerClientProxySupportIT {
5252

53-
private static final Logger logger = LoggerFactory.getLogger(ApmServerClientProxySupportTest.class);
53+
private static final Logger logger = LoggerFactory.getLogger(ApmServerClientProxySupportIT.class);
5454

5555
private static final String PROXY_HEADER = "proxy-header";
5656
private static final String PROXY_HEADER_VALUE = "1234";

apm-agent-core/src/test/java/co/elastic/apm/agent/report/ApmServerReporterIntegrationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static void stopServer() {
8989

9090
@BeforeEach
9191
void setUp() throws Exception {
92+
statusCode = HttpStatus.OK_200;
9293
handler = new BlockingHandler(exchange -> {
9394
if (statusCode < 300 && exchange.getRequestPath().equals("/intake/v2/events")) {
9495
receivedIntakeApiCalls.incrementAndGet();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package co.elastic.apm.agent.testutils;
20+
21+
import org.junit.jupiter.api.extension.ExtendWith;
22+
23+
import java.lang.annotation.Documented;
24+
import java.lang.annotation.ElementType;
25+
import java.lang.annotation.Retention;
26+
import java.lang.annotation.RetentionPolicy;
27+
import java.lang.annotation.Target;
28+
29+
@Target({ElementType.TYPE, ElementType.METHOD})
30+
@Retention(RetentionPolicy.RUNTIME)
31+
@Documented
32+
@ExtendWith(DisabledOnAppleSiliconCondition.class)
33+
public @interface DisabledOnAppleSilicon {
34+
35+
/**
36+
* The reason this annotated test class or test method is disabled.
37+
*/
38+
String value() default "";
39+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package co.elastic.apm.agent.testutils;
20+
21+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
22+
import org.junit.jupiter.api.extension.ExecutionCondition;
23+
import org.junit.jupiter.api.extension.ExtensionContext;
24+
25+
import java.lang.reflect.AnnotatedElement;
26+
27+
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
28+
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;
29+
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;
30+
31+
public class DisabledOnAppleSiliconCondition implements ExecutionCondition {
32+
33+
@Override
34+
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
35+
AnnotatedElement element = context.getElement().orElse(null);
36+
return findAnnotation(element, DisabledOnAppleSilicon.class)
37+
.map(annotation -> isOnAppleSilicon()
38+
? disabled(element + " is @DisabledOnAppleSilicon", annotation.value())
39+
: enabled("Not running on Apple silicon"))
40+
.orElse(enabled("@DisabledOnAppleSilicon is not present"));
41+
}
42+
43+
public boolean isOnAppleSilicon() {
44+
String os = System.getProperty("os.name").toLowerCase();
45+
String arch = System.getProperty("os.arch").toLowerCase();
46+
return os.contains("mac") && arch.contains("aarch");
47+
}
48+
}

apm-agent-core/src/test/resources/apm-server-schema/current/transaction.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,13 @@
826826
"string"
827827
]
828828
},
829+
"id": {
830+
"description": "A unique identifier of the invoked serverless function.",
831+
"type": [
832+
"null",
833+
"string"
834+
]
835+
},
829836
"trigger": {
830837
"description": "Trigger attributes.",
831838
"type": [

0 commit comments

Comments
 (0)