Skip to content

Create cursor rules file explaining our OpenTelemetry integration #4588

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

adinauer
Copy link
Member

@adinauer adinauer commented Aug 1, 2025

#skip-changelog

📜 Description

💡 Motivation and Context

💚 How did you test it?

📝 Checklist

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

@adinauer adinauer marked this pull request as ready for review August 1, 2025 08:51
Copy link
Member Author

adinauer commented Aug 1, 2025

@adinauer adinauer requested a review from lcian as a code owner August 1, 2025 08:51
@adinauer adinauer force-pushed the 08-01-create_cursor_rules_file_explaining_our_opentelemetry_integration branch from a7e9275 to 46df387 Compare August 1, 2025 09:06
@adinauer adinauer force-pushed the feat/offline-behaviour-rules-file branch from 0dc4ab2 to 1e939de Compare August 1, 2025 09:06
@adinauer adinauer changed the base branch from feat/offline-behaviour-rules-file to graphite-base/4588 August 1, 2025 09:12
@adinauer adinauer force-pushed the 08-01-create_cursor_rules_file_explaining_our_opentelemetry_integration branch from 46df387 to 85c39af Compare August 1, 2025 09:12
@adinauer adinauer force-pushed the graphite-base/4588 branch from 1e939de to 6fc8adc Compare August 1, 2025 09:13
@graphite-app graphite-app bot changed the base branch from graphite-base/4588 to main August 1, 2025 09:13
@adinauer adinauer force-pushed the 08-01-create_cursor_rules_file_explaining_our_opentelemetry_integration branch from 85c39af to af58c24 Compare August 1, 2025 09:13
Copy link
Member

@lcian lcian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I don't think we want to add the alwaysApply as we would only apply this selectively when working on OTEL related stuff.


**Manual Integration**:
While it's possible to manually wire up all the required classes to make Sentry and OpenTelemetry work together, we do not recommend this.
It is instead preferrable to go through `SentryAutoConfigurationCustomizerProvider` so the Sentry SDK has a place to manage required classes and update it when changes are needed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"to use" instead of "go through"?

- Determine whether any Sentry OpenTelemetry integration is present
- Determine which mode to use and in turn which Sentry auto instrumentation to suppress

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`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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`.
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`.


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

OpenTelemetry SDK makes use of `io.opentelemetry.context.Scope` in `try` with 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 statement and not calling `close` (e.g. not putting it in a `finally` block in that case).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe like this? try-with-resources is the name used in the oracle docs.

Suggested change
OpenTelemetry SDK makes use of `io.opentelemetry.context.Scope` in `try` with 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 statement and not calling `close` (e.g. not putting it in a `finally` block in that case).
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).

The Sentry Java SDK provides comprehensive OpenTelemetry integration through multiple modules:

- `sentry-opentelemetry-core`: Core OpenTelemetry integration functionality
- `sentry-opentelemetry-agent`: Agent-based integration for automatic instrumentation
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call it Java Agent here as well?

@@ -0,0 +1,84 @@
# Java SDK OpenTelemetry Integration
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add the header for cursor here? See https://docs.cursor.com/en/context/rules#rule-anatomy

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

## Advantages over using Sentry without OpenTelemetry
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this section relevant for an AI?

@@ -0,0 +1,84 @@
# Java SDK OpenTelemetry Integration
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, maybe double-check against the best practices for rules in the cursor docs: https://docs.cursor.com/en/context/rules#best-practices


**Agent-based integration**:
- Automatic instrumentation via Java agent
- Can be added to any JAR when starting, no extra dependencies or code changes required. Just add the agent to the `java` command.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an example command would be helpful here.

@@ -0,0 +1,84 @@
# Java SDK OpenTelemetry Integration
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of this ruleset?
To give cursor guidance on how to develop in this module? Or to let cursor know how to use this module in a project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants