Skip to content

Commit 2d54f70

Browse files
authored
Merge branch 'main' into feat/more-ai-rules
2 parents dba4b32 + 5be3176 commit 2d54f70

File tree

324 files changed

+19146
-333
lines changed

Some content is hidden

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

324 files changed

+19146
-333
lines changed

.craft.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ targets:
1919
maven:io.sentry:sentry:
2020
maven:io.sentry:sentry-spring:
2121
maven:io.sentry:sentry-spring-jakarta:
22+
# maven:io.sentry:sentry-spring-7:
2223
maven:io.sentry:sentry-spring-boot:
2324
maven:io.sentry:sentry-spring-boot-jakarta:
2425
maven:io.sentry:sentry-spring-boot-starter:
2526
maven:io.sentry:sentry-spring-boot-starter-jakarta:
27+
# maven:io.sentry:sentry-spring-boot-4:
28+
# maven:io.sentry:sentry-spring-boot-4-starter:
2629
maven:io.sentry:sentry-servlet:
2730
maven:io.sentry:sentry-servlet-jakarta:
2831
maven:io.sentry:sentry-logback:
@@ -59,3 +62,4 @@ targets:
5962
maven:io.sentry:sentry-android-replay:
6063
maven:io.sentry:sentry-apollo-4:
6164
maven:io.sentry:sentry-reactor:
65+
maven:io.sentry:sentry-ktor-client:

.cursor/rules/offline.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
alwaysApply: true
2+
alwaysApply: false
33
description: Java SDK Offline behaviour
44
---
55
# Java SDK Offline behaviour

