From f46bdf35ab90ebf742efd93bc132b7534cb457a9 Mon Sep 17 00:00:00 2001 From: pvannierop Date: Fri, 13 Sep 2024 17:25:29 +0200 Subject: [PATCH] Impl. support for Sentry monitoring --- radar-commons-gradle/README.md | 102 ++++++++++++++++++ radar-commons-gradle/build.gradle.kts | 2 + .../gradle/plugin/RadarKotlinPlugin.kt | 32 ++++++ 3 files changed, 136 insertions(+) diff --git a/radar-commons-gradle/README.md b/radar-commons-gradle/README.md index a860f24b..8faf7209 100644 --- a/radar-commons-gradle/README.md +++ b/radar-commons-gradle/README.md @@ -2,6 +2,16 @@ A Gradle plugin to do some common RADAR-base tasks. + +* [radar-commons-gradle](#radar-commons-gradle) + * [Usage](#usage) + * [radar-commons-gradle plugin](#radar-commons-gradle-plugin) + * [radarKotlin extension](#radarkotlin-extension) + * [Enable logging with log4j2](#enable-logging-with-log4j2) + * [Enable monitoring with Sentry](#enable-monitoring-with-sentry) + * [Enable Sentry source context](#enable-sentry-source-context) + + ## Usage Add the following block to `settings.gradle.kts` to get access to the RADAR-base plugins. @@ -51,6 +61,13 @@ subprojects { kotlinVersion.set(Versions.Plugins.kotlin) // already has a default value junitVersion.set(Versions.junit) // already has a default value ktlintVersion.set(Versions.ktlint) // already has a default value + slf4jVersion.set(Versions.slf4j) // already has a default value + // log4j2Version.set(Versions.log4j2) // setting this will enable log4j2 + // sentryVersion.set(Versions.sentry) // setting this will enable Sentry monitoring + // sentryEnabled.set(false) // setting this to true will enable Sentry monitoring + // sentryOrganization.set("radar-base") // already has a default value + // sentryProject.set("") // already has a default value + // sentrySourceContextToken.set("") // setting this will add the source context to Sentry } // Both values are required to be set to use radar-publishing. @@ -68,3 +85,88 @@ subprojects { } } ``` + +## radar-commons-gradle plugin + +This plugin provides the basics for RADAR-base projects. + +### radarKotlin extension + +#### Enable logging with log4j2 + +By default, no logging implementation is added to projects (only the slf4j interface is included). To enable log4j2, add +the following to your root project configurations: + +```gradle +... +subprojects { + ... + radarKotlin { + log4j2Version.set(Versions.log4j2) + } + ... +} +``` + +#### Enable monitoring with Sentry + +1. Activate log4j2 logging (see [above](#enable-logging-with-log4j2)) +2. Activate Sentry in the _radarKotlin_ extension: + +```gradle +... +subprojects { + ... + radarKotlin { + sentryEnabled.set(true) + } + ... +} +``` + +3. Add a Sentry log Appender to the `log4j2.xml` configuration file to `src/main/resources`. For example: + +```xml + + + + + + + + + + + + + + + +``` + +4. Set the `SENTRY_DSN` environment variable at runtime to the DSN of your Sentry project. + +#### Enable Sentry source context + +Sentry can be configured to show the source code context of the error. For this to work, source code can be uploaded +to the target sentry organization and project during the build phase. To enable this, set the following values: + +```gradle +... +subprojects { + ... + radarKotlin { + sentrySourceContextToken.set("my-token") + sentryOrganization.set("my-organization") + sentryProject.set("my-project") + } + ... +} +``` + +NOTE: The organization and project must correspond to the values for the monitoring environment in Sentry. The +organization and project are encooded in Sentry OAuth token. + + diff --git a/radar-commons-gradle/build.gradle.kts b/radar-commons-gradle/build.gradle.kts index b24acd5e..aa0919f4 100644 --- a/radar-commons-gradle/build.gradle.kts +++ b/radar-commons-gradle/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { implementation("io.github.gradle-nexus:publish-plugin:${Versions.Plugins.publishPlugin}") implementation("org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktlint}") implementation("com.github.jk1.dependency-license-report:com.github.jk1.dependency-license-report.gradle.plugin:${Versions.Plugins.licenseReport}") + implementation("io.sentry.jvm.gradle:io.sentry.jvm.gradle.gradle.plugin:${Versions.sentry}") } gradlePlugin { @@ -209,4 +210,5 @@ object Versions { const val guava = "32.1.1-jre" const val gradleVersionsPlugin = "0.50.0" const val ktlint = "12.0.3" + const val sentry = "4.10.0" } diff --git a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt index b3c4f059..0c396c9e 100644 --- a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt +++ b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt @@ -1,6 +1,8 @@ package org.radarbase.gradle.plugin import com.github.jk1.license.LicenseReportPlugin +import io.sentry.android.gradle.extensions.SentryPluginExtension +import io.sentry.jvm.gradle.SentryJvmPlugin import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.ApplicationPlugin @@ -42,6 +44,10 @@ interface RadarKotlinExtension { val log4j2Version: Property val slf4jVersion: Property val ktlintVersion: Property + val sentryEnabled: Property + val sentryOrganization: Property + val sentryProject: Property + val sentrySourceContextToken: Property } class RadarKotlinPlugin : Plugin { @@ -53,11 +59,18 @@ class RadarKotlinPlugin : Plugin { junitVersion.convention(Versions.junit) ktlintVersion.convention(Versions.ktlint) slf4jVersion.convention(Versions.ktlint) + sentryEnabled.convention(false) + sentryOrganization.convention("radar-base") + sentryProject.convention(project.name) + sentrySourceContextToken.convention("") } apply(plugin = "kotlin") apply() + // SentryJvmPlugin will be removed in afterEvaluate when sentryEnabled == false. + apply() + repositories { mavenCentral { mavenContent { @@ -162,6 +175,18 @@ class RadarKotlinPlugin : Plugin { implementation("org.slf4j:slf4j-api:${extension.slf4jVersion.get()}") } } + if (extension.sentryEnabled.get()) { + val sentry = extensions.get("sentry") as SentryPluginExtension + sentry.org.set(extension.sentryOrganization) + sentry.projectName.set(extension.sentryProject) + if (extension.sentrySourceContextToken.isPresent && + extension.sentrySourceContextToken.get().isNotEmpty() + ) { + // Passing the source context token will activate upload of our source code to Sentry. + sentry.includeSourceContext.set(true) + sentry.authToken.set(extension.sentrySourceContextToken) + } + } if (extension.log4j2Version.isPresent) { dependencies { val log4j2Version = extension.log4j2Version.get() @@ -171,6 +196,10 @@ class RadarKotlinPlugin : Plugin { runtimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl:$log4j2Version") runtimeOnly("org.apache.logging.log4j:log4j-core:$log4j2Version") runtimeOnly("org.apache.logging.log4j:log4j-jul:$log4j2Version") + if (extension.sentryEnabled.get()) { + val annotationProcessor by configurations + annotationProcessor("org.apache.logging.log4j:log4j-core:$log4j2Version") + } } else { val testRuntimeOnly by configurations testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl:$log4j2Version") @@ -195,6 +224,9 @@ class RadarKotlinPlugin : Plugin { } } } + + } else { + plugins.removeIf({ it is SentryJvmPlugin }) } }