diff --git a/.gitignore b/.gitignore index af078f2..13c5e2f 100644 --- a/.gitignore +++ b/.gitignore @@ -289,3 +289,5 @@ nbdist/ /gateway.iml *.iml + +.sentryEnabled diff --git a/build.gradle b/build.gradle index 5065949..3c1d4f5 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ plugins { id 'io.spring.dependency-management' version '1.0.9.RELEASE' id 'java' id 'checkstyle' + id "com.gorylenko.gradle-git-properties" version "2.2.2" } group = 'de.the-morpheus.e-du' @@ -17,6 +18,7 @@ configurations { compileOnly { extendsFrom annotationProcessor } + compile.exclude module: 'spring-boot-starter-logging' } repositories { @@ -26,11 +28,16 @@ repositories { dependencies { /* Utility */ - compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final' + implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' compile 'com.jcabi:jcabi-manifests:0.7.5' implementation 'com.auth0:java-jwt:3.10.1' + implementation 'org.apache.logging.log4j:log4j-core:2.12.0' + implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.12.0' + implementation ('io.sentry:sentry-log4j2:1.7.30') { + exclude group: "org.apache.logging.log4j" + } /* GraphQL */ implementation 'com.graphql-java-kickstart:graphql-spring-boot-starter:7.0.0' @@ -38,9 +45,20 @@ dependencies { compile group: 'com.graphql-java-kickstart', name: 'playground-spring-boot-starter', version: '7.0.0' /* Spring */ - implementation 'org.springframework.boot:spring-boot-starter' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - compile group: 'org.springframework', name: 'spring-webmvc', version: '5.2.5.RELEASE' + implementation ('org.springframework.boot:spring-boot-starter') { + exclude group: "commons-logging", module: "commons-logging" + exclude module: "spring-boot-starter-logging" + } + + developmentOnly ('org.springframework.boot:spring-boot-devtools'){ + exclude group: "commons-logging", module: "commons-logging" + exclude module: "spring-boot-starter-logging" + } + + compile (group: 'org.springframework', name: 'spring-webmvc', version: '5.2.5.RELEASE') { + exclude group: "commons-logging", module: "commons-logging" + exclude module: "spring-boot-starter-logging" + } /* Test */ testImplementation 'org.springframework.security:spring-security-test' @@ -54,20 +72,11 @@ test { useJUnitPlatform() } -def getGitHash = { -> - def stdout = new ByteArrayOutputStream() - exec { - commandLine 'git', 'rev-parse', '--short', 'HEAD' - standardOutput = stdout - } - return stdout.toString().trim() -} bootJar { manifest { attributes 'Implementation-Version': project.version.toString() attributes 'Implementation-Title': project.name.toString() - attributes 'Commit-Id': getGitHash() attributes 'Build-Time': System.currentTimeMillis() } } \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index fb3fb9d..0953641 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,3 +12,4 @@ services: JWT_SECRET: SECRET SERVICE_SECRET: SECRET PRODUCTIVE: "false" + SENTRY_ENABLED: "${SENTRY_ENABLED}" diff --git a/run.sh b/run.sh index 7723a60..e330f35 100755 --- a/run.sh +++ b/run.sh @@ -3,5 +3,13 @@ sh build.sh sudo sh buildDocker.sh -sudo docker-compose up +echo "Search for sentry configuration" +# Checks whether the file "_.sentryEnabled" exists +sentryEnabled=false +if [ -e .sentryEnabled ]; then + sentryEnabled=true +fi +echo "Sentry reporting enabled: ${sentryEnabled}" + +sudo SENTRY_ENABLED="$sentryEnabled" docker-compose up sudo docker-compose down diff --git a/src/main/java/de/themorpheus/edu/gateway/GatewayApplication.java b/src/main/java/de/themorpheus/edu/gateway/GatewayApplication.java index a2a5ce7..7e32aac 100644 --- a/src/main/java/de/themorpheus/edu/gateway/GatewayApplication.java +++ b/src/main/java/de/themorpheus/edu/gateway/GatewayApplication.java @@ -1,16 +1,29 @@ package de.themorpheus.edu.gateway; +import de.themorpheus.edu.gateway.util.GitInfo; +import com.jcabi.manifests.Manifests; +import io.sentry.Sentry; +import io.sentry.SentryClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.io.IOException; @SpringBootApplication public class GatewayApplication { + public static final boolean PRODUCTIVE = Boolean.parseBoolean(System.getenv("PRODUCTIVE")); + public static final boolean SENTRY_ENABLED = Boolean.parseBoolean(System.getenv("SENTRY_ENABLED")); + + private static final Logger LOGGER = LoggerFactory.getLogger(GatewayApplication.class.getSimpleName()); + public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); + initSentry(); } @Bean @@ -28,4 +41,36 @@ public void addCorsMappings(CorsRegistry registry) { }; } + private static void initSentry() { + if (!PRODUCTIVE && !SENTRY_ENABLED) { + Sentry.init(""); + LOGGER.info("Sentry error reporting is disabled."); + return; + } + + Sentry.init("https://198f56a887e14287bbf3e6d1b6fd2a5d@sentry.the-morpheus.de/9"); + SentryClient sentry = Sentry.getStoredClient(); + sentry.addTag("OS", System.getProperty("OS")); + sentry.addTag("version", GatewayApplication.class.getPackage().getImplementationVersion()); + sentry.addTag("title", GatewayApplication.class.getPackage().getImplementationTitle()); + sentry.addTag("environment", PRODUCTIVE ? "production" : "dev"); + + try { + GitInfo gitInfo = GitInfo.load(); + sentry.addTag("build-host", gitInfo.getBuildHost()); + sentry.addTag("build-time", Manifests.read("Build-Time")); + sentry.addTag("build-user-email", gitInfo.getBuildUserEmail()); + sentry.addTag("build-version", gitInfo.getBuildVersion()); + sentry.addTag("git-branch", gitInfo.getBranch()); + sentry.addTag("git-commit-id", gitInfo.getCommitId()); + sentry.addTag("git-commit-message", gitInfo.getCommitMessageShort()); + sentry.addTag("git-commit-user-email", gitInfo.getCommitUserEmail()); + sentry.addTag("git-dirty", gitInfo.getGitDirty()); + } catch (IOException ex) { + LOGGER.error("Error while loading git information", ex); + } + + LOGGER.info("Sentry error reporting is enabled."); + } + } diff --git a/src/main/java/de/themorpheus/edu/gateway/graphql/resolver/query/ServiceInfoResolver.java b/src/main/java/de/themorpheus/edu/gateway/graphql/resolver/query/ServiceInfoResolver.java index bddd47a..82aa095 100644 --- a/src/main/java/de/themorpheus/edu/gateway/graphql/resolver/query/ServiceInfoResolver.java +++ b/src/main/java/de/themorpheus/edu/gateway/graphql/resolver/query/ServiceInfoResolver.java @@ -1,23 +1,44 @@ package de.themorpheus.edu.gateway.graphql.resolver.query; import de.themorpheus.edu.gateway.graphql.dto.generic.ServiceInfoDTO; +import de.themorpheus.edu.gateway.util.GitInfo; import com.jcabi.manifests.Manifests; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import java.io.IOException; import graphql.kickstart.tools.GraphQLQueryResolver; import graphql.schema.DataFetchingEnvironment; @Component public class ServiceInfoResolver implements GraphQLQueryResolver { - private static final ServiceInfoDTO GATEWAY = new ServiceInfoDTO( - "Gateway", - ServiceInfoResolver.class.getPackage().getImplementationVersion(), - Manifests.read("Commit-Id"), - Long.parseLong(Manifests.read("Build-Time")) - ); + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceInfoResolver.class.getSimpleName()); + + private static ServiceInfoDTO GATEWAY; + + static { + try { + GitInfo info = GitInfo.load(); + GATEWAY = new ServiceInfoDTO( + "Gateway", + ServiceInfoResolver.class.getPackage().getImplementationVersion(), + info.getCommitId(), + Long.parseLong(Manifests.read("Build-Time")) + ); + } catch (IOException ex) { + LOGGER.error("Error while initializing service info using git properties", ex); + GATEWAY = new ServiceInfoDTO( + "Gateway", + ServiceInfoResolver.class.getPackage().getImplementationVersion(), + "", + -1 + ); + } + } public ServiceInfoDTO serviceInfoByName(@NotNull @NotEmpty @NotBlank String name, DataFetchingEnvironment environment) { return GATEWAY; diff --git a/src/main/java/de/themorpheus/edu/gateway/util/GitInfo.java b/src/main/java/de/themorpheus/edu/gateway/util/GitInfo.java new file mode 100644 index 0000000..7296a56 --- /dev/null +++ b/src/main/java/de/themorpheus/edu/gateway/util/GitInfo.java @@ -0,0 +1,40 @@ +package de.themorpheus.edu.gateway.util; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import java.io.IOException; +import java.util.Properties; + +@Data +@AllArgsConstructor +public class GitInfo { + + private String branch; + private String buildHost; + private String buildUserEmail; + private String buildVersion; + private String commitId; + private String commitMessageShort; + private String commitUserEmail; + private String gitDirty; + + public static GitInfo load() throws IOException { + Resource resource = new ClassPathResource("git.properties"); + Properties properties = new Properties(); + properties.load(resource.getInputStream()); + + return new GitInfo( + properties.getProperty("git.branch"), + properties.getProperty("git.build.host"), + properties.getProperty("git.build.user.email"), + properties.getProperty("git.build.version"), + properties.getProperty("git.commit.id"), + properties.getProperty("git.commit.message.short"), + properties.getProperty("git.commit.user.email"), + properties.getProperty("git.dirty") + ); + } + +} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..dfb1dc5 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,43 @@ + + + + + + + %style{[}{dim,white}%d{HH:mm:ss}%style{][}{dim,white}%highlight{%-5.5level{INFO=INFO, + WARN=WARN, ERROR=ERROR, DEBUG=DEBUG}}{ERROR=red, DEBUG=blue, + INFO=green}%style{][}{dim,white}%style{%logger}{dark,cyan}%style{]}{dim,white}: + %highlight{%msg%n%throwable}{ERROR=red, DEBUG=blue, INFO=default} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/sentry.properties b/src/main/resources/sentry.properties new file mode 100644 index 0000000..ca1e05c --- /dev/null +++ b/src/main/resources/sentry.properties @@ -0,0 +1 @@ +stacktrace.app.packages= # Disables the console warning