.cursor/rules/opentelemetry.mdc

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
alwaysApply: false
3+
description: Java SDK OpenTelemetry Integration
4+
---
5+
# Java SDK OpenTelemetry Integration
6+
7+
## Overview
8+
9+
The Sentry Java SDK provides comprehensive OpenTelemetry integration through multiple modules:
10+
11+
- `sentry-opentelemetry-core`: Core OpenTelemetry integration functionality
12+
- `sentry-opentelemetry-agent`: Java Agent-based integration for automatic instrumentation
13+
- `sentry-opentelemetry-agentless`: Manual instrumentation without Java agent
14+
- `sentry-opentelemetry-agentless-spring`: Spring-specific agentless integration
15+
- `sentry-opentelemetry-bootstrap`: Classes that go into the bootstrap classloader when the agent is used. For agentless they are simply used in the applications classloader.
16+
- `sentry-opentelemetry-agentcustomization`: Classes that help wire up Sentry in OpenTelemetry. These land in the agent classloader when the agent is used. For agentless they are simply used in the application classloader.
17+
18+
## Advantages over using Sentry without OpenTelemetry
19+
20+
- Support for more libraries and frameworks
21+
- See https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation for a list of supported libraries and frameworks
22+
- More automated Performance instrumentation (spans) created
23+
- Using `sentry-opentelemetry-agent` offers most support
24+
- Using `sentry-opentelemetry-agentless-spring` for Spring Boot also has a lot of supported libraries, altough fewer than the agent does
25+
- Note that `sentry-opentelemetry-agentless` will not have any OpenTelemetry auto instrumentation
26+
- Sentry also relies on OpenTelemetry `Context` propagation to propagate Sentry `Scopes`, ensuring e.g. that execution flow for a request shares data and does not leak data into other requests.
27+
- OpenTelemetry also offers better support for distributed tracing since more libraries are supported for attaching tracing information to outgoing requests and picking up incoming tracing information.
28+
29+
## Key Components
30+
31+
### Agent vs Agentless
32+
33+
**Java Agent-based integration**:
34+
- Automatic instrumentation via Java agent
35+
- Can be added to any JAR when starting, no extra dependencies or code changes required. Just add the agent when running the application, e.g. `SENTRY_PROPERTIES_FILE=sentry.properties JAVA_TOOL_OPTIONS="-javaagent:sentry-opentelemetry-agent.jar" java -jar your-application.jar`.
36+
- Uses OpenTelemetry Java agent with Sentry extensions
37+
- Uses bytecode manipulation
38+
39+
**Agentless-Spring integration**:
40+
- Automatic instrumentation setup via Spring Boot
41+
- Dependency needs to be added to the project.
42+
43+
**Agentless integration**:
44+
- Manual instrumentation setup
45+
- Dependency needs to be added to the project.
46+
47+
**Manual Integration**:
48+
While it's possible to manually wire up all the required classes to make Sentry and OpenTelemetry work together, we do not recommend this.
49+
It is instead preferrable to use `SentryAutoConfigurationCustomizerProvider` so the Sentry SDK has a place to manage required classes and update it when changes are needed.
50+
This way customers receive the updated config automatically as oppposed to having to update manually, wire in new classes, remove old ones etc.
51+
52+
### Integration Architecture
53+
54+
Sentry will try to locate certain classes that come with the Sentry OpenTelemetry integration to:
55+
- Determine whether any Sentry OpenTelemetry integration is present
56+
- Determine which mode to use and in turn which Sentry auto instrumentation to suppress
57+
58+
Reflection is used to search for `io.sentry.opentelemetry.OtelContextScopesStorage` and use it instead of `DefaultScopesStorage` when a Sentry OpenTelemetry integration is present at runtime. `IScopesStorage` is used to store Sentry `Scopes` instances. `DefaultScopesStorage` will use a thread local variable to store the current threads' `Scopes` whereas `OtelContextScopesStorage` makes use of OpenTelemetry SDKs `Context`. Sentry OpenTelemetry integrations configure OpenTelemetry to use `SentryOtelThreadLocalStorage` to customize restoring of the previous `Context`.
59+
60+
OpenTelemetry SDK makes use of `io.opentelemetry.context.Scope` in `try-with-resources` statements that call `close` when a code block is finished. Without customization, it would refuse to restore the previous `Context` onto the `ThreadLocal` if the current state of the `ThreadLocal` isn't the same as the one this scope was created for. Sentry changes this behaviour in `SentryScopeImpl` to restore the previous `Context` onto the `ThreadLocal` even if an inner `io.opentelemetry.context.Scope` wasn't properly cleaned up. Our thinking here is to prefer returning to a clean state as opposed to propagating the problem. The unclean state could happen, if `io.opentelemetry.context.Scope` isn't closed, e.g. when forgetting to put it in a `try-with-resources` statement and not calling `close` (e.g. not putting it in a `finally` block in that case).
61+
62+
`SentryContextStorageProvider` looks for any other `ContextStorageProvider` and forwards to that to not override any customized `ContextStorage`. If no other provider is found, `SentryOtelThreadLocalStorage` is used.
63+
64+
`SpanFactoryFactory` is used to configure Sentry to use `io.sentry.opentelemetry.OtelSpanFactory` if the class is present at runtime. Reflection is used to search for it. If the class is not available, we fall back to `DefaultSpanFactory`.
65+
66+
`DefaultSpanFactory` creates a `SentryTracer` instance when creating a transaction and spans are then created directly on the transaction via `startChild`.
67+
`OtelSpanFactory` instead creates an OpenTelemetry span and wraps it using `OtelTransactionSpanForwarder` to simulate a transaction. The `startChild` invocations on `OtelTransactionSpanForwarder` go through `OtelSpanFactory` again to create the child span.
68+
69+
## Configuration
70+
71+
We use `SentryAutoConfigurationCustomizerProvider` to configure OpenTelemetry for use with Sentry and register required classes, hooks etc.
72+
73+
## Span Processing
74+
75+
Both Sentry and OpenTelemetry API can be used to create spans. When using Sentry API, `OtelSpanFactory` is used to indirectly create a OpenTelemetry span.
76+
Regardless of API used, when an OpenTelemetry span is created, it goes through `SentrySampler` for sampling and `OtelSentrySpanProcessor` for `Scopes` forking and ensuring the trace is continued.
77+
When Sentry API is used, sampling is performed in `Scopes.createTransaction` before forwarding the call to `OtelSpanFactory`. The sampling decision and other sampling details are forwarded to `SentrySampler` and `OtelSentrySpanProcessor`.
78+
79+
When a span is finished, regardless of whether Sentry or OpenTelemetry API is used, it goes through `OtelSentrySpanProcessor` to set the end date and then through `BatchSpanProcessor` which will batch spans and then forward them to `SentrySpanExporter`.
80+
81+
`SentrySpanExporter` collects spans, then structures them to create a transaction for the local root span and attaches child spans to form a span tree.
82+
Some OpenTelemetry attributes are transformed into their corresponding Sentry data structure or format.
83+
84+
After creating the transaction with child spans `SentrySpanExporter` uses Sentry API to send the transaction to Sentry. This API call however forces the use of `DefaultSpanFactory` in order to create the required Sentry classes for sending and also to not create an infinite loop where any span created will cause a new span to be created recursively.
85+
86+
## Troubleshooting
87+
88+
To debug forking of `Scopes`, we added a reference to `parent` `Scopes` and a `creator` String to store the reason why `Scopes` were created or forked.

