From 2280c15f9022bf36ee53b96e08e19b47246b86ae Mon Sep 17 00:00:00 2001 From: Romuald Lemesle Date: Fri, 8 Mar 2024 09:22:07 +0100 Subject: [PATCH] [telemetry] Add telemetry with first metric --- openbas-api/pom.xml | 38 ++++++++++-- .../java/io/openbas/rest/user/UserApi.java | 8 +++ .../telemetry/OpenTelemetryConfig.java | 60 +++++++++++++++++++ .../telemetry/OpenTelemetryService.java | 37 ++++++++++++ .../src/main/resources/application.properties | 3 + 5 files changed, 141 insertions(+), 5 deletions(-) create mode 100644 openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryConfig.java create mode 100644 openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryService.java diff --git a/openbas-api/pom.xml b/openbas-api/pom.xml index 1d12b35ced..c7272a4246 100644 --- a/openbas-api/pom.xml +++ b/openbas-api/pom.xml @@ -21,6 +21,8 @@ 4.1.1 2.3.0 1.4 + 1.35.0 + 1.23.1-alpha @@ -71,6 +73,18 @@ + + + + io.opentelemetry + opentelemetry-bom + ${opentelemetry.version} + pom + import + + + + io.openbas @@ -198,6 +212,25 @@ httpclient5 ${httpclient5.version} + + + io.opentelemetry + opentelemetry-api + + + io.opentelemetry + opentelemetry-sdk + + + io.opentelemetry + opentelemetry-exporter-logging + + + io.opentelemetry.semconv + opentelemetry-semconv + ${opentelemetry-semconv.version} + + org.springframework.boot @@ -215,11 +248,6 @@ spring-security-test test - - com.h2database - h2 - test - diff --git a/openbas-api/src/main/java/io/openbas/rest/user/UserApi.java b/openbas-api/src/main/java/io/openbas/rest/user/UserApi.java index dba9aa77b9..1f97cab698 100644 --- a/openbas-api/src/main/java/io/openbas/rest/user/UserApi.java +++ b/openbas-api/src/main/java/io/openbas/rest/user/UserApi.java @@ -14,6 +14,7 @@ import io.openbas.rest.user.form.user.UpdateUserInput; import io.openbas.service.MailingService; import io.openbas.service.UserService; +import io.openbas.telemetry.OpenTelemetryService; import jakarta.annotation.Resource; import jakarta.transaction.Transactional; import jakarta.validation.Valid; @@ -41,6 +42,7 @@ public class UserApi extends RestBehavior { private TagRepository tagRepository; private UserService userService; private MailingService mailingService; + private OpenTelemetryService openTelemetryService; @Autowired public void setMailingService(MailingService mailingService) { @@ -67,6 +69,11 @@ public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } + @Autowired + public void setOpenTelemetryService(OpenTelemetryService openTelemetryService) { + this.openTelemetryService = openTelemetryService; + } + @PostMapping("/api/login") public User login(@Valid @RequestBody LoginUserInput input) { Optional optionalUser = userRepository.findByEmailIgnoreCase(input.getLogin()); @@ -74,6 +81,7 @@ public User login(@Valid @RequestBody LoginUserInput input) { User user = optionalUser.get(); if (userService.isUserPasswordValid(user, input.getPassword())) { userService.createUserSession(user); + this.openTelemetryService.login(user.getEmail()); return user; } } diff --git a/openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryConfig.java b/openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryConfig.java new file mode 100644 index 0000000000..a6aaaf8c6c --- /dev/null +++ b/openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryConfig.java @@ -0,0 +1,60 @@ +package io.openbas.telemetry; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.exporter.logging.LoggingMetricExporter; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.semconv.ResourceAttributes; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import static java.util.Objects.requireNonNull; + +@Service +@RequiredArgsConstructor +public class OpenTelemetryConfig { + + private final Environment env; + + @Bean + public OpenTelemetry openTelemetry() { + Resource resource = Resource.getDefault() + .toBuilder() + .put(ResourceAttributes.SERVICE_NAME, requireNonNull(this.env.getProperty("info.app.name"))) + .put(ResourceAttributes.SERVICE_VERSION, requireNonNull(this.env.getProperty("info.app.version"))) + .build(); + + SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder() + .registerMetricReader(PeriodicMetricReader.builder(LoggingMetricExporter.create()).build()) + .setResource(resource) + .build(); + + // TODO: Add file exporter + + return OpenTelemetrySdk.builder() + .setMeterProvider(sdkMeterProvider) + .setPropagators(ContextPropagators.create( + TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()) + )) + .build(); + } + + @Bean + public Meter meter(@NotNull final OpenTelemetry openTelemetry) { + return openTelemetry.meterBuilder(requireNonNull(this.env.getProperty("info.app.version")).replace(" ", "-") + "-metric") + .setInstrumentationVersion("1.0.0") + .build(); + } + +} + diff --git a/openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryService.java b/openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryService.java new file mode 100644 index 0000000000..d9109c4ae1 --- /dev/null +++ b/openbas-api/src/main/java/io/openbas/telemetry/OpenTelemetryService.java @@ -0,0 +1,37 @@ +package io.openbas.telemetry; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.LongCounter; +import io.opentelemetry.api.metrics.Meter; +import jakarta.annotation.PostConstruct; +import jakarta.validation.constraints.NotBlank; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class OpenTelemetryService { + + private final Meter meter; + + private LongCounter longCounter; + + @PostConstruct + private void init() { + this.longCounter = this.meter + .counterBuilder("app.login") + .setDescription("Number of login connections") + .setUnit("connections") + .build(); + } + + public void login(@NotBlank final String email) { + this.longCounter.add( + 1, + Attributes.of(AttributeKey.stringKey("user.email"), email) + ); + this.longCounter.add(1); // Global login count + } + +} diff --git a/openbas-api/src/main/resources/application.properties b/openbas-api/src/main/resources/application.properties index 9ee76ffeae..c3fc9b3c76 100644 --- a/openbas-api/src/main/resources/application.properties +++ b/openbas-api/src/main/resources/application.properties @@ -118,6 +118,9 @@ logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.-%d{yyyy-MM-dd}.%i logging.logback.rollingpolicy.max-file-size=10MB logging.logback.rollingpolicy.max-history=7 +# Telemetry +logging.level.io.opentelemetry.exporter.logging=info + ############# # INJECTORS # #############