Skip to content

Commit 38fe0b9

Browse files
committed
Merge branch 'main' into markushi/canvas-approach
2 parents 53654eb + fbbbb13 commit 38fe0b9

File tree

516 files changed

+25072
-1432
lines changed

Some content is hidden

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

516 files changed

+25072
-1432
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/deduplication.mdc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
alwaysApply: false
3+
description: Java SDK Event deduplication
4+
---
5+
6+
# Java SDK Event deduplication
7+
8+
To avoid sending the same error multiple times, there is deduplication logic in place in the SDK.
9+
Duplicate captures can happen due to multiple integrations capturing the exception as well as additional manual calls to `Sentry.captureException`.
10+
11+
Deduplication is performed in `DuplicateEventDetectionEventProcessor` which returns `null` when it detects a duplicate event causing it to be dropped.
12+
13+
The `enableDeduplication` option can be used to opt out of deduplication. It is enabled by default.

.cursor/rules/e2e_tests.mdc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
alwaysApply: false
3+
description: Java SDK End to End Tests
4+
---
5+
6+
# Java SDK End to End Tests (System Tests)
7+
8+
The samples in the `sentry-samples` directory are used to run end to end tests against them.
9+
10+
There is a python script (`system-test-runner.py`) that can be used to run one (using `--module SAMPLE_NAME`) or all (using `--all`) system tests.
11+
12+
The script has an interactive mode (`-i`) which allows selection of test setups to execute, whether to run the tests or just prepare infrastructure for testing from IDE.
13+
14+
The tests run a mock Sentry server via `system-test-sentry-server.py`. Any system under test will then have a DSN set that reflects this local mock server like `http://502f25099c204a2fbf4cb16edc5975d1@localhost:8000/0`.
15+
By using this local DSN, the system under test sends events to the local mock server.
16+
The tests can then use `TestHelper` to assert envelopes that were received by the mock server.
17+
`TestHelper` uses HTTP requests to retrieve the JSON payload of the received events and deserialize them back to objects for easier assertion.
18+
Tests can then assert events, transactions, logs etc. similar to how they would appear in `beforeSend` and similar callbacks.
19+
20+
`TestHelper` has a lot of helper methods for asserting, e.g. by span name, log body etc.
21+
22+
The end to end tests either expect the system under test to either be running on a server or call `java -jar` to execute a CLI system under test.
23+
24+
For Spring Boot, we spin up the Spring Boot server. The tests then send requests to that server and assert what is sent to Sentry.
25+
26+
End to end tests are also executed on CI using a matrix build, as defined in `.github/workflows/system-tests-backend.yml`.
27+
28+
Some of the samples are tested in multiple ways, e.g. with OpenTelemetry Agent auto init turned on and off.