.github/ISSUE_TEMPLATE/bug_report_java.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ body:
2424
- sentry-spring-boot-jakarta
2525
- sentry-spring-boot-starter
2626
- sentry-spring-boot-starter-jakarta
27+
- sentry-spring-boot-4
28+
- sentry-spring-boot-4-starter
2729
- sentry-spring
2830
- sentry-spring-jakarta
31+
- sentry-spring-7
2932
- sentry-logback
3033
- sentry-log4j2
3134
- sentry-graphql

.github/workflows/integration-tests-ui-critical.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@ jobs:
5959
fail-fast: false
6060
matrix:
6161
include:
62-
- api-level: 30 # Android 11
63-
target: aosp_atd
64-
channel: canary # Necessary for ATDs
65-
arch: x86_64
6662
- api-level: 31 # Android 12
6763
target: aosp_atd
6864
channel: canary # Necessary for ATDs
@@ -75,6 +71,10 @@ jobs:
7571
target: aosp_atd
7672
channel: canary # Necessary for ATDs
7773
arch: x86_64
74+
- api-level: 35 # Android 15
75+
target: aosp_atd
76+
channel: canary # Necessary for ATDs
77+
arch: x86_64
7878
steps:
7979
- name: Checkout code
8080
uses: actions/checkout@v4

.github/workflows/system-tests-backend.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ jobs:
6363
- sample: "sentry-samples-jul"
6464
agent: "false"
6565
agent-auto-init: "true"
66+
- sample: "sentry-samples-spring-boot-4"
67+
agent: "false"
68+
agent-auto-init: "true"
69+
- sample: "sentry-samples-spring-boot-4-webflux"
70+
agent: "false"
71+
agent-auto-init: "true"
72+
# - sample: "sentry-samples-spring-boot-4-opentelemetry-noagent"
73+
# agent: "false"
74+
# agent-auto-init: "true"
75+
- sample: "sentry-samples-spring-boot-4-opentelemetry"
76+
agent: "true"
77+
agent-auto-init: "true"
78+
- sample: "sentry-samples-spring-boot-4-opentelemetry"
79+
agent: "true"
80+
agent-auto-init: "false"
81+
- sample: "sentry-samples-spring-jakarta"
82+
agent: "false"
83+
agent-auto-init: "true"
6684
steps:
6785
- uses: actions/checkout@v4
6886
with:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ distributions/
2121
sentry-spring-boot-starter-jakarta/src/main/resources/META-INF/spring.factories
2222
sentry-samples/sentry-samples-spring-boot-jakarta/spy.log
2323
sentry-mock-server.txt
24+
tomcat-server.txt
2425
spring-server.txt
26+
*.pid
2527
spy.log
2628
.kotlin
29+
**/tomcat.8080/webapps/

.sauce/sentry-uitest-android-benchmark-lite.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ espresso:
1818

1919
suites:
2020

21-
- name: "Android 11 (api 30)"
21+
- name: "Android 15 Benchmark lite (api 35)"
2222
testOptions:
2323
clearPackageData: true
2424
useTestOrchestrator: true
2525
devices:
26-
- id: Google_Pixel_3a_real # Google Pixel 3a - api 30 (11)
26+
- name: ".*"
27+
platformVersion: "15"
2728

2829
artifacts:
2930
download:

.sauce/sentry-uitest-android-benchmark.yml

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,49 +19,34 @@ espresso:
1919
suites:
2020

2121
# Devices are chosen so that there is a high-end and a low-end device for each api level
22-
- name: "Android 12 (api 31)"
22+
- name: "Android 15 (api 35)"
2323
testOptions:
2424
clearPackageData: true
2525
useTestOrchestrator: true
2626
devices:
27-
- id: Google_Pixel_6_Pro_real_us # Google Pixel 6 Pro - api 31 (12) - high end
28-
- id: Google_Pixel_5_12_real_us # Google Pixel 5 - api 31 (12) - low end
27+
- id: Google_Pixel_9_Pro_XL_15_real_sjc1 # Google Pixel 9 Pro XL - api 35 (15) - high end
28+
- id: Samsung_Galaxy_S23_15_real_sjc1 # Samsung Galaxy S23 - api 35 (15) - mid end
29+
- id: Google_Pixel_6a_15_real_sjc1 # Google Pixel 6a - api 35 (15) - low end
2930

