Skip to content

Commit 1a043d2

Browse files
authored
http server 4xx configuration (#2037)
* http server 4xx configuration * statsbeat
1 parent 8d3603a commit 1a043d2

File tree

14 files changed

+231
-17
lines changed

14 files changed

+231
-17
lines changed

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ public static class PreviewConfiguration {
228228
// this is needed to unblock customer, but is not the ideal long-term solution
229229
// https://portal.microsofticm.com/imp/v3/incidents/details/266992200/home
230230
public boolean disablePropagation;
231+
public boolean captureHttpServer4xxAsError = true;
231232

232233
public List<InheritedAttribute> inheritedAttributes = new ArrayList<>();
233234

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/exporter/Exporter.java

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import io.opentelemetry.api.trace.SpanContext;
4747
import io.opentelemetry.api.trace.SpanId;
4848
import io.opentelemetry.api.trace.SpanKind;
49-
import io.opentelemetry.api.trace.StatusCode;
5049
import io.opentelemetry.api.trace.TraceState;
5150
import io.opentelemetry.instrumentation.api.aisdk.AiAppId;
5251
import io.opentelemetry.sdk.common.CompletableResultCode;
@@ -163,9 +162,11 @@ public class Exporter implements SpanExporter {
163162
}
164163

165164
private final TelemetryClient telemetryClient;
165+
private final boolean captureHttpServer4xxAsError;
166166

167-
public Exporter(TelemetryClient telemetryClient) {
167+
public Exporter(TelemetryClient telemetryClient, boolean captureHttpServer4xxAsError) {
168168
this.telemetryClient = telemetryClient;
169+
this.captureHttpServer4xxAsError = captureHttpServer4xxAsError;
169170
}
170171

171172
@Override
@@ -839,20 +840,21 @@ private void exportRequest(SpanData span) {
839840
exportEvents(span, operationName, samplingPercentage);
840841
}
841842

842-
private static boolean getSuccess(SpanData span) {
843-
if (span.getStatus().getStatusCode() == StatusCode.ERROR) {
844-
return false;
845-
}
846-
if (span.getStatus().getStatusCode() == StatusCode.OK) {
847-
// auto-instrumentation never sets OK, so this is explicit user override
848-
return true;
849-
}
850-
Long statusCode = span.getAttributes().get(SemanticAttributes.HTTP_STATUS_CODE);
851-
if (statusCode == null) {
852-
return true;
843+
private boolean getSuccess(SpanData span) {
844+
switch (span.getStatus().getStatusCode()) {
845+
case ERROR:
846+
return false;
847+
case OK:
848+
// auto-instrumentation never sets OK, so this is explicit user override
849+
return true;
850+
case UNSET:
851+
if (captureHttpServer4xxAsError) {
852+
Long statusCode = span.getAttributes().get(SemanticAttributes.HTTP_STATUS_CODE);
853+
return statusCode == null || statusCode < 400;
854+
}
855+
return true;
853856
}
854-
// override default OpenTelemetry mapping of status codes 4xx
855-
return statusCode < 400;
857+
return true;
856858
}
857859

858860
@Nullable

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/OpenTelemetryConfigurer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ private static BatchSpanProcessor createExporter(Configuration configuration) {
131131
// Reversing the order of processors before passing it to SpanProcessor
132132
Collections.reverse(processors);
133133

134-
SpanExporter currExporter = new Exporter(TelemetryClient.getActive());
134+
SpanExporter currExporter =
135+
new Exporter(
136+
TelemetryClient.getActive(), configuration.preview.captureHttpServer4xxAsError);
135137

136138
// NOTE if changing the span processor to something async, flush it in the shutdown hook before
137139
// flushing TelemetryClient

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/statsbeat/Feature.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ enum Feature {
5353
APACHE_CAMEL_DISABLED(22), // preview instrumentation, apache camel is ON by default in OTEL
5454
AKKA_DISABLED(23), // preview instrumentation, akka is ON by default in OTEL
5555
PROPAGATION_DISABLED(24),
56-
PLAY_DISABLED(25); // preview instrumentation, play is ON by default in OTEL
56+
PLAY_DISABLED(25), // preview instrumentation, play is ON by default in OTEL
57+
CAPTURE_HTTP_SERVER_4XX_AS_SUCCESS(26);
5758

5859
private static final Map<String, Feature> javaVendorFeatureMap;
5960

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/statsbeat/FeatureStatsbeat.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,5 +156,8 @@ void trackConfigurationOptions(Configuration config) {
156156
if (config.preview.disablePropagation) {
157157
featureList.add(Feature.PROPAGATION_DISABLED);
158158
}
159+
if (!config.preview.captureHttpServer4xxAsError) {
160+
featureList.add(Feature.CAPTURE_HTTP_SERVER_4XX_AS_SUCCESS);
161+
}
159162
}
160163
}

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ include ':test:smoke:testApps:gRPC'
8989
include ':test:smoke:testApps:HeartBeat'
9090
include ':test:smoke:testApps:HttpClients'
9191
include ':test:smoke:testApps:HttpHeaders'
92+
include ':test:smoke:testApps:HttpServer4xx'
9293
include ':test:smoke:testApps:InheritedAttributes'
9394
include ':test:smoke:testApps:Jdbc'
9495
include ':test:smoke:testApps:Jedis'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"connectionString": "InstrumentationKey=00000000-0000-0000-0000-0FEEDDADBEEF;IngestionEndpoint=http://host.docker.internal:6060/",
3+
"role": {
4+
"name": "testrolename",
5+
"instance": "testroleinstance"
6+
},
7+
"preview": {
8+
"captureHttpServer4xxAsError": false
9+
}
10+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
plugins {
2+
id("ai.smoke-test-war")
3+
}
4+
5+
dependencies {
6+
implementation("com.microsoft.azure:applicationinsights-web-auto")
7+
implementation("org.springframework.boot:spring-boot-starter-web:2.1.7.RELEASE") {
8+
exclude("org.springframework.boot", "spring-boot-starter-tomcat")
9+
}
10+
// this dependency is needed to make wildfly happy
11+
implementation("org.reactivestreams:reactive-streams:1.0.3")
12+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
package com.microsoft.applicationinsights.smoketestapp;
23+
24+
import org.springframework.boot.autoconfigure.SpringBootApplication;
25+
import org.springframework.boot.builder.SpringApplicationBuilder;
26+
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
27+
28+
@SpringBootApplication
29+
public class SpringBootApp extends SpringBootServletInitializer {
30+
@Override
31+
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
32+
return applicationBuilder.sources(SpringBootApp.class);
33+
}
34+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
package com.microsoft.applicationinsights.smoketestapp;
23+
24+
import javax.servlet.http.HttpServletResponse;
25+
import org.springframework.web.bind.annotation.GetMapping;
26+
import org.springframework.web.bind.annotation.RestController;
27+
28+
@RestController
29+
public class TestController {
30+
31+
@GetMapping("/")
32+
public String root() {
33+
return "OK";
34+
}
35+
36+
@GetMapping("/test4xx")
37+
public String test4xx(HttpServletResponse response) {
38+
response.setStatus(400);
39+
return "Not OK!";
40+
}
41+
}

0 commit comments

Comments
 (0)