.cursor/rules/new_module.mdc

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
description: Module Addition Rules for sentry-java
3+
alwaysApply: false
4+
---
5+
# Module Addition Rules for sentry-java
6+
7+
## Overview
8+
9+
This document outlines the complete process for adding a new module to the sentry-java repository. Follow these steps in order to ensure proper integration and release management.
10+
11+
## Step-by-Step Process
12+
13+
### 1. Create the Module Structure
14+
15+
1. Create the new module, conforming to the existing naming conventions and build scripts
16+
17+
2. Add the module to the include list in `settings.gradle.kts`
18+
19+
If adding a `sentry-samples` module, also add it to the `ignoredProjects` list in the root `build.gradle.kts`:
20+
21+
```kotlin
22+
ignoredProjects.addAll(
23+
listOf(
24+
// ... existing projects ...
25+
"sentry-samples-{module-name}"
26+
)
27+
)
28+
```
29+
30+
3. If adding a JVM sample, add E2E (system) tests, following the structure we have in the existing JVM examples.
31+
The test should then be added to `test/system-test-runner.py` and `.github/workflows/system-tests-backend.yml`.
32+
33+
### 2. Create Module Documentation
34+
35+
Create a `README.md` in the module directory with the following structure:
36+
37+
```markdown
38+
# sentry-{module-name}
39+
40+
This module provides an integration for [Technology/Framework Name].
41+
42+
Please consult the documentation on how to install and use this integration in the Sentry Docs for [Android](https://docs.sentry.io/platforms/android/integrations/{module-name}/) or [Java](https://docs.sentry.io/platforms/java/tracing/instrumentation/{module-name}/).
43+
```
44+
45+
The following tasks are required only when adding a module that isn't a sample.
46+
47+
### 3. Update Main README.md
48+
49+
Add the new module to the packages table in the main `README.md` with a placeholder link to the badge:
50+
51+
```markdown
52+
| sentry-{module-name} | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.sentry/sentry-{module-name}/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.sentry/sentry-{module-name}) | |
53+
```
54+
55+
Note that the badge will only work after the module is released to Maven Central.
56+
57+
### 4. Add Documentation to docs.sentry.io
58+
59+
Add the necessary documentation to [docs.sentry.io](https://docs.sentry.io):
60+
- For Java modules: Add to Java platform docs, usually in integrations section
61+
- For Android modules: Add to Android platform docs, usually in integrations section
62+
- Include installation instructions, configuration options, and usage examples
63+
64+
### 5. Post release tasks
65+
66+
Remind the user to perform the following tasks after the module is merged and released:
67+
68+
1. Add the SDK to the Sentry release registry, following the instructions in the [sentry-release-registry README](https://github.com/getsentry/sentry-release-registry#adding-new-sdks)
69+
70+
2. Add the module to `.craft.yml` in the `sdks` section:
71+
```yaml
72+
sdks:
73+
# ... existing modules ...
74+
maven:io.sentry:sentry-{module-name}:
75+
```
76+
77+
## Module Naming Conventions
78+
79+
- Use kebab-case for module names: `sentry-{module-name}`
80+
- Follow existing patterns: `sentry-okhttp`, `sentry-apollo-4`, `sentry-spring-boot`
81+
- For version-specific modules, include the version: `sentry-apollo-3`, `sentry-apollo-4`
82+
83+
## Important Notes
84+
85+
1. **API Files**: Do not modify `.api` files manually. Run `./gradlew apiDump` to regenerate them
86+
2. **Backwards Compatibility**: Ensure new features are opt-in by default
87+
3. **Testing**: Write comprehensive tests for all new functionality
88+
4. **Documentation**: Always include proper documentation and examples

.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.

.cursor/rules/overview_dev.mdc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
alwaysApply: true
3+
description: Sentry Java SDK - Development Rules Overview
4+
---
5+
6+
# Sentry Java SDK Development Rules
7+
8+
## Always Applied Rules
9+
10+
These rules are automatically included in every conversation:
11+
- **coding.mdc**: General contributing guidelines, build commands, and workflow rules
12+
13+
## Domain-Specific Rules (Fetch Only When Needed)
14+
15+
Use the `fetch_rules` tool to include these rules when working on specific areas:
16+
17+
### Core SDK Functionality
18+
- **`scopes`**: Use when working with:
19+
- Hub/Scope management, forking, or lifecycle
20+
- `Sentry.getCurrentScopes()`, `pushScope()`, `withScope()`
21+
- `ScopeType` (GLOBAL, ISOLATION, CURRENT)
22+
- Thread-local storage, scope bleeding issues
23+
- Migration from Hub API (v7 → v8)
24+
25+
- **`deduplication`**: Use when working with:
26+
- Duplicate event detection/prevention
27+
- `DuplicateEventDetectionEventProcessor`
28+
- `enableDeduplication` option
29+
30+
- **`offline`**: Use when working with:
31+
- Caching, envelope storage/retrieval
32+
- Network failure handling, retry logic
33+
- `AsyncHttpTransport`, `EnvelopeCache`
34+
- Rate limiting, cache rotation
35+
- Android vs JVM caching differences
36+
37+
### Integration & Infrastructure
38+
- **`opentelemetry`**: Use when working with:
39+
- OpenTelemetry modules (`sentry-opentelemetry-*`)
40+
- Agent vs agentless configurations
41+
- Span processing, sampling, context propagation
42+
- `OtelSpanFactory`, `SentrySpanExporter`
43+
- Tracing, distributed tracing
44+
45+
- **`new_module`**: Use when adding a new integration or sample module
46+
47+
### Testing
48+
- **`e2e_tests`**: Use when working with:
49+
- System tests, sample applications
50+
- `system-test-runner.py`, mock Sentry server
51+
- End-to-end test infrastructure
52+
- CI system test workflows
53+
54+
## Usage Guidelines
55+
56+
1. **Start minimal**: Only include `coding.mdc` (auto-applied) for general tasks
57+
2. **Fetch on-demand**: Use `fetch_rules ["rule_name"]` when you identify specific domain work
58+
3. **Multiple rules**: Fetch multiple rules if task spans domains (e.g., `["scopes", "opentelemetry"]` for tracing scope issues)
59+
4. **Context clues**: Look for these keywords in requests to determine relevant rules:
60+
- Scope/Hub/forking → `scopes`
61+
- Duplicate/dedup → `deduplication`
62+
- OpenTelemetry/tracing/spans → `opentelemetry`
63+
- new module/integration/sample → `new_module`
64+
- Cache/offline/network → `offline`
65+
- System test/e2e/sample → `e2e_tests`

0 commit comments

Comments
 (0)