30-
- name: "Android 11 (api 30)"
31+
- name: "Android 14 (api 34)"
3132
testOptions:
3233
clearPackageData: true
3334
useTestOrchestrator: true
3435
devices:
35-
- id: Samsung_Galaxy_S10_Plus_11_real_us # Samsung Galaxy S10+ - api 30 (11) - high end
36-
- id: Google_Pixel_4a_real_us # Google Pixel 4a - api 30 (11) - mid end
37-
- id: Google_Pixel_3a_real # Google Pixel 3a - api 30 (11) - low end
36+
- id: Google_Pixel_9_Pro_XL_real_sjc1 # Google Pixel 9 Pro XL - api 34 (14) - high end
37+
- id: Samsung_Galaxy_A54_real_sjc1 # Samsung Galaxy A54 - api 34 (14) - low end
3838

39-
- name: "Android 10 (api 29)"
39+
- name: "Android 13 (api 33)"
4040
testOptions:
4141
clearPackageData: true
4242
useTestOrchestrator: true
4343
devices:
44-
- id: Google_Pixel_3a_XL_real # Google Pixel 3a XL - api 29 (10)
45-
- id: OnePlus_6T_real # OnePlus 6T - api 29 (10)
44+
- id: Google_Pixel_7_Pro_real_us # Google Pixel 7 Pro - api 33 (13) - high end
45+
- id: Samsung_Galaxy_A32_5G_real_sjc1 # Samsung Galaxy A32 5G - api 33 (13) - low end
4646

47-
# At the time of writing (July, 4, 2022), the market share per android version is:
48-
# 12.0 = 17.54%, 11.0 = 31.65%, 10.0 = 21.92%
49-
# Using these 3 versions we cover 71,11% of all devices out there. Currently, this is enough for benchmarking scope
50-
# Leaving these devices here in case we change mind on them
51-
# devices:
52-
# - id: Samsung_Galaxy_S8_plus_real_us # Samsung Galaxy S8+ - api 28 (9)
53-
# - id: LG_G8_ThinQ_real_us # LG G8 ThinQ - api 28 (9)
54-
# - id: OnePlus_5_real_us # OnePlus 5 - api 27 (8.1.0)
55-
# - id: LG_K30_real_us1 # LG K30 - api 27 (8.1.0)
56-
# - id: HTC_10_real_us # HTC 10 - api 26 (8.0.0)
57-
# - id: Samsung_A3_real # Samsung Galaxy A3 2017 - api 26 (8.0.0)
58-
# - id: ZTE_Axon_7_real2_us # ZTE Axon 7 - api 25 (7.1.1)
59-
# - id: Motorola_Moto_X_Play_real # Motorola Moto X Play - api 25 (7.1.1)
60-
# - id: Samsung_note_5_real_us # Samsung Galaxy Note 5 - api 24 (7.0)
61-
# - id: LG_K10_real # LG K10 - api 24 (7.0)
62-
# - id: Samsung_Galaxy_S6_Edge_Plus_real # Samsung Galaxy S6 Edge+ - api 23 (6.0.1)
63-
# - id: Samsung_Tab_E_real_us # Samsung Tab E - api 23 (6.0.1)
64-
# - id: Amazon_Kindle_Fire_HD_8_real_us # Amazon Kindle Fire HD 8 - api 22 (5.1.1)
47+
# At the time of writing (August, 13, 2025), the market share per android version is:
48+
# 15.0 = 26.75%, 14.0 = 19.5%, 13 = 15.95%
49+
# Using these 3 versions we cover 62.2% of all devices out there. Currently, this is enough for benchmarking scope
6550

6651
artifacts:
6752
download:

.sauce/sentry-uitest-android-ui.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,29 @@ espresso:
1818
testApp: ./sentry-android-integration-tests/sentry-uitest-android/build/outputs/apk/androidTest/release/sentry-uitest-android-release-androidTest.apk
1919
suites:
2020

21-
- name: "Android 14 Ui test (api 34)"
21+
- name: "Android 15 Ui test (api 35)"
2222
testOptions:
2323
clearPackageData: true
2424
useTestOrchestrator: true
2525
devices:
2626
- name: ".*"
27-
platformVersion: "14"
27+
platformVersion: "15"
2828

29-
- name: "Android 13 Ui test (api 33)"
29+
- name: "Android 14 Ui test (api 34)"
3030
testOptions:
3131
clearPackageData: true
3232
useTestOrchestrator: true
3333
devices:
3434
- name: ".*"
35-
platformVersion: "13"
35+
platformVersion: "14"
3636

37-
- name: "Android 11 Ui test (api 31)"
37+
- name: "Android 13 Ui test (api 33)"
3838
testOptions:
3939
clearPackageData: true
4040
useTestOrchestrator: true
4141
devices:
4242
- name: ".*"
43-
platformVersion: "11"
43+
platformVersion: "13"
4444

4545
# Controls what artifacts to fetch when the suite on Sauce Cloud has finished.
4646
artifacts:

0 commit comments

Comments
 (0)