diff --git a/src/docs/accounts/quotas/manage-event-stream-guide.mdx b/src/docs/accounts/quotas/manage-event-stream-guide.mdx index ecbd83f951690..cc02249f01436 100644 --- a/src/docs/accounts/quotas/manage-event-stream-guide.mdx +++ b/src/docs/accounts/quotas/manage-event-stream-guide.mdx @@ -45,7 +45,7 @@ Check out additional configuration options with the [TryCatch](/platforms/javasc ### Other SDKs -**Java** - Sentry SDK provides integrations with common Java loggers through implemented _Handlers_ and _Appenders_. The configuration allows you to set a logging threshold determining the level under which all errors will be filtered. For more information see Java Integrations [java.util.logging](/platforms/java/guides/logging/), [Log4j 1.x](/platforms/java/guides/log4j/), [Log4j 2.x](/platforms/java/guides/log4j2/), and [Logback](/platforms/java/guides/logback/). +**Java** - Sentry SDK provides integrations with common Java loggers through implemented _Handlers_ and _Appenders_. The configuration allows you to set a logging threshold determining the level under which all errors will be filtered. For more information see Java Integrations [java.util.logging](/platforms/java/legacy/logging/), [Log4j 1.x](/platforms/java/legacy/log4j/), [Log4j 2.x](/platforms/java/guides/log4j2/), and [Logback](/platforms/java/guides/logback/). **PHP** - The `error_types` configuration option allows you to set the error types you want Sentry to monitor. For more information see [PHP: Common Options](/platforms/php/configuration/options/#common-options). diff --git a/src/includes/capture-error/java.mdx b/src/includes/capture-error/java.mdx new file mode 100644 index 0000000000000..6420827e642a3 --- /dev/null +++ b/src/includes/capture-error/java.mdx @@ -0,0 +1,11 @@ +In Java you can capture any exception object that you caught: + +```java +import io.sentry.Sentry; + +try { + aMethodThatMightFail(); +} catch(Exception e) { + Sentry.captureException(e); +} +``` diff --git a/src/includes/capture-message/java.mdx b/src/includes/capture-message/java.mdx new file mode 100644 index 0000000000000..e896fd5b9429f --- /dev/null +++ b/src/includes/capture-message/java.mdx @@ -0,0 +1,5 @@ +```java +import io.sentry.Sentry; + +Sentry.captureMessage("Something went wrong"); +``` diff --git a/src/includes/configuration/before-send/java.mdx b/src/includes/configuration/before-send/java.mdx new file mode 100644 index 0000000000000..8418050ceaa67 --- /dev/null +++ b/src/includes/configuration/before-send/java.mdx @@ -0,0 +1,17 @@ +A `BiFunction` can be used to mutate, discard (return null), or return a completely new event. + +```java +import io.sentry.Sentry; + +Sentry.init( + options -> { + options.setBeforeSend( + (event, hint) -> { + // Modify the event here: + event.setServerName(null); // Don't send server names. + return event; + }); + }); +``` + +When using [Spring Boot integration](/platforms/java/guides/spring-boot/), `beforeSend` can be registered simply by creating a Spring `bean` implementing `BeforeSendCallback`. See [Spring Boot integration](/platforms/java/guides/spring-boot/#registering-custom-before-send-callback) for more details. diff --git a/src/includes/configuration/config-intro/java.mdx b/src/includes/configuration/config-intro/java.mdx new file mode 100644 index 0000000000000..de753215640f4 --- /dev/null +++ b/src/includes/configuration/config-intro/java.mdx @@ -0,0 +1,45 @@ +Options can be set by passing a callback to the `init()` method which will +pass the option object along for modifications: + +```java {tabTitle:Java} +import io.sentry.Sentry; + +public class MyClass { + public static void main(String... args) { + Sentry.init( + options -> { + // your Sentry project/dashboard + options.setDsn("___PUBLIC_DSN___"); + options.setRelease("io.sentry.samples.console@3.0.0+1"); + options.setBeforeSend( + (event, hint) -> { + // Drop an event altogether: + if (event.getTag("SomeTag") != null) { + return null; + } + return event; + }); + }); + } +} +``` + +```kotlin {tabTitle:Kotlin} +import io.sentry.SentryOptions.BeforeSendCallback + +fun main() { + Sentry.init { + // your Sentry project/dashboard + it.dsn = "___PUBLIC_DSN___" + it.release = "io.sentry.samples.console@3.0.0+1" + it.beforeSend = BeforeSendCallback { event: SentryEvent, hint: Any? -> + // Drop an event altogether: + if (event.getTag("SomeTag") != null) { + null + } else { + event + } + } + } +} +``` diff --git a/src/includes/configuration/decluttering/java.mdx b/src/includes/configuration/decluttering/java.mdx new file mode 100644 index 0000000000000..2ddd4be51949e --- /dev/null +++ b/src/includes/configuration/decluttering/java.mdx @@ -0,0 +1,3 @@ +### Decluttering Sentry + +When used together with one of the logging framework integrations, the Java SDK captures all error logs as events. If you see a particular kind of error very often that has a `logger` tag, you can ignore that particular logger entirely. For more information see our Logback or Log4j 2.x integration. diff --git a/src/includes/configuration/drain-example/java.mdx b/src/includes/configuration/drain-example/java.mdx new file mode 100644 index 0000000000000..623b29c219b47 --- /dev/null +++ b/src/includes/configuration/drain-example/java.mdx @@ -0,0 +1 @@ +The Java SDK automatically shuts down on JVM exit and waits `shutdownTimeout` milliseconds before that happens. diff --git a/src/includes/configuration/sample-rate/java.mdx b/src/includes/configuration/sample-rate/java.mdx new file mode 100644 index 0000000000000..8b730abb1d0fd --- /dev/null +++ b/src/includes/configuration/sample-rate/java.mdx @@ -0,0 +1,8 @@ +```java +import io.sentry.Sentry; + +Sentry.init( + options -> { + options.setSampleRate(0.25); + }); +``` diff --git a/src/includes/set-environment/java.mdx b/src/includes/set-environment/java.mdx new file mode 100644 index 0000000000000..b747b34e9178f --- /dev/null +++ b/src/includes/set-environment/java.mdx @@ -0,0 +1,5 @@ +```java +Sentry.init(options -> { + options.setEnvironment("production"); +}); +``` diff --git a/src/includes/set-release/java.mdx b/src/includes/set-release/java.mdx new file mode 100644 index 0000000000000..91dbd8e0522fb --- /dev/null +++ b/src/includes/set-release/java.mdx @@ -0,0 +1,7 @@ +```java +Sentry.init(options -> { + options.setRelease("my-project-name@2.3.12"); +}); +``` + +When using Sentry in Spring Boot application, thanks to Spring Boot Starter the release field is set automatically. Read more in [Spring Boot Starter](/platforms/java/guides/spring-boot/#using-git-commit-id-as-the-release) guide. diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9f6f151bc0415..f73364f13f922 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -25,7 +25,7 @@ const HIGHLIGHTED_PLATFORMS = [ "php.laravel", "android", "apple", - "java.spring", + "java.spring-boot", "ruby.rails", ]; diff --git a/src/platforms/common/configuration/options.mdx b/src/platforms/common/configuration/options.mdx index 88edd681ab4b9..e53654d59d7fe 100644 --- a/src/platforms/common/configuration/options.mdx +++ b/src/platforms/common/configuration/options.mdx @@ -73,7 +73,7 @@ Grouping in Sentry is different for events with stack traces and without. As a r - + If this flag is enabled, certain personally identifiable information (PII) is added by active integrations. By default, no such data is sent. @@ -81,7 +81,7 @@ If possible, we recommended turning on this feature to send all such data by def - + This option can be used to supply a "server name." When provided, the name of the server is sent along and persisted in the event. For many integrations the server name actually corresponds to the device hostname, even in situations where the machine is not actually a server. Most SDKs will attempt to auto-discover this value. @@ -101,13 +101,13 @@ will be sent. This is a "contains" match to the entire file URL. As a result, if - + A list of string prefixes of module names that belong to the app. This option takes precedence over `in-app-exclude`. - + A list of string prefixes of module names that do not belong to the app, but rather to third-party packages. Modules considered not part of the app will be hidden from stack traces by default. @@ -177,19 +177,19 @@ The callback typically gets a second argument (called a "hint") which contains t - + ## Transport Options Transports are used to send events to Sentry. Transports can be customized to some degree to better support highly specific deployments. - + Switches out the transport used to send events. How this works depends on the SDK. It can, for instance, be used to capture events for unit-testing or to send it through some more complex setup that requires proxy authentication. - + When set, a proxy can be configured that should be used for outbound requests. This is also used for HTTPS requests unless a separate `https-proxy` is configured. However, not all SDKs support a separate HTTPS proxy. SDKs will attempt to default to the system-wide configured proxy, if possible. For instance, on Unix systems, the `http_proxy` environment variable will be picked up. @@ -201,7 +201,7 @@ Configures a separate proxy for outgoing HTTPS requests. This value might not be - + Controls how many seconds to wait before shutting down. Sentry SDKs send events from a background queue. This queue is given a certain amount to drain pending events. The default is SDK specific but typically around two seconds. Setting this value too low may cause problems for sending events from command line applications. Setting the value too high will cause the application to block for a long time for users experiencing network connectivity problems. diff --git a/src/platforms/common/configuration/releases.mdx b/src/platforms/common/configuration/releases.mdx index adb02e67b3401..80988babbecdc 100644 --- a/src/platforms/common/configuration/releases.mdx +++ b/src/platforms/common/configuration/releases.mdx @@ -13,7 +13,7 @@ A release is a version of your code that is deployed to an environment. When you - Resolve issues by including the issue number in your commit message - Receive email notifications when your code gets deployed - + Additionally, releases are used for applying [source maps](/platforms/javascript/sourcemaps/) to minified JavaScript to view original, untransformed source code. diff --git a/src/platforms/java/common/configuration/index.mdx b/src/platforms/java/common/configuration/index.mdx new file mode 100644 index 0000000000000..ce6c9f59de767 --- /dev/null +++ b/src/platforms/java/common/configuration/index.mdx @@ -0,0 +1,165 @@ +--- +title: Configuration +sidebar_order: 10 +description: "Learn more about how to configure the SDK. These options are set when the SDK is first initialized, passed to the `init()` as an object." +--- + +## Setting the DSN (Data Source Name) {#setting-the-dsn} + +The DSN is the first and most important thing to configure because it tells the SDK where to send events. You can find your project’s DSN in the “Client Keys” section of your “Project Settings” in Sentry. It can be configured in multiple ways. Explanations of the [configuration methods are detailed below](#configuration-methods). + +In a properties file on your filesystem or classpath (defaults to `sentry.properties`): + +```text {tabTitle:Properties File} {filename:sentry.properties} +dsn=___PUBLIC_DSN___ +``` + +Via the Java System Properties _(not available on Android)_: + +```bash {tabTitle:Java System Properties} +java -Dsentry.dsn=___PUBLIC_DSN___ -jar app.jar +``` + +Via a System Environment Variable _(not available on Android)_: + +```bash {tabTitle:System Environment Variable} +SENTRY_DSN=___PUBLIC_DSN___ java -jar app.jar +``` + +In code: + +```java +import io.sentry.Sentry; + +Sentry.init(options -> { + options.setDsn("___PUBLIC_DSN___"); +}); +``` + +## Configuration methods {#configuration-methods} + +There are multiple ways to configure the Java SDK, but all of them take the same options. See below for how to use each configuration method and how the option names might differ between them. + +To enable loading configuration from the properties file, system properties or environment variables, `enableExternalConfiguration` has to be set to `true` on `SentryOptions`: + +```java +import io.sentry.Sentry; + +Sentry.init(options -> { + options.setEnableExternalConfiguration(true); +}); +``` + +### Configuration via properties file + +The Java SDK can be configured via a [.properties file](https://en.wikipedia.org/wiki/.properties) that is located on the filesystem or in your application’s classpath. By default the SDK will look for a `sentry.properties` file in the application’s current working directory or in the root of your classpath. In most server side applications the default directory to add resources to your classpath is `src/main/resources/`, and on Android the default is `app/src/main/resources/`. You can override the location of the properties file by using either the `sentry.properties.file` Java System Property or the `SENTRY_PROPERTIES_FILE` System Environment Variable. + +Because this file is often bundled with your application, the values cannot be changed easily once your application has been packaged. For this reason, the properties file is useful for setting defaults or options that you don’t expect to change often. The properties file is the last place checked for each option value, so runtime configuration (described below) will override it if available. + +Option names in the property file exactly match the examples given below. For example, to configure the environment, in your properties file: + +```properties +environment=production +``` + +### Configuration via the runtime environment + +This is the most flexible method for configuring the Sentry client because it can be easily changed based on the environment you run your application in. _Neither Java System Properties or System Environment Variables are available for Android applications. Please configure Sentry for Android via code or the properties file._ + +Two methods are available for runtime configuration, checked in this order: Java System Properties and System Environment Variables. + +Java System Property option names are exactly like the examples given below except that they are prefixed with `sentry.`. For example, to enable sampling: + +```bash +java -Dsentry.environment=production -jar app.jar +``` + +System Environment Variable option names require that you replace the `.` with `_`, capitalize them, and add a `SENTRY_` prefix. For example, to enable sampling: + +```bash +SENTRY_ENVIRONMENT=production java -jar app.jar +``` + +### Configuration via code + +The DSN itself can also be configured directly in code: + +```java +import io.sentry.Sentry; + +Sentry.init(options -> { + options.setDsn("___PUBLIC_DSN___"); +}); +``` + +By passing a hardcoded DSN you are no longer able to override the DSN at runtime via Java System Properties or System Environment Variables. + +## Options + +The following options can all be configured as described above: via a `sentry.properties` file, via Java System Properties, via System Environment variables, or via the DSN. + +### Release + +To set the application version that will be sent with each event, use the `release` option: + +``` +release=1.0.0 +``` + +#### Distribution + +To set the application distribution that will be sent with each event, use the `dist` option: + +``` +release=1.0.0 +dist=x86 +``` + +The distribution is only useful (and used) if the `release` is also set. + +### Environment + +To set the application environment that will be sent with each event, use the `environment` option: + +``` +environment=staging +``` + +### Server Name + +To set the server name that will be sent with each event, use the `servername` option: + +``` +servername=host1 +``` + +## Using a Proxy + +If your application needs to send outbound requests through an HTTP proxy, you can configure the proxy information via JVM networking properties or as a Sentry option. + +For example, using JVM networking properties (affects the entire JVM process), + +```bash +java \ + # if you are using the HTTP protocol \ + -Dhttp.proxyHost=proxy.example.com \ + -Dhttp.proxyPort=8080 \ + \ + # if you are using the HTTPS protocol \ + -Dhttps.proxyHost=proxy.example.com \ + -Dhttps.proxyPort=8080 \ + \ + # relevant to both HTTP and HTTPS + -Dhttp.nonProxyHosts=”localhost|host.example.com” \ + \ + MyApp +``` + +See [Java Networking and Proxies](http://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html) for more information about the proxy properties. + +Alternatively, using Sentry options (only affects the Sentry HTTP client, useful inside shared application containers), + +``` +http.proxy.host=proxy.example.com +http.proxy.port=8080 +``` diff --git a/src/platforms/java/common/configuration/options.mdx b/src/platforms/java/common/configuration/options.mdx index 6ea9bdb6fdc79..e69de29bb2d1d 100644 --- a/src/platforms/java/common/configuration/options.mdx +++ b/src/platforms/java/common/configuration/options.mdx @@ -1,464 +0,0 @@ ---- -title: Basic Options -sidebar_order: 0 -description: "Learn more about how to configure the SDK. These options are set when the SDK is first initialized, passed to the `init()` as an object." -redirect_from: - - /clients/java/config/ ---- - -## Setting the DSN (Data Source Name) {#setting-the-dsn} - -The DSN is the first and most important thing to configure because it tells the SDK where to send events. You can find your project’s DSN in the “Client Keys” section of your “Project Settings” in Sentry. It can be configured in multiple ways. Explanations of the [configuration methods are detailed below](#configuration-methods). - -In a properties file on your filesystem or classpath (defaults to `sentry.properties`): - -```text {tabTitle:Properties File} {filename:sentry.properties} -dsn=___PUBLIC_DSN___ -``` - -Via the Java System Properties _(not available on Android)_: - -```bash {tabTitle:Java System Properties} -java -Dsentry.dsn=___PUBLIC_DSN___ -jar app.jar -``` - -Via a System Environment Variable _(not available on Android)_: - -```bash {tabTitle:System Environment Variable} -SENTRY_DSN=___PUBLIC_DSN___ java -jar app.jar -``` - -In code: - -```java -import io.sentry.Sentry; - -Sentry.init("___PUBLIC_DSN___"); -``` - -## Configuration methods {#configuration-methods} - -There are multiple ways to configure the Java SDK, but all of them take the same options. See below for how to use each configuration method and how the option names might differ between them. - -### Configuration via properties file - -The Java SDK can be configured via a [.properties file](https://en.wikipedia.org/wiki/.properties) that is located on the filesystem or in your application’s classpath. By default the SDK will look for a `sentry.properties` file in the application’s current working directory or in the root of your classpath. In most server side applications the default directory to add resources to your classpath is `src/main/resources/`, and on Android the default is `app/src/main/resources/`. You can override the location of the properties file by using either the `sentry.properties.file` Java System Property or the `SENTRY_PROPERTIES_FILE` System Environment Variable. - -Because this file is often bundled with your application, the values cannot be changed easily once your application has been packaged. For this reason, the properties file is useful for setting defaults or options that you don’t expect to change often. The properties file is the last place checked for each option value, so runtime configuration (described below) will override it if available. - -Option names in the property file exactly match the examples given below. For example, to enable sampling, in your properties file: - -```properties -sample.rate=0.75 -``` - -### Configuration via the runtime environment - -This is the most flexible method for configuring the Sentry client because it can be easily changed based on the environment you run your application in. _Neither Java System Properties or System Environment Variables are available for Android applications. Please configure Sentry for Android via code or the properties file._ - -Two methods are available for runtime configuration, checked in this order: Java System Properties and System Environment Variables. - -Java System Property option names are exactly like the examples given below except that they are prefixed with `sentry.`. For example, to enable sampling: - -```bash -java -Dsentry.sample.rate=0.75 -jar app.jar -``` - -System Environment Variable option names require that you replace the `.` with `_`, capitalize them, and add a `SENTRY_` prefix. For example, to enable sampling: - -```bash -SENTRY_SAMPLE_RATE=0.75 java -jar app.jar -``` - -### Configuration via code - -The DSN itself can also be configured directly in code: - -```java -import io.sentry.Sentry; - -Sentry.init("___PUBLIC_DSN___"); -``` - -Sentry **will not** be able to do anything with events until this line is run, so this method of configuration is not recommended if you might have errors occur during startup. In addition, by passing a hardcoded DSN you are no longer able to override the DSN at runtime via Java System Properties or System Environment Variables. - -### Configuration via the DSN - -The SDK can also be configured by setting querystring parameters on the DSN itself. This is a bit recursive because your DSN itself is an option that you must set somewhere (and not in the DSN!). - -Option names in the DSN exactly match the examples given below. For example, to enable sampling if you are setting your DSN via the environment: - -```bash -SENTRY_DSN={DSN}/1?sample.rate=0.75 java -jar app.jar -``` - -You can, of course, pass this DSN in using the other methods described above. - -## Options - -The following options can all be configured as described above: via a `sentry.properties` file, via Java System Properties, via System Environment variables, or via the DSN. - -### Release - -To set the application version that will be sent with each event, use the `release` option: - -``` -release=1.0.0 -``` - -#### Distribution - -To set the application distribution that will be sent with each event, use the `dist` option: - -``` -release=1.0.0 -dist=x86 -``` - -The distribution is only useful (and used) if the `release` is also set. - -### Environment - -To set the application environment that will be sent with each event, use the `environment` option: - -``` -environment=staging -``` - -### Server Name - -To set the server name that will be sent with each event, use the `servername` option: - -``` -servername=host1 -``` - -### Tags - -To set tags that will be sent with each event, use the `tags` option with comma separated pairs of keys and values that are joined by a colon: - -``` -tags=tag1:value1,tag2:value2 -``` - -### MDC Tags - -To set tag names that are extracted from the SLF4J MDC system, use the `mdctags` option with comma separated key names. This option is only useful when you're using one of the logging integrations. - -``` -mdctags=foo,bar -``` - -```java -import org.slf4j.MDC; - -MDC.put("foo", "value1"); -MDC.put("bar", "value2"); - -// This sends an event where the 'foo' and 'bar' MDC values are set as additional tags -logger.error("This is a test"); -``` - -### Extra Data - -To set extra data that will be sent with each event (but not as tags), use the `extra` option with comma separated pairs of keys and values that are joined by a colon: - -``` -extra=key1:value1,key2:value2 -``` - -### “In Application” Stack Frames - -Sentry differentiates stack frames that are directly related to your application (“in application”) from stack frames that come from other packages such as the standard library, frameworks, or other dependencies. The difference is visible in the Sentry web interface where only the “in application” frames are displayed by default. - -You can configure which package prefixes your application uses with the `stacktrace.app.packages` option, which takes a comma separated list. - -``` -stacktrace.app.packages=com.mycompany,com.other.name -``` - -If you don’t want to use this feature but want to disable the warning, simply set it to an empty string: - -``` -stacktrace.app.packages= -``` - -#### Same Frame as Enclosing Exception - -Sentry can use the “in application” system to hide frames in chained exceptions. Usually when a StackTrace is printed, the result looks like this: - -``` -HighLevelException: MidLevelException: LowLevelException - at Main.a(Main.java:13) - at Main.main(Main.java:4) -Caused by: MidLevelException: LowLevelException - at Main.c(Main.java:23) - at Main.b(Main.java:17) - at Main.a(Main.java:11) - ... 1 more -Caused by: LowLevelException - at Main.e(Main.java:30) - at Main.d(Main.java:27) - at Main.c(Main.java:21) - ... 3 more -``` - -Some frames are replaced by the `... N more` line as they are the same frames as in the enclosing exception. - -A similar behavior is enabled by default in Sentry. To disable it, use the `stacktrace.hidecommon` option. - -``` -stacktrace.hidecommon=false -``` - -### Event Sampling - -Sentry can be configured to sample events with the `sample.rate` option: - -``` -sample.rate=0.75 -``` - -This option takes a number from 0.0 to 1.0, representing the percent of events to allow through to server (from 0% to 100%). By default all events will be sent to the Sentry server. - -### Uncaught Exception Handler - -By default, an `UncaughtExceptionHandler` is configured that will attempt to send exceptions to Sentry. To disable it, use the `uncaught.handler.enabled` option. Exceptions are sent asynchronously by default, and there is **no guarantee** they will be sent before the JVM exits. This option is best used in conjunction with the disk buffering system described below. - -``` -uncaught.handler.enabled=false -``` - -### Buffering Events to Disk - -Sentry can be configured to write events to a specified directory on disk anytime communication with the Sentry server fails with the `buffer.dir` option. If the directory doesn’t exist, Sentry will attempt to create it on startup and may therefore need write permission on the parent directory. Sentry always requires write permission on the buffer directory itself. This is enabled by default if the `AndroidSentryClientFactory` is used. - -``` -buffer.dir=sentry-events -``` - -The maximum number of events that will be stored on disk defaults to 10, but can also be configured with the option `buffer.size`: - -``` -buffer.size=100 -``` - -If a buffer directory is provided, a background thread will periodically attempt to re-send the events that are found on disk. By default it will attempt to send events every 60 seconds. You can change this with the `buffer.flushtime` option (in milliseconds): - -``` -buffer.flushtime=10000 -``` - - - -The Java SDK currently uses the native Java serialization system to write out events to the filesystem when buffering is enabled. Due to weaknesses in the Java serialization system it is possible for users that have write access to the `buffer.dir` directory to cause the Java SDK to deserialize arbitrary Java classes. In extreme cases this might lead to the ability to execute code. - - - -#### Graceful Shutdown of Buffering (Advanced) - -In order to shutdown the buffer flushing thread gracefully, a `ShutdownHook` is created. By default, the buffer flushing thread is given 1 second to shutdown gracefully, but this can be adjusted via `buffer.shutdowntimeout` (represented in milliseconds): - -``` -buffer.shutdowntimeout=5000 -``` - -The special value `-1` can be used to disable the timeout and wait indefinitely for the executor to terminate. - -The `ShutdownHook` could lead to memory leaks in an environment where the life cycle of Sentry doesn’t match the life cycle of the JVM. - -An example would be in a JEE environment where the application using Sentry could be deployed and undeployed regularly. - -To avoid this behavior, it is possible to disable the graceful shutdown by setting the `buffer.gracefulshutdown` option: - -``` -buffer.gracefulshutdown=false -``` - -### Async Connection - -In order to avoid performance issues due to a large amount of logs being generated or a slow connection to the Sentry server, an asynchronous connection is set up, using a low priority thread pool to submit events to Sentry. - -To disable the async mode, add `async=false` to your options: - -``` -async=false -``` - -#### Graceful Shutdown of Async (Advanced) - -In order to shutdown the asynchronous connection gracefully, a `ShutdownHook` is created. By default, the asynchronous connection is given 1 second to shutdown gracefully, but this can be adjusted via `async.shutdowntimeout` (represented in milliseconds): - -``` -async.shutdowntimeout=5000 -``` - -The special value `-1` can be used to disable the timeout and wait indefinitely for the executor to terminate. - -The `ShutdownHook` could lead to memory leaks in an environment where the life cycle of Sentry doesn’t match the life cycle of the JVM. - -An example would be in a JEE environment where the application using Sentry could be deployed and undeployed regularly. - -To avoid this behavior, it is possible to disable the graceful shutdown. This might lead to some log entries being lost if the log application doesn’t shut down the `SentryClient` instance nicely. - -The option to do so is `async.gracefulshutdown`: - -``` -async.gracefulshutdown=false -``` - -#### Async Queue Size (Advanced) - -The default queue used to store unprocessed events is limited to 50 items. Additional items added once the queue is full are dropped and never sent to the Sentry server. Depending on the environment (if the memory is sparse) it is important to be able to control the size of that queue to avoid memory issues. - -It is possible to set a maximum with the option `async.queuesize`: - -``` -async.queuesize=100 -``` - -This means that if the connection to the Sentry server is down, only the 100 most recent events will be stored and processed as soon as the server is back up. - -The special value `-1` can be used to enable an unlimited queue. Beware that network connectivity or Sentry server issues could mean your process will run out of memory. - -#### Async Threads Count (Advanced) - -By default the thread pool used by the async connection contains one thread per processor available to the JVM. - -It’s possible to manually set the number of threads (for example if you want only one thread) with the option `async.threads`: - -``` -async.threads=1 -``` - -#### Async Threads Priority (Advanced) - -In most cases sending logs to Sentry isn’t as important as an application running smoothly, so the threads have a [minimal priority](https://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#MIN_PRIORITY). - -It is possible to customise this value to increase the priority of those threads with the option `async.priority`: - -``` -async.priority=10 -``` - -### Compression - -By default the content sent to Sentry is compressed before being sent. However, compressing and encoding the data adds a small CPU and memory hit which might not be useful if the connection to Sentry is fast and reliable. - -Depending on the limitations of the project (e.g. a mobile application with a limited connection, Sentry hosted on an external network), it can be useful to compress the data beforehand or not. - -It’s possible to manually enable/disable the compression with the option `compression` - -``` -compression=false -``` - -### Max Message Size - -By default only the first 1000 characters of a message will be sent to the server. This can be changed with the `maxmessagelength` option. - -``` -maxmessagelength=1500 -``` - -### Timeout (Advanced) - -A timeout is set to avoid blocking Sentry threads because establishing a connection is taking too long. - -It’s possible to manually set the timeout length with `timeout` (in milliseconds): - -``` -timeout=10000 -``` - -### Using a Proxy - -If your application needs to send outbound requests through an HTTP proxy, you can configure the proxy information via JVM networking properties or as a Sentry option. - -For example, using JVM networking properties (affects the entire JVM process), - -```bash -java \ - # if you are using the HTTP protocol \ - -Dhttp.proxyHost=proxy.example.com \ - -Dhttp.proxyPort=8080 \ - \ - # if you are using the HTTPS protocol \ - -Dhttps.proxyHost=proxy.example.com \ - -Dhttps.proxyPort=8080 \ - \ - # relevant to both HTTP and HTTPS - -Dhttp.nonProxyHosts=”localhost|host.example.com” \ - \ - MyApp -``` - -See [Java Networking and Proxies](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html) for more information about the proxy properties. - -Alternatively, using Sentry options (only affects the Sentry HTTP client, useful inside shared application containers), - -``` -http.proxy.host=proxy.example.com -http.proxy.port=8080 -``` - -## Custom functionality - -At times, you may require custom functionality that is not included in the Java SDK already. The most common way to do this is to create your own `SentryClientFactory` instance as seen in the example below. - -### Implementation - -```java -public class MySentryClientFactory extends DefaultSentryClientFactory { - @Override - public SentryClient createSentryClient(Dsn dsn) { - SentryClient sentryClient = new SentryClient(createConnection(dsn), getContextManager(dsn)); - - /* - Create and use the ForwardedAddressResolver, which will use the - X-FORWARDED-FOR header for the remote address if it exists. - */ - ForwardedAddressResolver forwardedAddressResolver = new ForwardedAddressResolver(); - sentryClient.addBuilderHelper(new HttpEventBuilderHelper(forwardedAddressResolver)); - - sentryClient.addBuilderHelper(new ContextBuilderHelper(sentryClient)); - return configureSentryClient(sentryClient, dsn); - } -} -``` - -### Usage - -To use your custom `SentryClientFactory` implementation, use the `factory` option: - -``` -factory=my.company.MySentryClientFactory -``` - -Your factory class will need to be available on your classpath with a zero argument constructor or an error will be thrown. - -## Linter configuration - -Sometimes linters can warn about types used by the SDK that are not available in your app. This can happen, for example, when using the Android integration due to the base SDK having JNDI lookup that takes no effect in Android. - -To get rid of the warning, configure your `lint.xml` as follows: - -```xml - - - - - -``` - -And in your Gradle plugin: - -```groovy -android { - lintOptions { - lintConfig file("path/to/lint.xml") - } -} -``` - -Where `path/to/lint.xml` is the path to the linting configuration file mentioned above. diff --git a/src/platforms/java/common/context.mdx b/src/platforms/java/common/context.mdx deleted file mode 100644 index 6609192d5e0e6..0000000000000 --- a/src/platforms/java/common/context.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Context & Breadcrumbs -sidebar_order: 3 -redirect_from: - - /clients/java/context/ ---- - -The Java SDK implements the idea of a “context” to support attaching additional information to events, such as breadcrumbs. A context may refer to a single request to a web framework, to the entire lifetime of an Android application, or something else that better suits your application’s needs. - -There is no single definition of context that applies to every application, for this reason a specific implementation must be chosen depending on what your application does and how it is structured. By default Sentry uses a `ThreadLocalContextManager` that maintains a single `Context` instance per thread. This is useful for frameworks that use one thread per user request such as those based on synchronous servlet APIs. Sentry also installs a `ServletRequestListener` that will clear the thread’s context after each servlet request finishes. - -Sentry defaults to the `SingletonContextManager` on Android, which maintains a single context instance for all threads for the lifetime of the application. - -To override the `ContextManager` you will need to override the `getContextManager` method in the `DefaultSentryClientFactory`. A simpler API will likely be provided in the future. - -## Usage - -Breadcrumbs can be used to describe actions that occurred in your application leading up to an event being sent. For example, whether external API requests were made, or whether a user clicked on something in an Android application. By default the last 100 breadcrumbs per context will be stored and sent with future events. - -The user can be set per context so that you know who was affected by each event. - -Once a `SentryClient` instance has been initialized you can begin setting state in the current context. - -```java -import io.sentry.Sentry; -import io.sentry.context.Context; -import io.sentry.event.BreadcrumbBuilder; -import io.sentry.event.UserBuilder; - -public class MyClass { - - /** - * Examples using the (recommended) static API. - */ - public void staticAPIExample() { - // Manually initialize the static client, you may also pass in a DSN and/or - // SentryClientFactory to use. Note that the client will attempt to automatically - // initialize on the first use of the static API, so this isn't strictly necessary. - Sentry.init(); - - // Note that all fields set on the context are optional. Context data is copied onto - // all future events in the current context (until the context is cleared). - - // Set the current user in the context. - Sentry.getContext().setUser( - new UserBuilder().setUsername("user1").build() - ); - - // Record a breadcrumb in the context. - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage("User did something specific again!").build() - ); - - // Add extra data to future events in this context. - Sentry.getContext().addExtra("extra", "thing"); - - // Add an additional tag to future events in this context. - Sentry.getContext().addTag("tagName", "tagValue"); - - // Send an event with the context data attached. - Sentry.capture("New event message"); - - // Clear the context, useful if you need to add hooks in a framework - // to empty context between requests. - Sentry.clearContext(); - } - - /** - * Examples that use the SentryClient instance directly. - */ - public void instanceAPIExample() { - // Create a SentryClient instance that you manage manually. - SentryClient sentryClient = SentryClientFactory.sentryClient(); - - // Get the current context instance. - Context context = sentryClient.getContext(); - - // Note that all fields set on the context are optional. Context data is copied onto - // all future events in the current context (until the context is cleared). - - // Set the current user in the context. - context.setUser( - new UserBuilder().setUsername("user1").build() - ); - - // Record a breadcrumb in the context. - context.recordBreadcrumb( - new BreadcrumbBuilder().setMessage("User did something specific!").build() - ); - - // Add extra data to future events in this context. - context.addExtra("extra", "thing"); - - // Add an additional tag to future events in this context. - context.addTag("tagName", "tagValue"); - - // Send an event with the context data attached. - sentryClient.sendMessage("New event message"); - - // Clear the context, useful if you need to add hooks in a framework - // to empty context between requests. - context.clear(); - } -} -``` diff --git a/src/platforms/java/common/legacy/configuration/index.mdx b/src/platforms/java/common/legacy/configuration/index.mdx new file mode 100644 index 0000000000000..ea7cbf20a675d --- /dev/null +++ b/src/platforms/java/common/legacy/configuration/index.mdx @@ -0,0 +1,467 @@ +--- +title: Configuration +sidebar_order: 10 +description: "Learn more about how to configure the SDK. These options are set when the SDK is first initialized, passed to the `init()` as an object." +--- + + + +A new Java SDK has superseded this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the [updated Java SDK](/platforms/java/) for new projects. + + +## Setting the DSN (Data Source Name) {#setting-the-dsn} + +The DSN is the first and most important thing to configure because it tells the SDK where to send events. You can find your project’s DSN in the “Client Keys” section of your “Project Settings” in Sentry. It can be configured in multiple ways. Explanations of the [configuration methods are detailed below](#configuration-methods). + +In a properties file on your filesystem or classpath (defaults to `sentry.properties`): + +```text {tabTitle:Properties File} {filename:sentry.properties} +dsn=___PUBLIC_DSN___ +``` + +Via the Java System Properties _(not available on Android)_: + +```bash {tabTitle:Java System Properties} +java -Dsentry.dsn=___PUBLIC_DSN___ -jar app.jar +``` + +Via a System Environment Variable _(not available on Android)_: + +```bash {tabTitle:System Environment Variable} +SENTRY_DSN=___PUBLIC_DSN___ java -jar app.jar +``` + +In code: + +```java +import io.sentry.Sentry; + +Sentry.init("___PUBLIC_DSN___"); +``` + +## Configuration methods {#configuration-methods} + +There are multiple ways to configure the Java SDK, but all of them take the same options. See below for how to use each configuration method and how the option names might differ between them. + +### Configuration via properties file + +The Java SDK can be configured via a [.properties file](https://en.wikipedia.org/wiki/.properties) that is located on the filesystem or in your application’s classpath. By default the SDK will look for a `sentry.properties` file in the application’s current working directory or in the root of your classpath. In most server side applications the default directory to add resources to your classpath is `src/main/resources/`, and on Android the default is `app/src/main/resources/`. You can override the location of the properties file by using either the `sentry.properties.file` Java System Property or the `SENTRY_PROPERTIES_FILE` System Environment Variable. + +Because this file is often bundled with your application, the values cannot be changed easily once your application has been packaged. For this reason, the properties file is useful for setting defaults or options that you don’t expect to change often. The properties file is the last place checked for each option value, so runtime configuration (described below) will override it if available. + +Option names in the property file exactly match the examples given below. For example, to enable sampling, in your properties file: + +```properties +sample.rate=0.75 +``` + +### Configuration via the runtime environment + +This is the most flexible method for configuring the Sentry client because it can be easily changed based on the environment you run your application in. _Neither Java System Properties or System Environment Variables are available for Android applications. Please configure Sentry for Android via code or the properties file._ + +Two methods are available for runtime configuration, checked in this order: Java System Properties and System Environment Variables. + +Java System Property option names are exactly like the examples given below except that they are prefixed with `sentry.`. For example, to enable sampling: + +```bash +java -Dsentry.sample.rate=0.75 -jar app.jar +``` + +System Environment Variable option names require that you replace the `.` with `_`, capitalize them, and add a `SENTRY_` prefix. For example, to enable sampling: + +```bash +SENTRY_SAMPLE_RATE=0.75 java -jar app.jar +``` + +### Configuration via code + +The DSN itself can also be configured directly in code: + +```java +import io.sentry.Sentry; + +Sentry.init("___PUBLIC_DSN___"); +``` + +Sentry **will not** be able to do anything with events until this line is run, so this method of configuration is not recommended if you might have errors occur during startup. In addition, by passing a hardcoded DSN you are no longer able to override the DSN at runtime via Java System Properties or System Environment Variables. + +### Configuration via the DSN + +The SDK can also be configured by setting querystring parameters on the DSN itself. This is a bit recursive because your DSN itself is an option that you must set somewhere (and not in the DSN!). + +Option names in the DSN exactly match the examples given below. For example, to enable sampling if you are setting your DSN via the environment: + +```bash +SENTRY_DSN={DSN}/1?sample.rate=0.75 java -jar app.jar +``` + +You can, of course, pass this DSN in using the other methods described above. + +## Options + +The following options can all be configured as described above: via a `sentry.properties` file, via Java System Properties, via System Environment variables, or via the DSN. + +### Release + +To set the application version that will be sent with each event, use the `release` option: + +``` +release=1.0.0 +``` + +#### Distribution + +To set the application distribution that will be sent with each event, use the `dist` option: + +``` +release=1.0.0 +dist=x86 +``` + +The distribution is only useful (and used) if the `release` is also set. + +### Environment + +To set the application environment that will be sent with each event, use the `environment` option: + +``` +environment=staging +``` + +### Server Name + +To set the server name that will be sent with each event, use the `servername` option: + +``` +servername=host1 +``` + +### Tags + +To set tags that will be sent with each event, use the `tags` option with comma separated pairs of keys and values that are joined by a colon: + +``` +tags=tag1:value1,tag2:value2 +``` + +### MDC Tags + +To set tag names that are extracted from the SLF4J MDC system, use the `mdctags` option with comma separated key names. This option is only useful when you're using one of the logging integrations. + +``` +mdctags=foo,bar +``` + +```java +import org.slf4j.MDC; + +MDC.put("foo", "value1"); +MDC.put("bar", "value2"); + +// This sends an event where the 'foo' and 'bar' MDC values are set as additional tags +logger.error("This is a test"); +``` + +### Extra Data + +To set extra data that will be sent with each event (but not as tags), use the `extra` option with comma separated pairs of keys and values that are joined by a colon: + +``` +extra=key1:value1,key2:value2 +``` + +### “In Application” Stack Frames + +Sentry differentiates stack frames that are directly related to your application (“in application”) from stack frames that come from other packages such as the standard library, frameworks, or other dependencies. The difference is visible in the Sentry web interface where only the “in application” frames are displayed by default. + +You can configure which package prefixes your application uses with the `stacktrace.app.packages` option, which takes a comma separated list. + +``` +stacktrace.app.packages=com.mycompany,com.other.name +``` + +If you don’t want to use this feature but want to disable the warning, simply set it to an empty string: + +``` +stacktrace.app.packages= +``` + +#### Same Frame as Enclosing Exception + +Sentry can use the “in application” system to hide frames in chained exceptions. Usually when a StackTrace is printed, the result looks like this: + +``` +HighLevelException: MidLevelException: LowLevelException + at Main.a(Main.java:13) + at Main.main(Main.java:4) +Caused by: MidLevelException: LowLevelException + at Main.c(Main.java:23) + at Main.b(Main.java:17) + at Main.a(Main.java:11) + ... 1 more +Caused by: LowLevelException + at Main.e(Main.java:30) + at Main.d(Main.java:27) + at Main.c(Main.java:21) + ... 3 more +``` + +Some frames are replaced by the `... N more` line as they are the same frames as in the enclosing exception. + +A similar behavior is enabled by default in Sentry. To disable it, use the `stacktrace.hidecommon` option. + +``` +stacktrace.hidecommon=false +``` + +### Event Sampling + +Sentry can be configured to sample events with the `sample.rate` option: + +``` +sample.rate=0.75 +``` + +This option takes a number from 0.0 to 1.0, representing the percent of events to allow through to server (from 0% to 100%). By default all events will be sent to the Sentry server. + +### Uncaught Exception Handler + +By default, an `UncaughtExceptionHandler` is configured that will attempt to send exceptions to Sentry. To disable it, use the `uncaught.handler.enabled` option. Exceptions are sent asynchronously by default, and there is **no guarantee** they will be sent before the JVM exits. This option is best used in conjunction with the disk buffering system described below. + +``` +uncaught.handler.enabled=false +``` + +### Buffering Events to Disk + +Sentry can be configured to write events to a specified directory on disk anytime communication with the Sentry server fails with the `buffer.dir` option. If the directory doesn’t exist, Sentry will attempt to create it on startup and may therefore need write permission on the parent directory. Sentry always requires write permission on the buffer directory itself. This is enabled by default if the `AndroidSentryClientFactory` is used. + +``` +buffer.dir=sentry-events +``` + +The maximum number of events that will be stored on disk defaults to 10, but can also be configured with the option `buffer.size`: + +``` +buffer.size=100 +``` + +If a buffer directory is provided, a background thread will periodically attempt to re-send the events that are found on disk. By default it will attempt to send events every 60 seconds. You can change this with the `buffer.flushtime` option (in milliseconds): + +``` +buffer.flushtime=10000 +``` + + + + The Java SDK currently uses the native Java serialization system to write out events to the filesystem when buffering is enabled. Due to weaknesses in the Java serialization system it is possible for users that have write access to the `buffer.dir` directory to cause the Java SDK to deserialize arbitrary Java classes. In extreme cases this might lead to the ability to execute code. + + + +#### Graceful Shutdown of Buffering (Advanced) + +In order to shutdown the buffer flushing thread gracefully, a `ShutdownHook` is created. By default, the buffer flushing thread is given 1 second to shutdown gracefully, but this can be adjusted via `buffer.shutdowntimeout` (represented in milliseconds): + +``` +buffer.shutdowntimeout=5000 +``` + +The special value `-1` can be used to disable the timeout and wait indefinitely for the executor to terminate. + +The `ShutdownHook` could lead to memory leaks in an environment where the life cycle of Sentry doesn’t match the life cycle of the JVM. + +An example would be in a JEE environment where the application using Sentry could be deployed and undeployed regularly. + +To avoid this behavior, it is possible to disable the graceful shutdown by setting the `buffer.gracefulshutdown` option: + +``` +buffer.gracefulshutdown=false +``` + +### Async Connection + +In order to avoid performance issues due to a large amount of logs being generated or a slow connection to the Sentry server, an asynchronous connection is set up, using a low priority thread pool to submit events to Sentry. + +To disable the async mode, add `async=false` to your options: + +``` +async=false +``` + +#### Graceful Shutdown of Async (Advanced) + +In order to shutdown the asynchronous connection gracefully, a `ShutdownHook` is created. By default, the asynchronous connection is given 1 second to shutdown gracefully, but this can be adjusted via `async.shutdowntimeout` (represented in milliseconds): + +``` +async.shutdowntimeout=5000 +``` + +The special value `-1` can be used to disable the timeout and wait indefinitely for the executor to terminate. + +The `ShutdownHook` could lead to memory leaks in an environment where the life cycle of Sentry doesn’t match the life cycle of the JVM. + +An example would be in a JEE environment where the application using Sentry could be deployed and undeployed regularly. + +To avoid this behavior, it is possible to disable the graceful shutdown. This might lead to some log entries being lost if the log application doesn’t shut down the `SentryClient` instance nicely. + +The option to do so is `async.gracefulshutdown`: + +``` +async.gracefulshutdown=false +``` + +#### Async Queue Size (Advanced) + +The default queue used to store unprocessed events is limited to 50 items. Additional items added once the queue is full are dropped and never sent to the Sentry server. Depending on the environment (if the memory is sparse) it is important to be able to control the size of that queue to avoid memory issues. + +It is possible to set a maximum with the option `async.queuesize`: + +``` +async.queuesize=100 +``` + +This means that if the connection to the Sentry server is down, only the 100 most recent events will be stored and processed as soon as the server is back up. + +The special value `-1` can be used to enable an unlimited queue. Beware that network connectivity or Sentry server issues could mean your process will run out of memory. + +#### Async Threads Count (Advanced) + +By default the thread pool used by the async connection contains one thread per processor available to the JVM. + +It’s possible to manually set the number of threads (for example if you want only one thread) with the option `async.threads`: + +``` +async.threads=1 +``` + +#### Async Threads Priority (Advanced) + +In most cases sending logs to Sentry isn’t as important as an application running smoothly, so the threads have a [minimal priority](http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#MIN_PRIORITY). + +It is possible to customise this value to increase the priority of those threads with the option `async.priority`: + +``` +async.priority=10 +``` + +### Compression + +By default the content sent to Sentry is compressed before being sent. However, compressing and encoding the data adds a small CPU and memory hit which might not be useful if the connection to Sentry is fast and reliable. + +Depending on the limitations of the project (e.g. a mobile application with a limited connection, Sentry hosted on an external network), it can be useful to compress the data beforehand or not. + +It’s possible to manually enable/disable the compression with the option `compression` + +``` +compression=false +``` + +### Max Message Size + +By default only the first 1000 characters of a message will be sent to the server. This can be changed with the `maxmessagelength` option. + +``` +maxmessagelength=1500 +``` + +### Timeout (Advanced) + +A timeout is set to avoid blocking Sentry threads because establishing a connection is taking too long. + +It’s possible to manually set the timeout length with `timeout` (in milliseconds): + +``` +timeout=10000 +``` + +### Using a Proxy + +If your application needs to send outbound requests through an HTTP proxy, you can configure the proxy information via JVM networking properties or as a Sentry option. + +For example, using JVM networking properties (affects the entire JVM process), + +```bash +java \ + # if you are using the HTTP protocol \ + -Dhttp.proxyHost=proxy.example.com \ + -Dhttp.proxyPort=8080 \ + \ + # if you are using the HTTPS protocol \ + -Dhttps.proxyHost=proxy.example.com \ + -Dhttps.proxyPort=8080 \ + \ + # relevant to both HTTP and HTTPS + -Dhttp.nonProxyHosts=”localhost|host.example.com” \ + \ + MyApp +``` + +See [Java Networking and Proxies](http://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html) for more information about the proxy properties. + +Alternatively, using Sentry options (only affects the Sentry HTTP client, useful inside shared application containers), + +``` +http.proxy.host=proxy.example.com +http.proxy.port=8080 +``` + +## Custom functionality + +At times, you may require custom functionality that is not included in the Java SDK already. The most common way to do this is to create your own `SentryClientFactory` instance as seen in the example below. + +### Implementation + +```java +public class MySentryClientFactory extends DefaultSentryClientFactory { + @Override + public SentryClient createSentryClient(Dsn dsn) { + SentryClient sentryClient = new SentryClient(createConnection(dsn), getContextManager(dsn)); + + /* + Create and use the ForwardedAddressResolver, which will use the + X-FORWARDED-FOR header for the remote address if it exists. + */ + ForwardedAddressResolver forwardedAddressResolver = new ForwardedAddressResolver(); + sentryClient.addBuilderHelper(new HttpEventBuilderHelper(forwardedAddressResolver)); + + sentryClient.addBuilderHelper(new ContextBuilderHelper(sentryClient)); + return configureSentryClient(sentryClient, dsn); + } +} +``` + +### Usage + +To use your custom `SentryClientFactory` implementation, use the `factory` option: + +``` +factory=my.company.MySentryClientFactory +``` + +Your factory class will need to be available on your classpath with a zero argument constructor or an error will be thrown. + +## Linter configuration + +Sometimes linters can warn about types used by the SDK that are not available in your app. This can happen, for example, when using the Android integration due to the base SDK having JNDI lookup that takes no effect in Android. + +To get rid of the warning, configure your `lint.xml` as follows: + +```xml + + + + + +``` + +And in your Gradle plugin: + +```groovy +android { + lintOptions { + lintConfig file("path/to/lint.xml") + } +} +``` + +Where `path/to/lint.xml` is the path to the linting configuration file mentioned above. diff --git a/src/platforms/java/guides/google-app-engine/index.mdx b/src/platforms/java/common/legacy/google-app-engine/index.mdx similarity index 87% rename from src/platforms/java/guides/google-app-engine/index.mdx rename to src/platforms/java/common/legacy/google-app-engine/index.mdx index d36a2dcb4c0e2..784c17814c05d 100644 --- a/src/platforms/java/guides/google-app-engine/index.mdx +++ b/src/platforms/java/common/legacy/google-app-engine/index.mdx @@ -1,9 +1,13 @@ --- title: Google App Engine -redirect_from: - - /clients/java/modules/appengine/ +sidebar_order: 30 --- + + +An [updated Java SDK](/platforms/java/) Java SDK has superseded this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the updated Java SDK for new projects. + + The `sentry-appengine` library provides [Google App Engine](https://cloud.google.com/appengine/) support for Sentry via the [Task Queue API](https://cloud.google.com/appengine/docs/java/taskqueue/). The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-appengine). diff --git a/src/platforms/java/common/legacy/index.mdx b/src/platforms/java/common/legacy/index.mdx new file mode 100644 index 0000000000000..05a1010d22965 --- /dev/null +++ b/src/platforms/java/common/legacy/index.mdx @@ -0,0 +1,24 @@ +--- +title: Legacy SDK (1.7) +sidebar_order: 2000 +--- + +This section covers the legacy Sentry SDK for Java (1.7.x), which is no longer under active development. We **strongly encourage** updating to [the updated Java SDK](/platforms/java/). + +Find more details about how to set up, configure and use the Legacy SDK: + +- [Configuration](/platforms/java/legacy/configuration) +- [Manual Usage](/platforms/java/legacy/usage) + +## Integrations + +- [Google App Engine](/platforms/java/legacy/google-app-engine/) +- [java.util.logging](/platforms/java/legacy/logging/) +- [log4j 1.x](/platforms/java/legacy/log4j/) +- [log4j 2.x](/platforms/java/legacy/log4j2/) +- [Logback](/platforms/java/legacy/logback/) +- [Spring](/platforms/java/legacy/spring/) + +## Resources + +- [Code](https://github.com/getsentry/sentry-java/tree/v1.7.30) diff --git a/src/platforms/java/guides/log4j/index.mdx b/src/platforms/java/common/legacy/log4j/index.mdx similarity index 91% rename from src/platforms/java/guides/log4j/index.mdx rename to src/platforms/java/common/legacy/log4j/index.mdx index 93bc0a71f2c7d..e380d865830e4 100644 --- a/src/platforms/java/guides/log4j/index.mdx +++ b/src/platforms/java/common/legacy/log4j/index.mdx @@ -1,10 +1,14 @@ --- title: log4j 1.x -redirect_from: - - /clients/java/modules/log4j/ +sidebar_order: 30 --- -The `sentry-log4j` library provides [Log4j 1.x](https://logging.apache.org/log4j/1.2/) support for Sentry via an [Appender](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Appender.html) that sends logged exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](usage/), in order to do things like record breadcrumbs, set the current user, or manually send events. + + +An [updated Java SDK](/platforms/java/) supersedes this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the updated Java SDK for new projects. + + +The `sentry-log4j` library provides [Log4j 1.x](https://logging.apache.org/log4j/1.2/) support for Sentry via an [Appender](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Appender.html) that sends logged exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](/platforms/java/legacy/usage/), in order to do things like record breadcrumbs, set the current user, or manually send events. The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-log4j). @@ -81,7 +85,7 @@ Alternatively, using the `log4j.xml` format: ``` -Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](configuration/options/) for ways you can do this. +Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](/platforms/java/legacy/configuration/) for ways you can do this. diff --git a/src/platforms/java/common/legacy/log4j2/index.mdx b/src/platforms/java/common/legacy/log4j2/index.mdx new file mode 100644 index 0000000000000..1a55b3cb4f773 --- /dev/null +++ b/src/platforms/java/common/legacy/log4j2/index.mdx @@ -0,0 +1,140 @@ +--- +title: log4j 2.x +sidebar_order: 30 +--- + + + +An [updated Java SDK](/platforms/java/) SDK supersedes this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the updated Java SDK for new projects. + + +The `sentry-log4j2` library provides [Log4j 2.x](https://logging.apache.org/log4j/2.x/) support for Sentry via an [Appender](https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/Appender.html) that sends logged exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](/platforms/java/legacy/usage), in order to do things like record breadcrumbs, set the current user, or manually send events. + +The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-log4j2). + +### Installation + +```xml {tabTitle:Maven} + + io.sentry + sentry-log4j2 + {{ packages.version('sentry.java', '1.7.30') }} + +``` + +```groovy {tabTitle:Gradle} +implementation 'io.sentry:sentry-log4j2:{{ packages.version('sentry.java', '1.7.30') }}' +``` + +```scala {tabTitle: SBT} +libraryDependencies += "io.sentry" % "sentry-log4j2" % "{{ packages.version('sentry.java', '1.7.30') }}" +``` + +For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-log4j2). + +### Usage + +The following example configures a `ConsoleAppender` that logs to standard out at the `INFO` level and a `SentryAppender` that logs to the Sentry server at the `WARN` level. The `ConsoleAppender` is only provided as an example of a non-Sentry appender that is set to a different logging threshold, like one you may already have in your project. + +Example configuration using the `log4j2.xml` format: + +```xml + + + + + + + + + + + + + + + + + + +``` + +Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](/platforms/java/legacy/configuration/) for ways you can do this. + + + +### Additional Data + +It’s possible to add extra data to events thanks to [the marker system](https://logging.apache.org/log4j/2.x/manual/markers.html) provided by Log4j 2.x. + +#### Mapped Tags + +By default all MDC parameters are stored under the “Additional Data” tab in Sentry. By specifying the `mdctags` option in your configuration you can choose which MDC keys to send as tags instead, which allows them to be used as filters within the Sentry UI. + +```java +void logWithExtras() { + // ThreadContext ("MDC") extras + ThreadContext.put("Environment", "Development"); + ThreadContext.put("OS", "Linux"); + + // This sends an event where the Environment and OS MDC values are set as additional data + logger.error("This is a test"); +} +``` + +### In Practice + +```java +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; + +public class MyClass { + private static final Logger logger = LogManager.getLogger(MyClass.class); + private static final Marker MARKER = MarkerManager.getMarker("myMarker"); + + void logSimpleMessage() { + // This sends a simple event to Sentry + logger.error("This is a test"); + } + + void logWithBreadcrumbs() { + // Record a breadcrumb that will be sent with the next event(s), + // by default the last 100 breadcrumbs are kept. + Sentry.record( + new BreadcrumbBuilder().setMessage("User made an action").build() + ); + + // This sends a simple event to Sentry + logger.error("This is a test"); + } + + void logWithTag() { + // This sends an event with a tag named 'log4j2-Marker' to Sentry + logger.error(MARKER, "This is a test"); + } + + void logWithExtras() { + // MDC extras + ThreadContext.put("extra_key", "extra_value"); + // NDC extras are sent under 'log4j2-NDC' + ThreadContext.push("Extra_details"); + // This sends an event with extra data to Sentry + logger.error("This is a test"); + } + + void logException() { + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry + logger.error("Exception caught", e); + } + } + + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } +} +``` diff --git a/src/platforms/java/common/legacy/logback/index.mdx b/src/platforms/java/common/legacy/logback/index.mdx new file mode 100644 index 0000000000000..5db6e76beff19 --- /dev/null +++ b/src/platforms/java/common/legacy/logback/index.mdx @@ -0,0 +1,187 @@ +--- +title: Logback +sidebar_order: 30 +--- + + + +A new Java SDK has superseded this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the [updated Java SDK](/platforms/java/) for new projects. + + +The `sentry-logback` library provides [Logback](http://logback.qos.ch/) support for Sentry via an [Appender](http://logback.qos.ch/apidocs/ch/qos/logback/core/Appender.html) that sends logged exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](/platforms/java/legacy/usage), in order to do things like record breadcrumbs, set the current user, or manually send events. + +The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-logback). + +### Installation + +```xml {tabTitle:Maven} + + io.sentry + sentry-logback + {{ packages.version('sentry.java', '1.7.30') }} + +``` + +```groovy {tabTitle:Gradle} +implementation 'io.sentry:sentry-logback:{{ packages.version('sentry.java', '1.7.30') }}' +``` + +```scala {tabTitle: SBT} +libraryDependencies += "io.sentry" % "sentry-logback" % "{{ packages.version('sentry.java', '1.7.30') }}" +``` + +For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-logback). + +### Usage + +The following example configures a `ConsoleAppender` that logs to standard out at the `INFO` level and a `SentryAppender` that logs to the Sentry server at the `WARN` level. The `ConsoleAppender` is only provided as an example of a non-Sentry appender that is set to a different logging threshold, like one you may already have in your project. + +Example configuration using the `logback.xml` format: + +```xml + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + WARN + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + +``` + +Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](/platforms/java/legacy/configuration/#setting-the-dsn-data-source-name-setting-the-dsn) for ways you can do this. + + + +### Additional Data + +It’s possible to add extra data to events thanks to [the MDC system provided by Logback](http://logback.qos.ch/manual/mdc.html). + +#### Mapped Tags + +By default all MDC parameters are stored under the “Additional Data” tab in Sentry. By specifying the `mdctags` option in your configuration you can choose which MDC keys to send as tags instead, which allows them to be used as filters within the Sentry UI. + +```java +void logWithExtras() { + // MDC extras + MDC.put("Environment", "Development"); + MDC.put("OS", "Linux"); + + // This sends an event where the Environment and OS MDC values are set as additional data + logger.error("This is a test"); +} +``` + +#### Global Tags + +Sometimes it's useful to add tags and extra data to all log events. +You can add tags and extras to logs globally (not thread-bound) by adding entries to the LoggerContext. +Tags are distinguished by the existing mdcTags configuration property detailed above. + +```java + LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory(); + context.putProperty("global", "value"); +``` + +Global log entries can also be added via third-party encoders +(_whether such entries can be distinguished as tags or entries, however, is encoder implementation-specific_). +The `net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder` for example has a `customFields` option: + +```java + + {"appname":"myWebservice","roles":["customerorder","auth"]} + +``` + +In the event of naming clashes, the more specific MDC tags will take precedence. + +### In Practice + +```java +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.MarkerFactory; + +public class MyClass { + private static final Logger logger = LoggerFactory.getLogger(MyClass.class); + private static final Marker MARKER = MarkerFactory.getMarker("myMarker"); + + void logSimpleMessage() { + // This sends a simple event to Sentry + logger.error("This is a test"); + } + + void logWithBreadcrumbs() { + // Record a breadcrumb that will be sent with the next event(s), + // by default the last 100 breadcrumbs are kept. + Sentry.record( + new BreadcrumbBuilder().setMessage("User made an action").build() + ); + + // This sends a simple event to Sentry + logger.error("This is a test"); + } + + void logWithTag() { + // This sends an event with a tag named 'logback-Marker' to Sentry + logger.error(MARKER, "This is a test"); + } + + void logWithExtras() { + // MDC extras + MDC.put("extra_key", "extra_value"); + // This sends an event with extra data to Sentry + logger.error("This is a test"); + } + + void logWithGlobalTag() { + LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory(); + // This adds a tag named 'logback-Marker' to every subsequent Sentry event + context.putProperty(MARKER, "This is a test"); + + // This sends an event to Sentry, and a tag named 'logback-Marker' will be added. + logger.info("This is a test"); + } + + void addGlobalExtras() { + LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory(); + // This adds extra data to every subsequent Sentry event + context.putProperty("extra_key", "extra_value"); + + // This sends an event to Sentry, and extra data ("extra_key", "extra_value") will be added. + logger.info("This is a test"); + } + + void logException() { + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry + logger.error("Exception caught", e); + } + } + + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } +} +``` diff --git a/src/platforms/java/guides/logging/index.mdx b/src/platforms/java/common/legacy/logging/index.mdx similarity index 80% rename from src/platforms/java/guides/logging/index.mdx rename to src/platforms/java/common/legacy/logging/index.mdx index 9a5008396f0d7..9c906d090716d 100644 --- a/src/platforms/java/guides/logging/index.mdx +++ b/src/platforms/java/common/legacy/logging/index.mdx @@ -1,10 +1,14 @@ --- title: java.util.logging -redirect_from: - - /clients/java/modules/jul/ +sidebar_order: 30 --- -The `sentry` library provides a [java.util.logging Handler](https://docs.oracle.com/javase/7/docs/api/java/util/logging/Handler.html) that sends logged exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](usage/), in order to do things like record breadcrumbs, set the current user, or manually send events. + + +An [updated Java SDK](/platforms/java/) supersedes this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the updated Java SDK for new projects. + + +The `sentry` library provides a [java.util.logging Handler](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Handler.html) that sends logged exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](/platforms/java/legacy/usage), in order to do things like record breadcrumbs, set the current user, or manually send events. The source for `sentry` can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry). @@ -51,7 +55,7 @@ When starting your application, add the `java.util.logging.config.file` to the s $ java -Djava.util.logging.config.file=/path/to/app.properties MyClass ``` -Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](configuration/options/) for ways you can do this. +Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](/platforms/java/legacy/configuration) for ways you can do this. diff --git a/src/platforms/java/common/migration.mdx b/src/platforms/java/common/legacy/migration.mdx similarity index 99% rename from src/platforms/java/common/migration.mdx rename to src/platforms/java/common/legacy/migration.mdx index 2f7f2ee571817..9fa3857acc147 100644 --- a/src/platforms/java/common/migration.mdx +++ b/src/platforms/java/common/legacy/migration.mdx @@ -1,5 +1,5 @@ --- -title: Migration Guide +title: Migrating Between Raven and Version 1.7 sidebar_order: 1000 redirect_from: - /clients/java/migration/ diff --git a/src/platforms/java/common/legacy/spring/index.mdx b/src/platforms/java/common/legacy/spring/index.mdx new file mode 100644 index 0000000000000..8dfa21c800174 --- /dev/null +++ b/src/platforms/java/common/legacy/spring/index.mdx @@ -0,0 +1,79 @@ +--- +title: Spring +sidebar_order: 30 +--- + + + +An [updated Java SDK](/platforms/java/) supersedes this deprecated version. Sentry preserves this documentation for customers using the old client. We recommend using the updated Java SDK for new projects. + + +The `sentry-spring` library provides [Spring](https://spring.io/) support for Sentry via a [HandlerExceptionResolver](https://docs.spring.io/spring/docs/4.3.9.RELEASE/javadoc-api/org/springframework/web/servlet/HandlerExceptionResolver.html) that sends exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](/platforms/java/legacy/usage), in order to do things like record breadcrumbs, set the current user, or manually send events. + +The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-spring). + +### Installation + +```xml {tabTitle:Maven} + + io.sentry + sentry-spring + {{ packages.version('sentry.java', '1.7.30') }} + +``` + +```groovy {tabTitle:Gradle} +implementation 'io.sentry:sentry-spring:{{ packages.version('sentry.java', '1.7.30') }}' +``` + +```scala {tabTitle: SBT} +libraryDependencies += "io.sentry" % "sentry-spring" % "{{ packages.version('sentry.java', '1.7.30') }}" +``` + +For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-spring). + +### Usage + +The `sentry-spring` library provides two classes that can be enabled by registering them as Beans in your Spring application. + +#### Recording Exceptions + +In order to record all exceptions thrown by your controllers, you can register `io.sentry.spring.SentryExceptionResolver` as a Bean in your application. Once registered, all exceptions will be sent to Sentry and then passed on to the default exception handlers. + +Configuration via `web.xml`: + +```xml + +``` + +Or via a configuration class: + +```java +@Bean +public HandlerExceptionResolver sentryExceptionResolver() { + return new io.sentry.spring.SentryExceptionResolver(); +} +``` + +Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](/platforms/java/legacy/configuration) for ways you can do this. + +#### Spring Boot HTTP Data + +Spring Boot doesn’t automatically load any `javax.servlet.ServletContainerInitializer`, which means the Sentry SDK doesn’t have an opportunity to hook into the request cycle to collect information about the HTTP request. In order to add HTTP request data to your Sentry events in Spring Boot, you need to register the `io.sentry.spring.SentryServletContextInitializer` class as a Bean in your application. + +Configuration via `web.xml`: + +```xml + +``` + +Or via a configuration class: + +```java +@Bean +public ServletContextInitializer sentryServletContextInitializer() { + return new io.sentry.spring.SentryServletContextInitializer(); +} +``` + +After that, your Sentry events should contain information such as HTTP request headers. diff --git a/src/platforms/java/common/legacy/usage.mdx b/src/platforms/java/common/legacy/usage.mdx new file mode 100644 index 0000000000000..ee435eb0716e2 --- /dev/null +++ b/src/platforms/java/common/legacy/usage.mdx @@ -0,0 +1,221 @@ +--- +title: Manual Usage +sidebar_order: 15 +redirect_from: + - /clients/java/usage/ +--- + +## Installation + +```xml {tabTitle:Maven} + + io.sentry + sentry + 1.7.30 + +``` + +```groovy {tabTitle:Gradle} +implementation 'io.sentry:sentry:1.7.30' +``` + +```scala {tabTitle:SBT} +libraryDependencies += "io.sentry" % "sentry" % "1.7.30" +``` + +For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-spring). + +## Capture an Error + +To report an event manually you need to initialize a `SentryClient`. It is recommended that you use the static API via the `Sentry` class, but you can also construct and manage your own `SentryClient` instance. An example of each style is shown below: + +```java +import io.sentry.context.Context; +import io.sentry.event.BreadcrumbBuilder; +import io.sentry.event.UserBuilder; + +public class MyClass { + private static SentryClient sentry; + + public static void main(String... args) { + /* + It is recommended that you use the DSN detection system, which + will check the environment variable "SENTRY_DSN", the Java + System Property "sentry.dsn", or the "sentry.properties" file + in your classpath. This makes it easier to provide and adjust + your DSN without needing to change your code. See the configuration + page for more information. + + For example, using an environment variable + + export SENTRY_DSN="___PUBLIC_DSN___" + */ + Sentry.init(); + + // You can also manually provide the DSN to the ``init`` method. + // Sentry.init("___PUBLIC_DSN___"); + + /* + It is possible to go around the static ``Sentry`` API, which means + you are responsible for making the SentryClient instance available + to your code. + */ + sentry = SentryClientFactory.sentryClient(); + + MyClass myClass = new MyClass(); + myClass.logWithStaticAPI(); + myClass.logWithInstanceAPI(); + } + + /** + * An example method that throws an exception. + */ + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } + + /** + * Examples using the (recommended) static API. + */ + void logWithStaticAPI() { + // Note that all fields set on the context are optional. Context data is copied onto + // all future events in the current context (until the context is cleared). + + // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept. + Sentry.getContext().recordBreadcrumb( + new BreadcrumbBuilder().setMessage("User made an action").build() + ); + + // Set the user in the current context. + Sentry.getContext().setUser( + new UserBuilder().setEmail("hello@sentry.io").build() + ); + + // Add extra data to future events in this context. + Sentry.getContext().addExtra("extra", "thing"); + + // Add an additional tag to future events in this context. + Sentry.getContext().addTag("tagName", "tagValue"); + + /* + This sends a simple event to Sentry using the statically stored instance + that was created in the ``main`` method. + */ + Sentry.capture("This is a test"); + + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry using the statically stored instance + // that was created in the ``main`` method. + Sentry.capture(e); + } + } + + /** + * Examples that use the SentryClient instance directly. + */ + void logWithInstanceAPI() { + // Retrieve the current context. + Context context = sentry.getContext(); + + // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept. + context.recordBreadcrumb(new BreadcrumbBuilder().setMessage("User made an action").build()); + + // Set the user in the current context. + context.setUser(new UserBuilder().setEmail("hello@sentry.io").build()); + + // This sends a simple event to Sentry. + sentry.sendMessage("This is a test"); + + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry. + sentry.sendException(e); + } + } +} +``` + +### Building More Complex Events + +For more complex messages, you’ll need to build an `Event` with the `EventBuilder` class: + +```java +import io.sentry.Sentry; + import io.sentry.event.Event; + import io.sentry.event.EventBuilder; + import io.sentry.event.interfaces.ExceptionInterface; + + public class MyClass { + public static void main(String... args) { + Sentry.init(); + } + + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } + + void logSimpleMessage() { + // This sends an event to Sentry. + EventBuilder eventBuilder = new EventBuilder() + .withMessage("This is a test") + .withLevel(Event.Level.INFO) + .withLogger(MyClass.class.getName()); + + // Note that the *unbuilt* EventBuilder instance is passed in so that + // EventBuilderHelpers are run to add extra information to your event. + Sentry.capture(eventBuilder); + } + + void logException() { + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry. + EventBuilder eventBuilder = new EventBuilder() + .withMessage("Exception caught") + .withLevel(Event.Level.ERROR) + .withLogger(MyClass.class.getName()) + .withSentryInterface(new ExceptionInterface(e)); + + // Note that the *unbuilt* EventBuilder instance is passed in so that + // EventBuilderHelpers are run to add extra information to your event. + Sentry.capture(eventBuilder); + } + } +} +``` + +### Automatically Enhancing Events + +You can also implement an `EventBuilderHelper` that is able to automatically enhance outgoing events. + +```java +import io.sentry.Sentry; +import io.sentry.SentryClient; +import io.sentry.event.EventBuilder; +import io.sentry.event.helper.EventBuilderHelper; + +public class MyClass { + public void myMethod() { + SentryClient client = Sentry.getStoredClient(); + + EventBuilderHelper myEventBuilderHelper = new EventBuilderHelper() { + @Override + public void helpBuildingEvent(EventBuilder eventBuilder) { + eventBuilder.withMessage("Overwritten by myEventBuilderHelper!"); + } + }; + + // Add an ``EventBuilderHelper`` to the current client instance. Note that + // this helper will process *all* future events. + client.addBuilderHelper(myEventBuilderHelper); + + // Send an event to Sentry. During construction of the event the message + // body will be overwritten by ``myEventBuilderHelper``. + Sentry.capture("Hello, world!"); + } +} +``` diff --git a/src/platforms/java/common/scope.mdx b/src/platforms/java/common/scope.mdx new file mode 100644 index 0000000000000..b8cf8056e5ae6 --- /dev/null +++ b/src/platforms/java/common/scope.mdx @@ -0,0 +1,59 @@ +--- +title: Scope & Breadcrumbs +sidebar_order: 3 +redirect_from: + - /clients/java/context/ +--- + +The Java SDK implements the idea of a “scope” to support attaching additional information to events, such as breadcrumbs. A scope may refer to a single request to a web framework, to the entire lifetime of an Android application, or something else that better suits your application’s needs. + +## Usage + +Breadcrumbs can be used to describe actions that occurred in your application leading up to an event being sent. For example, whether external API requests were made, or whether a user clicked on something in an Android application. By default the last 100 breadcrumbs per scope will be stored and sent with future events. + +The user can be set per scope so that you know who was affected by each event. + +Once a `Sentry` instance has been initialized you can begin setting state in the current scope. + +```java +import io.sentry.Sentry; +import io.sentry.protocol.User; + +public class MyClass { + + public void example() { + // Manually initialize the static client, you must also pass in a DSN and/or + // SentryClientFactory to use. Note that the client will attempt to automatically + // initialize on the first use of the static API, so this isn't strictly necessary. + Sentry.init(options -> { + options.setDsn("___PUBLIC_DSN___"); + }); + + // Note that all fields set on the scope are optional. Scope data is copied onto + // all future events in the current scope (until the scope is cleared). + + // Set the current user in the scope. + Sentry.configureScope(scope -> { + User user = new User(); + user.setUsername("user1"); + scope.setUser(user); + }); + + // Record a breadcrumb in the scope. + Sentry.addBreadcrumb("User did something specific again!"); + + // Add extra data to future events in this scope. + Sentry.configureScope(scope -> { + scope.setExtra("extra", "thing"); + }); + + // Add an additional tag to future events in this scope. + Sentry.configureScope(scope -> { + scope.setTag("tagName", "tagValue"); + }); + + // Send an event with the scope data attached. + Sentry.captureMessage("New event message"); + } +} +``` diff --git a/src/platforms/java/guides/log4j2/index.mdx b/src/platforms/java/guides/log4j2/index.mdx index 7f5e8e8ef1428..1f71a42c20333 100644 --- a/src/platforms/java/guides/log4j2/index.mdx +++ b/src/platforms/java/guides/log4j2/index.mdx @@ -14,123 +14,197 @@ The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tre io.sentry sentry-log4j2 - {{ packages.version('sentry.java', '1.7.30') }} + {{ packages.version('sentry.java', '3.0.0') }} ``` ```groovy {tabTitle:Gradle} -implementation 'io.sentry:sentry-log4j2:{{ packages.version('sentry.java', '1.7.30') }}' +implementation 'io.sentry:sentry-log4j2:{{ packages.version('sentry.java', '3.0.0') }}' ``` ```scala {tabTitle: SBT} -libraryDependencies += "io.sentry" % "sentry-log4j2" % "{{ packages.version('sentry.java', '1.7.30') }}" +libraryDependencies += "io.sentry" % "sentry-log4j2" % "{{ packages.version('sentry.java', '3.0.0') }}" ``` For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-log4j2). ### Usage -The following example configures a `ConsoleAppender` that logs to standard out at the `INFO` level and a `SentryAppender` that logs to the Sentry server at the `WARN` level. The `ConsoleAppender` is only provided as an example of a non-Sentry appender that is set to a different logging threshold, like one you may already have in your project. +The following example configures a `ConsoleAppender` that logs to standard out at the `INFO` level and a `SentryAppender` that logs to the Sentry server at the `ERROR` level. The `ConsoleAppender` is only provided as an example of a non-Sentry appender that is set to a different logging threshold, like one you may already have in your project. Example configuration using the `log4j2.xml` format: ```xml - - + + - + + + + + + + + + + +``` + +### DSN Configuration - - - - - - - - - - - +Note that **you need to configure your DSN** (client key). + +```xml + ``` -Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](configuration/options/) for ways you can do this. +If the DSN is not present in the `log4j2.xml` configuration, Sentry will attempt to read it from the system property `sentry.dsn`, environment variable `SENTRY_DSN` or the `dsn` property in `sentry.properties` file. [See the configuration page](/platforms/java/configuration/) for more details on external configuration. - +### Minimum Log Level -### Additional Data +Two log levels are used to configure this integration (see options below). One will configure the lowest level required for a log message to become an event (`minimumEventLevel`) sent to Sentry. The other option (`minimumBreadcrumbLevel`) configures the lowest level a message has to be to become a breadcrumb. Breadcrumbs are kept in memory (by default the last 100 records) and are sent with events. For example, by default, if you log 100 entries with `logger.info` or `logger.warn`, no event is sent to Sentry. If you then log with `logger.error`, an event is sent to Sentry which includes those 100 `info` or `warn` messages. For this to work, `SentryAppender` needs to receive **all** log entries in order to decide what to keep as breadcrumb or sent as event. Make sure to set the `SentryAppender` log level configuration to a value lower than what you set for the `minimumBreadcrumbLevel` and `minimumEventLevel` to make sure `SentryAppender` receives these log messages. -It’s possible to add extra data to events thanks to [the marker system](https://logging.apache.org/log4j/2.x/manual/markers.html) provided by Log4j 2.x. +```xml + + + +``` #### Mapped Tags -By default all MDC parameters are stored under the “Additional Data” tab in Sentry. By specifying the `mdctags` option in your configuration you can choose which MDC keys to send as tags instead, which allows them to be used as filters within the Sentry UI. +By default all `ThreadContext` parameters are stored under the “Context Data” tab in Sentry. -```java +```java {tabTitle:Java} void logWithExtras() { // ThreadContext ("MDC") extras ThreadContext.put("Environment", "Development"); ThreadContext.put("OS", "Linux"); - // This sends an event where the Environment and OS MDC values are set as additional data + // This sends an event where the Environment and OS ThreadContext values are set as Context Data entries + logger.error("This is a test"); +} +``` + +```kotlin {tabTitle:Kotlin} +fun logWithExtras() { + // MDC extras + ThreadContext.put("Environment", "Development"); + ThreadContext.put("OS", "Linux"); + + // This sends an event where the Environment and OS ThreadContext values are set as Context Data entries logger.error("This is a test"); } ``` ### In Practice -```java +```java {tabTitle:Java} +import io.sentry.core.Sentry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.MarkerManager; +import org.apache.logging.log4j.ThreadContext; public class MyClass { - private static final Logger logger = LogManager.getLogger(MyClass.class); - private static final Marker MARKER = MarkerManager.getMarker("myMarker"); + private static final Logger logger = LogManager.getLogger(MyClass.class); + + void logSimpleMessage() { + // This sends a simple event to Sentry + logger.error("This is a test"); + } - void logSimpleMessage() { + void logWithBreadcrumbs() { + // Record a breadcrumb that will be sent with the next event(s), + // by default the last 100 breadcrumbs are kept. + Sentry.addBreadcrumb("User made an action"); + + // Log entries below `minimumEventLevel` and above or equal to `minimumBreadcrumbLevel` + // are recorded as breadcrumbs + logger.info("User made another action"); + + // This sends a simple event to Sentry + logger.error("This is a test"); + } + + void logWithExtras() { + // MDC extras + ThreadContext.put("extra_key", "extra_value"); + // NDC extras are sent under 'log4j2-NDC' + ThreadContext.push("Extra_details"); + // This sends an event with extra data to Sentry + logger.error("This is a test"); + } + + void logException() { + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry + logger.error("Exception caught", e); + } + } + + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } +} +``` + +```kotlin {tabTitle:Kotlin} +import io.sentry.core.Sentry +import org.apache.logging.log4j.LogManager +import org.apache.logging.log4j.ThreadContext + +class MyClass { + companion object { + private val logger = LogManager.getLogger(MyClass::class.java) + } + + fun logSimpleMessage() { // This sends a simple event to Sentry - logger.error("This is a test"); + logger.error("This is a test") } - void logWithBreadcrumbs() { + fun logWithBreadcrumbs() { // Record a breadcrumb that will be sent with the next event(s), // by default the last 100 breadcrumbs are kept. - Sentry.record( - new BreadcrumbBuilder().setMessage("User made an action").build() - ); + Sentry.addBreadcrumb("User made an action") - // This sends a simple event to Sentry - logger.error("This is a test"); - } + // Log entries below `minimumEventLevel` and above or equal to `minimumBreadcrumbLevel` + // are recorded as breadcrumbs + logger.info("User made another action") - void logWithTag() { - // This sends an event with a tag named 'log4j2-Marker' to Sentry - logger.error(MARKER, "This is a test"); + // This sends a simple event to Sentry + logger.error("This is a test") } - void logWithExtras() { + fun logWithExtras() { // MDC extras - ThreadContext.put("extra_key", "extra_value"); + ThreadContext.put("extra_key", "extra_value") // NDC extras are sent under 'log4j2-NDC' - ThreadContext.push("Extra_details"); + ThreadContext.push("Extra_details") // This sends an event with extra data to Sentry - logger.error("This is a test"); + logger.error("This is a test") } - void logException() { + fun logException() { try { - unsafeMethod(); - } catch (Exception e) { + unsafeMethod() + } catch (e: Exception) { // This sends an exception event to Sentry - logger.error("Exception caught", e); + logger.error("Exception caught", e) } } - void unsafeMethod() { - throw new UnsupportedOperationException("You shouldn't call this!"); + fun unsafeMethod() { + throw UnsupportedOperationException("You shouldn't call this!") } } ``` diff --git a/src/platforms/java/guides/logback/index.mdx b/src/platforms/java/guides/logback/index.mdx index 9c405868cdad7..01e06bb1a2289 100644 --- a/src/platforms/java/guides/logback/index.mdx +++ b/src/platforms/java/guides/logback/index.mdx @@ -15,12 +15,12 @@ The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tre io.sentry sentry-logback - {{ packages.version('sentry.java', '1.7.30') }} + {{ packages.version('sentry.java', '3.0.0') }} ``` ```groovy {tabTitle:Gradle} -implementation 'io.sentry:sentry-logback:{{ packages.version('sentry.java', '1.7.30') }}' +implementation 'io.sentry:sentry-logback:{{ packages.version('sentry.java', '3.0.0') }}' ``` ```scala {tabTitle: SBT} @@ -31,7 +31,7 @@ For other dependency managers see the [central Maven repository](https://search. ### Usage -The following example configures a `ConsoleAppender` that logs to standard out at the `INFO` level and a `SentryAppender` that logs to the Sentry server at the `WARN` level. The `ConsoleAppender` is only provided as an example of a non-Sentry appender that is set to a different logging threshold, like one you may already have in your project. +The following example configures a `ConsoleAppender` that logs to standard out at the `INFO` level and a `SentryAppender` that logs to the Sentry server at the `ERROR` level. The `ConsoleAppender` is only provided as an example of a non-Sentry appender that is set to a different logging threshold, like one you may already have in your project. Example configuration using the `logback.xml` format: @@ -46,13 +46,10 @@ Example configuration using the `logback.xml` format: - - WARN - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - + + + ___PUBLIC_DSN___ + + ___PUBLIC_DSN___ + + +``` + +If the DSN is not present in the `logback.xml` configuration, Sentry will attempt to read it from the system property `sentry.dsn`, environment variable `SENTRY_DSN` or the `dsn` property in `sentry.properties` file. [See the configuration page](/platforms/java/configuration/) for more details on external configuration. + +### Advanced Configuration + + +Optionally you can configure other values such as `environment` and `release`. [See the configuration page](configuration/options/#setting-the-dsn) for the in-depth explanation of each property. + +```xml + + + + ___PUBLIC_DSN___ + 2000 + 15000 + false + 100 + 1.0.0 + production + 1.0 + false + false + host-4 + 5000 + 5000 + + +``` + +### Minimum log level + +Two log levels are used to configure this integration (see options below). One will configure the lowest level required for a log message to become an event (`minimumEventLevel`) sent to Sentry. The other option (`minimumBreadcrumbLevel`) configures the lowest level a message has to be to become a breadcrumb. Breadcrumbs are kept in memory (by default the last 100 records) and are sent with events. For example, by default, if you log 100 entries with `logger.info` or `logger.warn`, no event is sent to Sentry. If you then log with `logger.error`, an event is sent to Sentry which includes those 100 `info` or `warn` messages. For this to work, `SentryAppender` needs to receive **all** log entries in order to decide what to keep as breadcrumb or sent as event. Make sure to set the `SentryAppender` log level configuration to a value lower than what you set for the `minimumBreadcrumbLevel` and `minimumEventLevel` to make sure `SentryAppender` receives these log messages. - +```xml + + + + ___PUBLIC_DSN___ + + + WARN + + DEBUG + +``` ### Additional Data @@ -74,53 +125,39 @@ It’s possible to add extra data to events thanks to [the MDC system provided b #### Mapped Tags -By default all MDC parameters are stored under the “Additional Data” tab in Sentry. By specifying the `mdctags` option in your configuration you can choose which MDC keys to send as tags instead, which allows them to be used as filters within the Sentry UI. +By default all MDC parameters are stored under the “MDC” tab in Sentry. -```java +```java {tabTitle:Java} void logWithExtras() { // MDC extras MDC.put("Environment", "Development"); MDC.put("OS", "Linux"); - // This sends an event where the Environment and OS MDC values are set as additional data + // This sends an event where the Environment and OS MDC values are set as MDC entries logger.error("This is a test"); } ``` -#### Global Tags - -Sometimes it's useful to add tags and extra data to all log events. -You can add tags and extras to logs globally (not thread-bound) by adding entries to the LoggerContext. -Tags are distinguished by the existing mdcTags configuration property detailed above. - -```java - LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory(); - context.putProperty("global", "value"); -``` - -Global log entries can also be added via third-party encoders -(_whether such entries can be distinguished as tags or entries, however, is encoder implementation-specific_). -The `net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder` for example has a `customFields` option: +```kotlin {tabTitle:Kotlin} +fun logWithExtras() { + // MDC extras + MDC.put("Environment", "Development"); + MDC.put("OS", "Linux"); -```java - - {"appname":"myWebservice","roles":["customerorder","auth"]} - + // This sends an event where the Environment and OS MDC values are set as MDC entries + logger.error("This is a test"); +} ``` -In the event of naming clashes, the more specific MDC tags will take precedence. - ### In Practice -```java +```java {tabTitle:Java} import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -import org.slf4j.MarkerFactory; public class MyClass { private static final Logger logger = LoggerFactory.getLogger(MyClass.class); - private static final Marker MARKER = MarkerFactory.getMarker("myMarker"); void logSimpleMessage() { // This sends a simple event to Sentry @@ -130,19 +167,16 @@ public class MyClass { void logWithBreadcrumbs() { // Record a breadcrumb that will be sent with the next event(s), // by default the last 100 breadcrumbs are kept. - Sentry.record( - new BreadcrumbBuilder().setMessage("User made an action").build() - ); + Sentry.addBreadcrumb("User made an action"); + + // Log entries below `minimumEventLevel` and above or equal to `minimumBreadcrumbLevel` + // are recorded as breadcrumbs + logger.info("User made another action"); // This sends a simple event to Sentry logger.error("This is a test"); } - void logWithTag() { - // This sends an event with a tag named 'logback-Marker' to Sentry - logger.error(MARKER, "This is a test"); - } - void logWithExtras() { // MDC extras MDC.put("extra_key", "extra_value"); @@ -150,24 +184,6 @@ public class MyClass { logger.error("This is a test"); } - void logWithGlobalTag() { - LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory(); - // This adds a tag named 'logback-Marker' to every subsequent Sentry event - context.putProperty(MARKER, "This is a test"); - - // This sends an event to Sentry, and a tag named 'logback-Marker' will be added. - logger.info("This is a test"); - } - - void addGlobalExtras() { - LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory(); - // This adds extra data to every subsequent Sentry event - context.putProperty("extra_key", "extra_value"); - - // This sends an event to Sentry, and extra data ("extra_key", "extra_value") will be added. - logger.info("This is a test"); - } - void logException() { try { unsafeMethod(); @@ -182,3 +198,53 @@ public class MyClass { } } ``` + +```kotlin {tabTitle:Kotlin} +import io.sentry.core.Sentry +import org.slf4j.LoggerFactory +import org.slf4j.MDC + +class Main { + companion object { + private val logger = LoggerFactory.getLogger(Main::class.java) + } + + fun logSimpleMessage() { + // This sends a simple event to Sentry + logger.error("This is a test") + } + + fun logWithBreadcrumbs() { + // Record a breadcrumb that will be sent with the next event(s), + // by default the last 100 breadcrumbs are kept. + Sentry.addBreadcrumb("User made an action") + + // Log entries below `minimumEventLevel` and above or equal to `minimumBreadcrumbLevel` + // are recorded as breadcrumbs + logger.info("User made another action") + + // This sends a simple event to Sentry + logger.error("This is a test") + } + + fun logWithExtras() { + // MDC extras + MDC.put("extra_key", "extra_value") + // This sends an event with extra data to Sentry + logger.error("This is a test") + } + + fun logException() { + try { + unsafeMethod() + } catch (e: Exception) { + // This sends an exception event to Sentry + logger.error("Exception caught", e) + } + } + + fun unsafeMethod() { + throw UnsupportedOperationException("You shouldn't call this!") + } +} +``` diff --git a/src/platforms/java/guides/spring-boot/index.mdx b/src/platforms/java/guides/spring-boot/index.mdx new file mode 100644 index 0000000000000..1d89ab8c5a534 --- /dev/null +++ b/src/platforms/java/guides/spring-boot/index.mdx @@ -0,0 +1,261 @@ +--- +title: Spring Boot +--- + +The `sentry-spring-boot-starter` library enhances [Sentry Spring](/platforms/java/guides/spring/) support with an auto-configuration for [Spring Boot](https://spring.io/projects/spring-boot) providing following features: + +- fine-grained configuration via `application.properties` +- automatically setting the release on `SentryEvent` when [Spring Boot Git integration is configured](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-git-info) +- automatically registering `BeforeSendCallback`, `BeforeBreadcrumbCallback`, `EventProcessor`, `Integration` beans + +For the best experience we recommend using Sentry Spring Boot integration together with one of the logging framework integrations as they seamlessly work together: + +- [Logback](/platforms/java/guides/logback/) +- [Log4j2](/platforms/java/guides/log4j2/) + +Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](usage/), in order to do things like record breadcrumbs, set the current user, or manually send events. + + + To use Sentry without Spring Boot, we recommend using Sentry Spring integration. + + +The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-spring). + +### Installation + +```xml {tabTitle:Maven} + + io.sentry + sentry-spring-boot-starter + {{ packages.version('sentry.java', '3.0.0') }} + +``` + +```groovy {tabTitle:Gradle} +implementation 'io.sentry:sentry-spring-boot-starter:{{ packages.version('sentry.java', '3.0.0') }}' +``` + +For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-spring). + +### Usage + +The `sentry-spring-boot-starter` must be provided with a `sentry.dsn` property via `application.properties` or `application.yml`: + +```properties {tabTitle:application.properties} +# NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry project/dashboard +sentry.dsn=___PUBLIC_DSN___ +``` + +```yaml {tabTitle:application.yml} +# NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry project/dashboard +sentry: + dsn: ___PUBLIC_DSN___ +``` + +#### Recording User Information From HTTP Request + +In order to record user's IP address and `Principal#name` as the username, sending personal information flag has to be set to `true`. + +```properties {tabTitle:application.properties} +sentry.send-default-pii=true +``` + +```yaml {tabTitle:application.yml} +sentry: + send-default-pii: true +``` + +#### Recording Custom User Information + +In order to record custom user information, you care register a bean that implements `SentryUserProvider` interface. + +```java {tabTitle:Java} +import org.springframework.stereotype.Component; +import io.sentry.core.protocol.User; +import io.sentry.spring.SentryUserProvider; + +@Component +class CustomSentryUserProvider implements SentryUserProvider { + public User provideUser() { + User user = User(); + // ... set user information + return user + } +} +``` + +```kotlin {tabTitle:Kotlin} +import org.springframework.stereotype.Component +import io.sentry.core.protocol.User +import io.sentry.spring.SentryUserProvider + +@Component +class CustomSentryUserProvider : SentryUserProvider { + override fun provideUser(): User? { + val user = User() + // ... set user information + return user + } +} +``` + +#### Using Git Commit ID As The Release + +When Spring Boot is [configured to generate Git information](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-git-info) every event triggered by Sentry will have a `release` field set to the current Git commit ID that will enable [Monitor Release Health](/product/releases/health/) Sentry feature. + +This feature can be disabled in `application.properties` file: + +```properties {tabTitle:application.properties} +sentry.use-git-commit-id-as-release=false +``` + +```yaml {tabTitle:application.yml} +sentry: + use-git-commit-id-as-release: false +``` + +#### Registering Custom Event Processor + +A Spring bean implementing `EventProcessor` will be automatically set on `SentryOptions` during Sentry SDK auto-configuration. There can be multiple event processors registered in single application. + +```java +import io.sentry.SentryEvent; +import io.sentry.EventProcessor; +import org.springframework.stereotype.Component; + +@Component +public class CustomEventProcessor implements EventProcessor { + @Override + public SentryEvent process(SentryEvent event, Object hint) { + // modify the event or return null to drop it + return event; + } +} +``` + +#### Registering Custom Before Send Callback + +A Spring bean implementing `BeforeSendCallback` will be automatically set on `SentryOptions` during Sentry SDK auto-configuration. Note that there can be only single bean like that. + +```java +import io.sentry.SentryEvent; +import io.sentry.SentryOptions; +import org.springframework.stereotype.Component; + +@Component +public class CustomBeforeSendCallback implements SentryOptions.BeforeSendCallback { + @Override + public SentryEvent execute(SentryEvent event, Object hint) { + event.setServerName(null); + return event; + } +} +``` + +#### Registering Custom Before Breadcrumb Callback + +A Spring bean implementing `BeforeBreadcrumbCallback` will be automatically set on `SentryOptions` during Sentry SDK auto-configuration. Note that there can be only single bean like that. + +```java +import io.sentry.Breadcrumb; +import io.sentry.SentryOptions; +import org.springframework.stereotype.Component; + +@Component +public class CustomBeforeBreadcrumbCallback implements SentryOptions.BeforeBreadcrumbCallback { + + @Override + public Breadcrumb execute(Breadcrumb breadcrumb, Object hint) { + // Don't add breadcrumbs with message containing: + if (breadcrumb.getMessage() != null + && breadcrumb.getMessage().contains("bad breadcrumb")) { + return null; + } + return breadcrumb; + } +} +``` + +## Using With Logging Framework Integration + +For the best experience we recommend using Sentry Spring Boot integration together with one of the logging framework integrations as they seamlessly work together. + +### Logback + +To use Sentry Logback integration in Spring Boot application you must include a dependency to `sentry-logback` module and Sentry Spring Boot Starter will auto-configure `SentryAppender`: + +```xml {tabTitle:Maven} + + io.sentry + sentry-logback + {{ packages.version('sentry.java', '3.0.0') }} + +``` + +```groovy {tabTitle:Gradle} +implementation 'io.sentry:sentry-logback:{{ packages.version('sentry.java', '3.0.0') }}' +``` + +Minimum logging levels for `SentryAppender` can be configured in `application.properties` or `application.yml` file. + +```properties +sentry.logging.minimum-event-level=info +sentry.logging.minimum-breadcrumb-level=debug +``` + +When `SentryAppender` auto-configuration does not suit your needs it can be turned off by setting: + +```properties +sentry.logging.enabled=false +``` + +If you decide to opt-out from `application.properties` based Spring Boot logging configuration and configure logging in `logback-spring.xml` file, `SentryAppender` can be configured in the following way: + +```xml + + + + + + + + + + + + +``` + + +Note that there is no need to configure DSN in Logback configuration file as Sentry gets configured via Spring Boot integration. + +However, if potential errors that appear during the startup are meant to be sent to Sentry, the DSN must be provided to both Logback and Spring Boot configuration. + + +### Log4j2 + +To use Sentry Log4j2 integration in Spring Boot application, [follow the guide on configuring Log4j2 with Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-configure-log4j-for-logging) and configure `SentryAppender` in `log4j2.xml` file: + +```xml + + + + + + + + + + + + + + + +``` + + +Note that there is no need to configure DSN in Log4j2 configuration file as Sentry gets configured via Spring Boot integration. + +However, if potential errors that appear during the startup are meant to be sent to Sentry, the DSN must be provided to both Log4j2 and Spring Boot configuration. + diff --git a/src/platforms/java/guides/spring/index.mdx b/src/platforms/java/guides/spring/index.mdx index 4018e3ea53cf5..2d13c8cedfb55 100644 --- a/src/platforms/java/guides/spring/index.mdx +++ b/src/platforms/java/guides/spring/index.mdx @@ -4,7 +4,18 @@ redirect_from: - /platforms/java/guides/spring/config/ --- -The `sentry-spring` library provides [Spring](https://spring.io/) support for Sentry via a [HandlerExceptionResolver](https://docs.spring.io/spring/docs/4.3.9.RELEASE/javadoc-api/org/springframework/web/servlet/HandlerExceptionResolver.html) that sends exceptions to Sentry. Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](usage/), in order to do things like record breadcrumbs, set the current user, or manually send events. +The `sentry-spring` library provides [Spring MVC](https://spring.io/) support for Sentry via: + +- a [HandlerExceptionResolver](https://docs.spring.io/spring/docs/4.3.9.RELEASE/javadoc-api/org/springframework/web/servlet/HandlerExceptionResolver.html) that sends unhandled exceptions to Sentry. +- attaches HTTP request information to all `SentryEvent`s recorded within the scope of the request +- adds option to attach user information retrieved from HTTP request to all `SentryEvent`s recorded within the scope of the request +- adds a `SentryUserProvider` hook that can be used to provide additional user information + +Once this integration is configured you can _also_ use Sentry’s static API, [as shown on the usage page](usage/), in order to do things like record breadcrumbs, set the current user, or manually send events. + + + To use Sentry with Spring Boot, we recommend using Sentry Spring Boot integration as it provides richer configuration capabilities. + The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tree/master/sentry-spring). @@ -14,62 +25,96 @@ The source can be found [on GitHub](https://github.com/getsentry/sentry-java/tre io.sentry sentry-spring - {{ packages.version('sentry.java', '1.7.30') }} + {{ packages.version('sentry.java', '3.0.0') }} ``` ```groovy {tabTitle:Gradle} -implementation 'io.sentry:sentry-spring:{{ packages.version('sentry.java', '1.7.30') }}' +implementation 'io.sentry:sentry-spring:{{ packages.version('sentry.java', '3.0.0') }}' ``` ```scala {tabTitle: SBT} -libraryDependencies += "io.sentry" % "sentry-spring" % "{{ packages.version('sentry.java', '1.7.30') }}" +libraryDependencies += "io.sentry" % "sentry-spring" % "{{ packages.version('sentry.java', '3.0.0') }}" ``` For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-spring). ### Usage -The `sentry-spring` library provides two classes that can be enabled by registering them as Beans in your Spring application. +The `sentry-spring` library provides `@EnableSentry` annotation that registers all required Spring beans. `@EnableSentry` can be places on any class annotated with [@Configuration](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html) including main entry class in Spring Boot applications annotated with [@SpringBootApplication](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/SpringBootApplication.html). -#### Recording Exceptions +```java {tabTitle:Java} +import io.sentry.spring.EnableSentry; +// NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry +// project/dashboard +@EnableSentry(dsn = "___PUBLIC_DSN___") +@Configuration +class SentryConfiguration { +} +``` -In order to record all exceptions thrown by your controllers, you can register `io.sentry.spring.SentryExceptionResolver` as a Bean in your application. Once registered, all exceptions will be sent to Sentry and then passed on to the default exception handlers. +```kotlin {tabTitle:Kotlin} +import io.sentry.spring.EnableSentry +// NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry +// project/dashboard +@EnableSentry(dsn = "___PUBLIC_DSN___") +@Configuration +class SentryConfiguration +``` -Configuration via `web.xml`: +The DSN can be also proided through the system property `sentry.dsn`, environment variable `SENTRY_DSN` or the `dsn` property in `sentry.properties` file. [See the configuration page](/platforms/java/configuration/) for more details on external configuration. -```xml - -``` +#### Recording User Information From HTTP Request -Or via a configuration class: +In order to record user's IP address and `Principal#name` as the username, sending personal information flag has to be set to `true`. -```java -@Bean -public HandlerExceptionResolver sentryExceptionResolver() { - return new io.sentry.spring.SentryExceptionResolver(); +```Java {tabTitle:Java} +import io.sentry.spring.EnableSentry; + +@EnableSentry(dsn = "___PUBLIC_DSN___", sendDefaultPii = true) +@Configuration +class SentryConfiguration { } ``` -Next, **you’ll need to configure your DSN** (client key) and optionally other values such as `environment` and `release`. [See the configuration page](configuration/options/#setting-the-dsn) for ways you can do this. - -#### Spring Boot HTTP Data +```kotlin {tabTitle:Kotlin} +import io.sentry.spring.EnableSentry -Spring Boot doesn’t automatically load any `javax.servlet.ServletContainerInitializer`, which means the Sentry SDK doesn’t have an opportunity to hook into the request cycle to collect information about the HTTP request. In order to add HTTP request data to your Sentry events in Spring Boot, you need to register the `io.sentry.spring.SentryServletContextInitializer` class as a Bean in your application. +@EnableSentry(dsn = "...", sendDefaultPii = true) +@Configuration +class SentryConfiguration +``` -Configuration via `web.xml`: +#### Recording Custom User Information -```xml - -``` +In order to record custom user information, you care register a bean that implements `SentryUserProvider` interface. -Or via a configuration class: +```java {tabTitle:Java} +import org.springframework.stereotype.Component; +import io.sentry.core.protocol.User; +import io.sentry.spring.SentryUserProvider; -```java -@Bean -public ServletContextInitializer sentryServletContextInitializer() { - return new io.sentry.spring.SentryServletContextInitializer(); +@Component +class CustomSentryUserProvider implements SentryUserProvider { + public User provideUser() { + User user = User(); + // ... set user information + return user + } } ``` -After that, your Sentry events should contain information such as HTTP request headers. +```kotlin {tabTitle:Kotlin} +import org.springframework.stereotype.Component +import io.sentry.core.protocol.User +import io.sentry.spring.SentryUserProvider + +@Component +class CustomSentryUserProvider : SentryUserProvider { + override fun provideUser(): User? { + val user = User() + // ... set user information + return user + } +} +``` diff --git a/src/platforms/java/usage.mdx b/src/platforms/java/usage.mdx index 4da37453ed0ae..bd91ba9391233 100644 --- a/src/platforms/java/usage.mdx +++ b/src/platforms/java/usage.mdx @@ -11,211 +11,331 @@ redirect_from: io.sentry sentry - 1.7.30 + 3.0.0 ``` ```groovy {tabTitle:Gradle} -implementation 'io.sentry:sentry:1.7.30' +implementation 'io.sentry:sentry:3.0.0' ``` ```scala {tabTitle:SBT} -libraryDependencies += "io.sentry" % "sentry" % "1.7.30" +libraryDependencies += "io.sentry" % "sentry" % "3.0.0" ``` For other dependency managers see the [central Maven repository](https://search.maven.org/artifact/io.sentry/sentry-spring). -## Capture an Error +## Configuration -To report an event manually you need to initialize a `SentryClient`. It is recommended that you use the static API via the `Sentry` class, but you can also construct and manage your own `SentryClient` instance. An example of each style is shown below: +When Sentry is used in manual way, configuration options must be passed to a static `Sentry#init` method: -```java -import io.sentry.context.Context; -import io.sentry.event.BreadcrumbBuilder; -import io.sentry.event.UserBuilder; +```java {tabTitle:Java} +import io.sentry.Sentry; public class MyClass { - private static SentryClient sentry; - - public static void main(String... args) { - /* - It is recommended that you use the DSN detection system, which - will check the environment variable "SENTRY_DSN", the Java - System Property "sentry.dsn", or the "sentry.properties" file - in your classpath. This makes it easier to provide and adjust - your DSN without needing to change your code. See the configuration - page for more information. - - For example, using an environment variable - - export SENTRY_DSN="___PUBLIC_DSN___" - */ - Sentry.init(); - - // You can also manually provide the DSN to the ``init`` method. - // Sentry.init("___PUBLIC_DSN___"); - - /* - It is possible to go around the static ``Sentry`` API, which means - you are responsible for making the SentryClient instance available - to your code. - */ - sentry = SentryClientFactory.sentryClient(); - - MyClass myClass = new MyClass(); - myClass.logWithStaticAPI(); - myClass.logWithInstanceAPI(); - } + public static void main(String... args) { + Sentry.init( + options -> { + // NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in + // your Sentry project/dashboard + options.setDsn("https://f7f320d5c3a54709be7b28e0f2ca7081@sentry.io/1808954"); + + // All events get assigned to the release. See more at + // https://docs.sentry.io/workflow/releases/ + options.setRelease("io.sentry.samples.console@3.0.0+1"); + + // Modifications to event before it goes out. Could replace the event altogether + options.setBeforeSend( + (event, hint) -> { + // Drop an event altogether: + if (event.getTag("SomeTag") != null) { + return null; + } + return event; + }); + + // Allows inspecting and modifying, returning a new or simply rejecting (returning null) + options.setBeforeBreadcrumb( + (breadcrumb, hint) -> { + // Don't add breadcrumbs with message containing: + if (breadcrumb.getMessage() != null + && breadcrumb.getMessage().contains("bad breadcrumb")) { + return null; + } + return breadcrumb; + }); + + // Configure the background worker which sends events to sentry: + // Wait up to 5 seconds before shutdown while there are events to send. + options.setShutdownTimeout(5000); + + // Enable SDK logging with Debug level + options.setDebug(true); + // To change the verbosity, use: + // By default it's DEBUG. + options.setDiagnosticLevel( + SentryLevel + .ERROR); // A good option to have SDK debug log in prod is to use only level + // ERROR here. + + // Exclude frames from some packages from being "inApp" so are hidden by default in Sentry + // UI: + options.addInAppExclude("org.jboss"); + }); + } +} +``` - /** - * An example method that throws an exception. - */ - void unsafeMethod() { - throw new UnsupportedOperationException("You shouldn't call this!"); - } +```kotlin {tabTitle:Kotlin} +import io.sentry.SentryOptions.BeforeBreadcrumbCallback +import io.sentry.SentryOptions.BeforeSendCallback + +fun main() { + Sentry.init { + // NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in + // your Sentry project/dashboard + it.dsn = "https://f7f320d5c3a54709be7b28e0f2ca7081@sentry.io/1808954" + + // All events get assigned to the release. See more at + // https://docs.sentry.io/workflow/releases/ + it.release = "io.sentry.samples.console@3.0.0+1" + + // Modifications to event before it goes out. Could replace the event altogether + it.beforeSend = BeforeSendCallback { event: SentryEvent, hint: Any? -> + // Drop an event altogether: + if (event.getTag("SomeTag") != null) { + null + } else { + event + } + } - /** - * Examples using the (recommended) static API. - */ - void logWithStaticAPI() { - // Note that all fields set on the context are optional. Context data is copied onto - // all future events in the current context (until the context is cleared). - - // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept. - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage("User made an action").build() - ); - - // Set the user in the current context. - Sentry.getContext().setUser( - new UserBuilder().setEmail("hello@sentry.io").build() - ); - - // Add extra data to future events in this context. - Sentry.getContext().addExtra("extra", "thing"); - - // Add an additional tag to future events in this context. - Sentry.getContext().addTag("tagName", "tagValue"); - - /* - This sends a simple event to Sentry using the statically stored instance - that was created in the ``main`` method. - */ - Sentry.capture("This is a test"); - - try { - unsafeMethod(); - } catch (Exception e) { - // This sends an exception event to Sentry using the statically stored instance - // that was created in the ``main`` method. - Sentry.capture(e); + // Allows inspecting and modifying, returning a new or simply rejecting (returning null) + it.beforeBreadcrumb = BeforeBreadcrumbCallback { breadcrumb: Breadcrumb, hint: Any? -> + // Don't add breadcrumbs with message containing: + val message = breadcrumb.message + if (message != null && message.contains("bad breadcrumb")) { + null + } else { + breadcrumb + } } + + // Configure the background worker which sends events to sentry: + // Wait up to 5 seconds before shutdown while there are events to send. + it.shutdownTimeout = 5000 + + // Enable SDK logging with Debug level + it.isDebug = true + // To change the verbosity, use: + // By default it's DEBUG. + it.setDiagnosticLevel( + SentryLevel.ERROR) // A good option to have SDK debug log in prod is to use only level + // ERROR here. + + // Exclude frames from some packages from being "inApp" so are hidden by default in Sentry + // UI: + it.addInAppExclude("org.jboss") } +} +``` - /** - * Examples that use the SentryClient instance directly. - */ - void logWithInstanceAPI() { - // Retrieve the current context. - Context context = sentry.getContext(); +Find more configuration options in the [Configuration](/platforms/java/configuration/) section. - // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept. - context.recordBreadcrumb(new BreadcrumbBuilder().setMessage("User made an action").build()); +## Capture an Error - // Set the user in the current context. - context.setUser(new UserBuilder().setEmail("hello@sentry.io").build()); +To report an event manually you need to initialize a `Sentry` class. It is recommended that you use the static API via the `Sentry` class, but you can also construct and manage your own `IHub` instance. An example of each style is shown below: - // This sends a simple event to Sentry. - sentry.sendMessage("This is a test"); +```java +import io.sentry.HubAdapter; +import io.sentry.IHub; +import io.sentry.Sentry; +import io.sentry.protocol.User; - try { - unsafeMethod(); - } catch (Exception e) { - // This sends an exception event to Sentry. - sentry.sendException(e); - } +public class MyClass { + private static IHub hub; + + public static void main(String... args) { + // NOTE: Replace the test DSN below with YOUR OWN DSN + Sentry.init(options -> { + options.setDsn("https://f7f320d5c3a54709be7b28e0f2ca7081@sentry.io/1808954"); + }); + + /* + It is possible to go around the static Sentry API, which means + you are responsible for making the IHub instance available + to your code. + */ + hub = HubAdapter.getInstance(); + + MyClass myClass = new MyClass(); + myClass.logWithStaticAPI(); + myClass.logWithInstanceAPI(); + } + + /** + * An example method that throws an exception. + */ + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } + + /** + * Examples using the (recommended) static API. + */ + void logWithStaticAPI() { + // Note that all fields set on the scope are optional. Scope data is copied onto + // all future events in the current scope (until the scope is cleared). + + // Record a breadcrumb in the current scope. By default the last 100 breadcrumbs are kept. + Sentry.addBreadcrumb("User made an action"); + + // Set the user in the current scope. + Sentry.configureScope(scope -> { + User user = new User(); + user.setEmail("hello@sentry.io"); + scope.setUser(user); + }); + + // Add extra data to future events in this scope. + Sentry.configureScope(scope -> { + scope.setExtra("extra", "thing"); + }); + + // Add an additional tag to future events in this scope. + Sentry.configureScope(scope -> { + scope.setTag("tagName", "tagValue"); + }); + + /* + This sends a simple event to Sentry using the statically stored instance + that was created in the ``main`` method. + */ + Sentry.captureMessage("This is a test"); + + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry using the statically stored instance + // that was created in the ``main`` method. + Sentry.captureException(e); } + } + + /** + * Examples that use the SentryClient instance directly. + */ + void logWithInstanceAPI() { + + // Record a breadcrumb in the current scope. By default the last 100 breadcrumbs are kept. + hub.addBreadcrumb("User made an action"); + + // Set the user in the current scope. + hub.configureScope(scope -> { + User user = new User(); + user.setEmail("hello@sentry.io"); + scope.setUser(user); + }); + + // This sends a simple event to Sentry. + hub.captureMessage("This is a test"); + + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry. + hub.captureException(e); + } + } } ``` ### Building More Complex Events -For more complex messages, you’ll need to build an `Event` with the `EventBuilder` class: +For more complex messages, you’ll need to build an `SentryEvent` object: ```java import io.sentry.Sentry; - import io.sentry.event.Event; - import io.sentry.event.EventBuilder; - import io.sentry.event.interfaces.ExceptionInterface; - - public class MyClass { - public static void main(String... args) { - Sentry.init(); - } - - void unsafeMethod() { - throw new UnsupportedOperationException("You shouldn't call this!"); - } - - void logSimpleMessage() { - // This sends an event to Sentry. - EventBuilder eventBuilder = new EventBuilder() - .withMessage("This is a test") - .withLevel(Event.Level.INFO) - .withLogger(MyClass.class.getName()); - - // Note that the *unbuilt* EventBuilder instance is passed in so that - // EventBuilderHelpers are run to add extra information to your event. - Sentry.capture(eventBuilder); - } - - void logException() { - try { - unsafeMethod(); - } catch (Exception e) { - // This sends an exception event to Sentry. - EventBuilder eventBuilder = new EventBuilder() - .withMessage("Exception caught") - .withLevel(Event.Level.ERROR) - .withLogger(MyClass.class.getName()) - .withSentryInterface(new ExceptionInterface(e)); - - // Note that the *unbuilt* EventBuilder instance is passed in so that - // EventBuilderHelpers are run to add extra information to your event. - Sentry.capture(eventBuilder); - } - } +import io.sentry.SentryEvent; +import io.sentry.SentryLevel; +import io.sentry.protocol.Message; + +public class MyClass { + public static void main(String... args) { + // NOTE: Replace the test DSN below with YOUR OWN DSN + Sentry.init(options -> { + options.setDsn("https://f7f320d5c3a54709be7b28e0f2ca7081@sentry.io/1808954"); + }); + } + + void unsafeMethod() { + throw new UnsupportedOperationException("You shouldn't call this!"); + } + + void logSimpleMessage() { + // This sends an event to Sentry. + SentryEvent event = new SentryEvent(); + Message message = new Message(); + message.setMessage("This is a test"); + event.setMessage(message); + event.setLevel(SentryLevel.INFO); + event.setLogger(MyClass.class.getName()); + + Sentry.captureEvent(event); + } + + void logException() { + try { + unsafeMethod(); + } catch (Exception e) { + // This sends an exception event to Sentry. + SentryEvent event = new SentryEvent(); + Message message = new Message(); + message.setMessage("Exception caught"); + event.setMessage(message); + event.setLevel(SentryLevel.INFO); + event.setLogger(MyClass.class.getName()); + event.setThrowable(e); + + Sentry.captureEvent(event); + } + } } ``` ### Automatically Enhancing Events -You can also implement an `EventBuilderHelper` that is able to automatically enhance outgoing events. +You can also implement an `EventProcesor` that is able to automatically enhance outgoing events. ```java +import io.sentry.EventProcessor; +import io.sentry.HubAdapter; +import io.sentry.IHub; import io.sentry.Sentry; -import io.sentry.SentryClient; -import io.sentry.event.EventBuilder; -import io.sentry.event.helper.EventBuilderHelper; +import io.sentry.SentryEvent; +import io.sentry.protocol.Message; public class MyClass { - public void myMethod() { - SentryClient client = Sentry.getStoredClient(); - - EventBuilderHelper myEventBuilderHelper = new EventBuilderHelper() { - @Override - public void helpBuildingEvent(EventBuilder eventBuilder) { - eventBuilder.withMessage("Overwritten by myEventBuilderHelper!"); - } - }; - - // Add an ``EventBuilderHelper`` to the current client instance. Note that - // this helper will process *all* future events. - client.addBuilderHelper(myEventBuilderHelper); + public void myMethod() { + IHub hub = HubAdapter.getInstance(); + + // Add an `EventProcessor` to the current scope. Note that + // this helper will process *all* future events in this scope. + hub.configureScope(scope -> { + scope.addEventProcessor(new EventProcessor() { + @Override + public SentryEvent process(SentryEvent event, Object hint) { + Message message = new Message(); + message.setMessage("Overwritten by myEventBuilderHelper!"); + event.setMessage(message); + return event; + } + }); + }); - // Send an event to Sentry. During construction of the event the message - // body will be overwritten by ``myEventBuilderHelper``. - Sentry.capture("Hello, world!"); - } + // Send an event to Sentry. During construction of the event the message + // body will be overwritten by `myEventBuilderHelper`. + hub.captureMessage("Hello, world!"); + } } ```