diff --git a/backend/Dockerfile b/backend/Dockerfile
index ff87c55bd7..40e635565a 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -35,4 +35,4 @@ EXPOSE ${PORT}
HEALTHCHECK CMD curl -f http://localhost:${PORT}/actuator/health | grep '"status":"UP"'
# Startup
-ENTRYPOINT ["/app/nr-forest-client-backend"]
\ No newline at end of file
+ENTRYPOINT ["/app/nr-forest-client-backend","--spring.profiles.active=container"]
\ No newline at end of file
diff --git a/backend/pom.xml b/backend/pom.xml
index f6dab5a3b8..5f602f5e58 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -75,10 +75,25 @@
org.springframework.boot
spring-boot-starter-aop
+
io.micrometer
micrometer-registry-prometheus
+
+ io.micrometer
+ micrometer-tracing-bridge-otel
+
+
+ io.opentelemetry
+ opentelemetry-exporter-zipkin
+
+
+ org.springframework.experimental
+ r2dbc-micrometer-spring-boot
+ 1.0.2
+
+
org.springframework
spring-jdbc
@@ -96,6 +111,7 @@
org.flywaydb
flyway-core
+
org.apache.commons
commons-lang3
@@ -110,6 +126,7 @@
lombok
true
+
org.springframework.boot
spring-boot-starter-test
@@ -172,6 +189,20 @@
reactor-netty-http
1.1.13
+
+ io.micrometer
+ micrometer-bom
+ ${micrometer.version}
+ pom
+ import
+
+
+ io.micrometer
+ micrometer-tracing-bom
+ ${micrometer-tracing.version}
+ pom
+ import
+
@@ -203,10 +234,10 @@
-H:+ReportExceptionStackTraces
- --trace-class-initialization=org.apache.commons.logging.LogFactoryService
- --trace-class-initialization=org.apache.commons.logging.LogFactory
+ --trace-class-initialization=org.apache.commons.logging.LogFactoryService,io.micrometer.common.util.internal.logging.LocationAwareSlf4JLogger,ch.qos.logback.classic.Logger
+ --trace-class-initialization=org.apache.commons.logging.LogFactory,io.micrometer.common.util.internal.logging.LocationAwareSlf4JLogger,ch.qos.logback.classic.Logger
- --initialize-at-build-time=org.apache.commons.logging.LogFactoryService
+ --initialize-at-build-time=org.apache.commons.logging.LogFactoryService,io.micrometer.common.util.internal.logging.LocationAwareSlf4JLogger,ch.qos.logback.classic.Logger
diff --git a/backend/src/main/java/ca/bc/gov/app/BootApplication.java b/backend/src/main/java/ca/bc/gov/app/BootApplication.java
index 0d9392925f..d2eef3b941 100644
--- a/backend/src/main/java/ca/bc/gov/app/BootApplication.java
+++ b/backend/src/main/java/ca/bc/gov/app/BootApplication.java
@@ -1,14 +1,19 @@
package ca.bc.gov.app;
+import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
+import reactor.core.publisher.Hooks;
@SpringBootApplication
@EnableScheduling
public class BootApplication {
public static void main(String[] args) {
+ SLF4JBridgeHandler.removeHandlersForRootLogger();
+ SLF4JBridgeHandler.install();
+ Hooks.enableAutomaticContextPropagation();
SpringApplication.run(BootApplication.class, args);
}
diff --git a/backend/src/main/java/ca/bc/gov/app/configuration/TracingConfiguration.java b/backend/src/main/java/ca/bc/gov/app/configuration/TracingConfiguration.java
new file mode 100644
index 0000000000..1683becb6e
--- /dev/null
+++ b/backend/src/main/java/ca/bc/gov/app/configuration/TracingConfiguration.java
@@ -0,0 +1,28 @@
+package ca.bc.gov.app.configuration;
+
+import io.micrometer.observation.ObservationRegistry;
+import io.micrometer.observation.aop.ObservedAspect;
+import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
+import io.micrometer.tracing.annotation.MethodInvocationProcessor;
+import io.micrometer.tracing.annotation.SpanAspect;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration(proxyBeanMethods = false)
+@Slf4j
+public class TracingConfiguration {
+
+ @Bean
+ ObservedAspect observedAspect(
+ ObservationRegistry observationRegistry
+ ) {
+ ObservationThreadLocalAccessor.getInstance().setObservationRegistry(observationRegistry);
+ return new ObservedAspect(observationRegistry);
+ }
+
+ @Bean
+ SpanAspect spanAspect(MethodInvocationProcessor methodInvocationProcessor) {
+ return new SpanAspect(methodInvocationProcessor);
+ }
+}
diff --git a/backend/src/main/java/ca/bc/gov/app/controller/GlobalErrorController.java b/backend/src/main/java/ca/bc/gov/app/controller/GlobalErrorController.java
index 7a94133ca9..4ab150998a 100644
--- a/backend/src/main/java/ca/bc/gov/app/controller/GlobalErrorController.java
+++ b/backend/src/main/java/ca/bc/gov/app/controller/GlobalErrorController.java
@@ -1,6 +1,7 @@
package ca.bc.gov.app.controller;
import ca.bc.gov.app.exception.ValidationException;
+import io.micrometer.observation.annotation.Observed;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
@@ -31,6 +32,7 @@
@Slf4j
@Component
@Order(-2)
+@Observed
public class GlobalErrorController extends AbstractErrorWebExceptionHandler {
public GlobalErrorController(
diff --git a/backend/src/main/java/ca/bc/gov/app/controller/ches/ChesController.java b/backend/src/main/java/ca/bc/gov/app/controller/ches/ChesController.java
index deab97128d..c7bcf07ff5 100644
--- a/backend/src/main/java/ca/bc/gov/app/controller/ches/ChesController.java
+++ b/backend/src/main/java/ca/bc/gov/app/controller/ches/ChesController.java
@@ -2,6 +2,7 @@
import ca.bc.gov.app.dto.client.EmailRequestDto;
import ca.bc.gov.app.service.client.ClientService;
+import io.micrometer.observation.annotation.Observed;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
@@ -21,6 +22,7 @@
@Slf4j
@RequestMapping(value = "/api/ches", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
+@Observed
public class ChesController {
private final ClientService clientService;
diff --git a/backend/src/main/java/ca/bc/gov/app/controller/client/ClientAddressController.java b/backend/src/main/java/ca/bc/gov/app/controller/client/ClientAddressController.java
index b495bd79a0..400839a84f 100644
--- a/backend/src/main/java/ca/bc/gov/app/controller/client/ClientAddressController.java
+++ b/backend/src/main/java/ca/bc/gov/app/controller/client/ClientAddressController.java
@@ -3,6 +3,7 @@
import ca.bc.gov.app.dto.client.ClientAddressDto;
import ca.bc.gov.app.dto.client.CodeNameDto;
import ca.bc.gov.app.service.client.ClientAddressService;
+import io.micrometer.observation.annotation.Observed;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
@@ -18,6 +19,7 @@
@Slf4j
@RequestMapping(value = "/api/clients", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
+@Observed
public class ClientAddressController {
private final ClientAddressService clientAddressService;
@@ -30,6 +32,8 @@ public Flux findPossibleAddresses(
Integer maxSuggestions,
@RequestParam(value = "searchTerm", required = true)
String searchTerm) {
+ log.info("Requesting possible addresses for country: {}, maxSuggestions: {}, searchTerm: {}",
+ country, maxSuggestions, searchTerm);
return clientAddressService
.findPossibleAddresses(country, maxSuggestions, searchTerm);
}
@@ -37,6 +41,7 @@ public Flux findPossibleAddresses(
@GetMapping("/addresses/{addressId}")
public Mono getAddress(
@PathVariable String addressId) {
+ log.info("Requesting address for addressId: {}", addressId);
return clientAddressService
.getAddress(addressId);
}
diff --git a/backend/src/main/java/ca/bc/gov/app/controller/client/ClientController.java b/backend/src/main/java/ca/bc/gov/app/controller/client/ClientController.java
index 286fe895eb..cd45349009 100644
--- a/backend/src/main/java/ca/bc/gov/app/controller/client/ClientController.java
+++ b/backend/src/main/java/ca/bc/gov/app/controller/client/ClientController.java
@@ -7,6 +7,7 @@
import ca.bc.gov.app.dto.client.EmailRequestDto;
import ca.bc.gov.app.exception.NoClientDataFound;
import ca.bc.gov.app.service.client.ClientService;
+import io.micrometer.observation.annotation.Observed;
import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -30,6 +31,7 @@
@RequestMapping(value = "/api/clients", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
@Slf4j
+@Observed
public class ClientController {
private final ClientService clientService;
@@ -40,6 +42,7 @@ public Mono getClientDetails(
@RequestHeader(ApplicationConstant.USERID_HEADER) String userId,
@RequestHeader(name = ApplicationConstant.BUSINESSID_HEADER, defaultValue = StringUtils.EMPTY) String businessId
) {
+ log.info("Requesting client details for client number {} from the client service.", clientNumber);
return clientService.getClientDetails(clientNumber,userId,businessId);
}
@@ -48,7 +51,9 @@ public Flux listCountries(
@RequestParam(value = "page", required = false, defaultValue = "0")
Integer page,
@RequestParam(value = "size", required = false, defaultValue = "10")
- Integer size) {
+ Integer size
+ ) {
+ log.info("Requesting a list of countries from the client service.");
return clientService
.listCountries(page, size);
}
@@ -56,6 +61,7 @@ public Flux listCountries(
@GetMapping("/getCountryByCode/{countryCode}")
public Mono getCountryByCode(
@PathVariable String countryCode) {
+ log.info("Requesting a country by code {} from the client service.", countryCode);
return clientService.getCountryByCode(countryCode);
}
@@ -66,6 +72,7 @@ public Flux listProvinces(
Integer page,
@RequestParam(value = "size", required = false, defaultValue = "10")
Integer size) {
+ log.info("Requesting a list of provinces for country code {} from the client service.", countryCode);
return clientService
.listProvinces(countryCode, page, size);
}
@@ -73,11 +80,13 @@ public Flux listProvinces(
@GetMapping("/getClientTypeByCode/{code}")
public Mono getClientTypeByCode(
@PathVariable String code) {
+ log.info("Requesting a client type by code {} from the client service.", code);
return clientService.getClientTypeByCode(code);
}
@GetMapping("/activeClientTypeCodes")
public Flux findActiveClientTypeCodes() {
+ log.info("Requesting a list of active client type codes from the client service.");
return clientService
.findActiveClientTypeCodes(LocalDate.now());
}
@@ -89,6 +98,7 @@ public Flux listClientContactTypeCodes(
@RequestParam(value = "size", required = false, defaultValue = "10")
Integer size
) {
+ log.info("Requesting a list of active client contact type codes from the client service.");
return clientService
.listClientContactTypeCodes(LocalDate.now(),page, size);
}
@@ -103,6 +113,7 @@ public Flux listClientContactTypeCodes(
public Flux findByClientName(
@PathVariable String name
) {
+ log.info("Requesting a list of clients with name {} from the client service.", name);
return clientService
.findByClientNameOrIncorporation(name)
.map(client -> client.withName(WordUtils.capitalize(client.name())));
@@ -111,6 +122,7 @@ public Flux findByClientName(
@GetMapping(value = "/incorporation/{incorporationId}")
public Mono findByIncorporationNumber(
@PathVariable String incorporationId) {
+ log.info("Requesting a client with incorporation number {} from the client service.", incorporationId);
return clientService
.findByClientNameOrIncorporation(incorporationId)
.next()
@@ -133,6 +145,7 @@ public Mono sendEmail(
@RequestHeader(ApplicationConstant.USERID_HEADER) String userId,
@RequestHeader(name = ApplicationConstant.BUSINESSID_HEADER, defaultValue = StringUtils.EMPTY) String businessId
) {
+ log.info("Sending email to {} from the client service.", emailRequestDto.email());
return clientService.triggerEmailDuplicatedClient(emailRequestDto, userId, businessId);
}
diff --git a/backend/src/main/java/ca/bc/gov/app/controller/client/ClientSubmissionController.java b/backend/src/main/java/ca/bc/gov/app/controller/client/ClientSubmissionController.java
index 083ae38999..7a0a79cf5a 100644
--- a/backend/src/main/java/ca/bc/gov/app/controller/client/ClientSubmissionController.java
+++ b/backend/src/main/java/ca/bc/gov/app/controller/client/ClientSubmissionController.java
@@ -11,8 +11,10 @@
import ca.bc.gov.app.models.client.SubmissionStatusEnum;
import ca.bc.gov.app.service.client.ClientSubmissionService;
import ca.bc.gov.app.validator.client.ClientSubmitRequestValidator;
+import io.micrometer.observation.annotation.Observed;
import java.util.List;
import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -32,6 +34,8 @@
@RestController
@RequestMapping(value = "/api/clients/submissions", produces = MediaType.APPLICATION_JSON_VALUE)
+@Observed
+@Slf4j
public class ClientSubmissionController extends
AbstractController {
@@ -61,6 +65,8 @@ public Flux listSubmissions(
@RequestParam(required = false)
String[] updatedAt
) {
+ log.info("Listing submissions: page={}, size={}, requestType={}, requestStatus={}, clientType={}, name={}, updatedAt={}",
+ page, size, requestType, requestStatus, clientType, name, updatedAt);
return clientService
.listSubmissions(
page,
@@ -82,17 +88,23 @@ public Mono submit(
@RequestHeader(ApplicationConstant.USERMAIL_HEADER) String userEmail,
@RequestHeader(ApplicationConstant.USERNAME_HEADER) String userName,
ServerHttpResponse serverResponse) {
- return Mono.just(request)
+
+ return Mono
+ .just(request)
.switchIfEmpty(
Mono.error(new InvalidRequestObjectException("no request body was provided"))
)
+ .doOnNext(sub -> log.info("Submitting request: {}", sub))
.doOnNext(this::validate)
+ .doOnNext(sub -> log.info("Request is valid: {}", sub))
+ .doOnError(e -> log.error("Request is invalid: {}", e.getMessage()))
.flatMap(submissionDto -> clientService.submit(
submissionDto,
userId,
userEmail,
userName,
businessId))
+ .doOnNext(submissionId -> log.info("Submission persisted: {}", submissionId))
.doOnNext(submissionId ->
serverResponse
.getHeaders()
diff --git a/backend/src/main/java/ca/bc/gov/app/controller/cognito/CognitoController.java b/backend/src/main/java/ca/bc/gov/app/controller/cognito/CognitoController.java
index fa85523d38..306c5faf66 100644
--- a/backend/src/main/java/ca/bc/gov/app/controller/cognito/CognitoController.java
+++ b/backend/src/main/java/ca/bc/gov/app/controller/cognito/CognitoController.java
@@ -4,6 +4,7 @@
import ca.bc.gov.app.configuration.ForestClientConfiguration;
import ca.bc.gov.app.exception.UnableToProcessRequestException;
import ca.bc.gov.app.service.cognito.CognitoService;
+import io.micrometer.observation.annotation.Observed;
import java.time.Duration;
import java.util.UUID;
import java.util.stream.Stream;
@@ -27,6 +28,7 @@
@RestController
@Slf4j
@RequiredArgsConstructor
+@Observed
public class CognitoController {
public static final String LOCATION = "Location";
@@ -76,8 +78,11 @@ public Mono logon(
.getHeaders()
.add(LOCATION, famUrl);
+ log.info("Executing login for provider: {}", code);
+
return Mono.empty();
} else {
+ log.error("Invalid provider code: {}", code);
return Mono.error(new UnableToProcessRequestException("Invalid provider code."));
}
}
@@ -119,6 +124,8 @@ public Mono logout(
.getHeaders()
.add(LOCATION, famUrl);
+ log.info("Executing logout");
+
return Mono.empty();
}
@@ -126,6 +133,8 @@ public Mono logout(
@ResponseStatus(HttpStatus.FOUND)
public Mono refresh(@RequestParam String code, ServerHttpResponse serverResponse) {
+ log.info("Executing refresh for code: {}", code);
+
return
service
.refreshToken(code)
@@ -164,6 +173,8 @@ public Mono extractToken(
ServerHttpResponse serverResponse
) {
+ log.info("Extracting JWT from code: {}", code);
+
return
Mono
.just(code)
diff --git a/backend/src/main/java/ca/bc/gov/app/service/bcregistry/BcRegistryService.java b/backend/src/main/java/ca/bc/gov/app/service/bcregistry/BcRegistryService.java
index 74c897b2d9..41ade0ee42 100644
--- a/backend/src/main/java/ca/bc/gov/app/service/bcregistry/BcRegistryService.java
+++ b/backend/src/main/java/ca/bc/gov/app/service/bcregistry/BcRegistryService.java
@@ -15,6 +15,7 @@
import ca.bc.gov.app.dto.bcregistry.BcRegistryOfficesDto;
import ca.bc.gov.app.exception.InvalidAccessTokenException;
import ca.bc.gov.app.exception.NoClientDataFound;
+import io.micrometer.observation.annotation.Observed;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
@@ -29,6 +30,7 @@
@Slf4j
@Service
+@Observed
public class BcRegistryService {
private final WebClient bcRegistryApi;
@@ -37,7 +39,6 @@ public BcRegistryService(@Qualifier("bcRegistryApi") WebClient bcRegistryApi) {
this.bcRegistryApi = bcRegistryApi;
}
-
/**
* Searches the BC Registry API for {@link BcRegistryFacetSearchResultEntryDto} instances matching
* the given value.
diff --git a/backend/src/main/java/ca/bc/gov/app/service/ches/ChesService.java b/backend/src/main/java/ca/bc/gov/app/service/ches/ChesService.java
index 7e5ad922b1..40da8f8937 100644
--- a/backend/src/main/java/ca/bc/gov/app/service/ches/ChesService.java
+++ b/backend/src/main/java/ca/bc/gov/app/service/ches/ChesService.java
@@ -21,6 +21,8 @@
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
+import io.micrometer.observation.annotation.Observed;
+import io.r2dbc.postgresql.codec.Json;
import java.io.IOException;
import java.io.StringWriter;
import java.time.LocalDateTime;
@@ -43,6 +45,7 @@
@Service
@Slf4j
+@Observed
public class ChesService {
public static final String FAILED_TO_SEND_EMAIL = "Failed to send email: {}";
@@ -91,6 +94,8 @@ public Mono sendEmail(String templateName,
? subject
: String.format("[%s] %s", configuration.getCognito().getEnvironment(), subject);
+ log.info("Sending email to {} with subject {}", emailAddress, processedSubject);
+
return this
.buildTemplate(templateName, variables)
.map(body -> new ChesRequestDto(List.of(emailAddress), body))
@@ -132,6 +137,7 @@ public Mono sendEmail(String templateName,
}
private Mono saveEmailLog(EmailLogDto emailLogDto, String transactionMsg) {
+ log.info("Saving email log {}", emailLogDto.emailId());
if (emailLogDto.emailLogId() != null) {
return emailLogRepository.findById(emailLogDto.emailLogId())
.flatMap(existingLogEntity -> updateExistingLogEntity(
diff --git a/backend/src/main/java/ca/bc/gov/app/service/client/ClientAddressService.java b/backend/src/main/java/ca/bc/gov/app/service/client/ClientAddressService.java
index bd29b97347..e74030c252 100644
--- a/backend/src/main/java/ca/bc/gov/app/service/client/ClientAddressService.java
+++ b/backend/src/main/java/ca/bc/gov/app/service/client/ClientAddressService.java
@@ -8,6 +8,7 @@
import ca.bc.gov.app.dto.client.ClientValueTextDto;
import ca.bc.gov.app.dto.client.CodeNameDto;
import ca.bc.gov.app.exception.AddressLookupException;
+import io.micrometer.observation.annotation.Observed;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
@@ -22,6 +23,7 @@
@Service
@Slf4j
+@Observed
public class ClientAddressService {
private final ForestClientConfiguration.AddressCompleteConfiguration configuration;
diff --git a/backend/src/main/java/ca/bc/gov/app/service/client/ClientLegacyService.java b/backend/src/main/java/ca/bc/gov/app/service/client/ClientLegacyService.java
index da702a38f8..439a6dc811 100644
--- a/backend/src/main/java/ca/bc/gov/app/service/client/ClientLegacyService.java
+++ b/backend/src/main/java/ca/bc/gov/app/service/client/ClientLegacyService.java
@@ -1,6 +1,7 @@
package ca.bc.gov.app.service.client;
import ca.bc.gov.app.dto.legacy.ForestClientDto;
+import io.micrometer.observation.annotation.Observed;
import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
@@ -12,6 +13,7 @@
@Slf4j
@Service
+@Observed
public class ClientLegacyService {
private final WebClient legacyApi;
diff --git a/backend/src/main/java/ca/bc/gov/app/service/client/ClientService.java b/backend/src/main/java/ca/bc/gov/app/service/client/ClientService.java
index 09392d082d..4218aee435 100644
--- a/backend/src/main/java/ca/bc/gov/app/service/client/ClientService.java
+++ b/backend/src/main/java/ca/bc/gov/app/service/client/ClientService.java
@@ -25,6 +25,8 @@
import ca.bc.gov.app.repository.client.ProvinceCodeRepository;
import ca.bc.gov.app.service.bcregistry.BcRegistryService;
import ca.bc.gov.app.service.ches.ChesService;
+import io.micrometer.observation.annotation.Observed;
+import io.micrometer.tracing.annotation.SpanTag;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
@@ -44,6 +46,7 @@
@Service
@RequiredArgsConstructor
@Slf4j
+@Observed
public class ClientService {
private final ClientTypeCodeRepository clientTypeCodeRepository;
@@ -65,7 +68,7 @@ public class ClientService {
* @return A list of {@link CodeNameDto}
*/
public Flux findActiveClientTypeCodes(LocalDate targetDate) {
-
+ log.info("Loading active client type codes from the client service.");
return
clientTypeCodeRepository
.findActiveAt(targetDate)
@@ -87,6 +90,7 @@ public Flux findActiveClientTypeCodes(LocalDate targetDate) {
* @return A list of {@link CodeNameDto} entries.
*/
public Flux listCountries(int page, int size) {
+ log.info("Requesting a list of countries from the client service.");
return countryCodeRepository
.findBy(PageRequest.of(page, size, Sort.by("order", "description")))
.map(entity -> new CodeNameDto(entity.getCountryCode(), entity.getDescription()));
@@ -105,6 +109,8 @@ public Flux listCountries(int page, int size) {
* @see CodeNameDto
*/
public Mono getCountryByCode(String countryCode) {
+ log.info("Loading country information for country code {} from the client service.",
+ countryCode);
return countryCodeRepository
.findByCountryCode(countryCode)
.map(entity -> new CodeNameDto(entity.getCountryCode(),
@@ -123,6 +129,8 @@ public Mono getCountryByCode(String countryCode) {
* @see CodeNameDto
*/
public Mono getClientTypeByCode(String code) {
+ log.info("Loading client type information for client type code {} from the client service.",
+ code);
return clientTypeCodeRepository
.findByCode(code)
.map(entity -> new CodeNameDto(entity.getCode(),
@@ -140,6 +148,7 @@ public Mono getClientTypeByCode(String code) {
* @return A list of {@link CodeNameDto} entries.
*/
public Flux listProvinces(String countryCode, int page, int size) {
+ log.info("Loading a list of provinces/states for country {} from the client service.",countryCode);
return provinceCodeRepository
.findByCountryCode(countryCode, PageRequest.of(page, size, Sort.by("description")))
.map(entity -> new CodeNameDto(entity.getProvinceCode(), entity.getDescription()));
@@ -153,7 +162,10 @@ public Flux listProvinces(String countryCode, int page, int size) {
* @param size The amount of entries per page.
* @return A list of {@link CodeNameDto} entries.
*/
- public Flux listClientContactTypeCodes(LocalDate activeDate, int page, int size) {
+
+ public Flux listClientContactTypeCodes(LocalDate activeDate,int page, int size) {
+ log.info("Loading a list of contact types from the client service.");
+
return contactTypeCodeRepository
.findActiveAt(activeDate, PageRequest.of(page, size))
.map(entity -> new CodeNameDto(
@@ -173,7 +185,7 @@ public Mono getClientDetails(
String userId,
String businessId
) {
- log.info("Loading details for {}", clientNumber);
+ log.info("Loading details for client {}", clientNumber);
return
bcRegistryService
.requestDocumentData(clientNumber)
@@ -248,6 +260,7 @@ public Mono getClientDetails(
* @throws InvalidAccessTokenException if the access token is invalid or expired
*/
public Flux findByClientNameOrIncorporation(String value) {
+ log.info("Searching for client by name or incorporation on bc registry {}", value);
return bcRegistryService
.searchByFacets(value)
.map(entry -> new ClientLookUpDto(
@@ -282,6 +295,8 @@ public Mono triggerEmailDuplicatedClient(
String userId,
String businessId
) {
+ log.info("Searching on Oracle legacy db for {} {}", emailRequestDto.incorporation(),
+ emailRequestDto.name());
return
legacyService
.searchLegacy(
@@ -291,6 +306,10 @@ public Mono triggerEmailDuplicatedClient(
businessId
)
.next()
+ .doOnNext(legacy ->
+ log.info("Found legacy entry for {} {}", emailRequestDto.incorporation(),
+ emailRequestDto.name())
+ )
.flatMap(
triggerEmailDuplicatedClient(emailRequestDto.email(), emailRequestDto.userName()))
.then();
@@ -456,7 +475,7 @@ private Predicate isMatchWith(BcRegistryDocumentDto document) {
private Function> triggerEmailDuplicatedClient(
String email, String userName) {
-
+ log.info("Sending matched email using CHES Client number application can’t go ahead");
return legacy -> chesService.sendEmail(
"matched",
email,
@@ -467,6 +486,7 @@ private Function> triggerEmailDuplicatedC
}
private Mono triggerEmail(EmailRequestDto emailRequestDto) {
+ log.info("Sending {} email using CHES {}", emailRequestDto.templateName(),emailRequestDto.subject());
return chesService.sendEmail(
emailRequestDto.templateName(),
emailRequestDto.email(),
diff --git a/backend/src/main/java/ca/bc/gov/app/service/client/ClientSubmissionService.java b/backend/src/main/java/ca/bc/gov/app/service/client/ClientSubmissionService.java
index e6167a70f6..d1ee784f53 100644
--- a/backend/src/main/java/ca/bc/gov/app/service/client/ClientSubmissionService.java
+++ b/backend/src/main/java/ca/bc/gov/app/service/client/ClientSubmissionService.java
@@ -33,6 +33,7 @@
import ca.bc.gov.app.repository.client.SubmissionMatchDetailRepository;
import ca.bc.gov.app.repository.client.SubmissionRepository;
import ca.bc.gov.app.service.ches.ChesService;
+import io.micrometer.observation.annotation.Observed;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -58,6 +59,7 @@
@Service
@RequiredArgsConstructor
@Slf4j
+@Observed
public class ClientSubmissionService {
private final SubmissionRepository submissionRepository;
@@ -95,7 +97,7 @@ public Flux listSubmissions(
.flatMapMany(clientTypes ->
loadSubmissions(page, size, requestType, requestStatus, updatedAt)
.flatMap(submission ->
- loadSubmissionDetail(clientType, name, submission)
+ loadSubmissionDetail(clientType, name, submission.getSubmissionId())
.map(submissionDetail ->
new ClientListSubmissionDto(
submission.getSubmissionId(),
@@ -144,17 +146,23 @@ public Mono submit(
.updatedBy(userName)
.build()
)
+ .doOnNext(submission -> log.info("Submission ready to be saved: {}", submission))
//Save submission to begin with
.flatMap(submissionRepository::save)
+ .doOnNext(submission -> log.info("Submission saved: {}", submission))
//Save the submission detail
.map(submission -> mapToSubmissionDetailEntity(submission.getSubmissionId(),
clientSubmissionDto.businessInformation())
)
+ .doOnNext(submissionDetail -> log.info("Submission detail ready to be saved: {}",
+ submissionDetail))
.flatMap(submissionDetailRepository::save)
+ .doOnNext(submissionDetail -> log.info("Submission detail saved: {}", submissionDetail))
//Save the locationNames and contacts and do the association
.flatMap(submission ->
//Save all locationNames
saveAddresses(clientSubmissionDto, submission)
+ .doOnNext(locations -> log.info("Locations saved: {}", locations))
//For each contact, save it,
// then find the associated location and save the association
.flatMapMany(locations ->
@@ -176,6 +184,8 @@ public Mono submit(
)
//Then grab all back as a list, to make all reactive flows complete
.collectList()
+ .doOnNext(submissionLocationContacts ->
+ log.info("Location contacts saved: {}", submissionLocationContacts))
//Return what we need only
.thenReturn(submission.getSubmissionId())
)
@@ -255,16 +265,19 @@ public Mono getSubmissionDetail(Long id) {
.all();
return detailsBusiness
+ .doOnNext(submissionDetailsDto -> log.info("Loaded submission details for id {}", id))
.flatMap(submissionDetailsDto ->
contacts
.collectList()
.map(submissionDetailsDto::withContact)
)
+ .doOnNext(submissionDetailsDto -> log.info("Loaded submission contacts for id {}", id))
.flatMap(submissionDetailsDto ->
addresses
.collectList()
.map(submissionDetailsDto::withAddress)
)
+ .doOnNext(submissionDetailsDto -> log.info("Loaded submission addresses for id {}", id))
.flatMap(submissionDetailsDto ->
submissionMatchDetailRepository
.findBySubmissionId(id.intValue())
@@ -273,6 +286,7 @@ public Mono getSubmissionDetail(Long id) {
.withApprovedTimestamp(matched.getUpdatedAt())
.withMatchers(matched.getMatchers())
)
+ .doOnNext(match -> log.info("Loaded submission match for id {}", id))
.defaultIfEmpty(
submissionDetailsDto
.withMatchers(Map.of())
@@ -289,6 +303,7 @@ public Mono approveOrReject(
String userName,
SubmissionApproveRejectDto request
) {
+ log.info("Request {} is being {}", id, request.approved() ? "approved" : "rejected");
return
submissionRepository
.findById(id.intValue())
@@ -301,6 +316,8 @@ public Mono approveOrReject(
return submission;
})
.flatMap(submissionRepository::save)
+ .doOnNext(submission -> log.info("Submission {} is now {}", id,
+ submission.getSubmissionStatus()))
.flatMap(submission ->
submissionMatchDetailRepository
.findBySubmissionId(id.intValue())
@@ -310,6 +327,7 @@ public Mono approveOrReject(
.withUpdatedAt(LocalDateTime.now())
.withMatchingMessage(processRejectionReason(request))
)
+ .doOnNext(matched -> log.info("Match for submission {} is now being saved {}", id, matched.getStatus()))
.flatMap(submissionMatchDetailRepository::save)
)
.then();
@@ -322,6 +340,8 @@ private Mono saveAndAssociateContact(
String userId
) {
+ log.info("Saving contact {} for submission {}", contact.lastName(), submissionId);
+
return
Mono
.just(mapToSubmissionContactEntity(contact))
@@ -335,19 +355,26 @@ private Mono saveAndAssociateContact(
.submissionContactId(contactEntity.getSubmissionContactId())
.build()
)
- .flatMap(submissionLocationContactRepository::save);
+ .flatMap(submissionLocationContactRepository::save)
+ .doOnNext(submissionLocationContactEntity ->
+ log.info("Contact {} saved for submission {}", contact.lastName(), submissionId)
+ );
}
private Mono> saveAddresses(
ClientSubmissionDto clientSubmissionDto,
SubmissionDetailEntity submission) {
+ log.info("Saving location for submission {}", submission.getSubmissionId());
return submissionLocationRepository
.saveAll(
mapAllToSubmissionLocationEntity(
submission.getSubmissionId(),
clientSubmissionDto.location().addresses())
)
- .collectList();
+ .collectList()
+ .doOnNext(submissionLocationEntities ->
+ log.info("Location saved for submission {}", submission.getSubmissionId())
+ );
}
private Mono sendEmail(
@@ -356,6 +383,7 @@ private Mono sendEmail(
String email,
String userName
) {
+ log.info("Sending email to {} for submission {}", email, submissionId);
return chesService.sendEmail(
"registration",
email,
@@ -367,6 +395,7 @@ private Mono sendEmail(
private Mono