diff --git a/build.sbt b/build.sbt index 7fb42fa0ed..2bad077cef 100755 --- a/build.sbt +++ b/build.sbt @@ -51,7 +51,6 @@ val munitVersion = "1.0.0-M10" val nimbusJoseJwtVersion = "9.37.1" val postgresJdbcVersion = "42.6.0" val pureconfigVersion = "0.17.4" -val scalaLoggingVersion = "3.9.5" val scalaTestVersion = "3.2.17" val scalaXmlVersion = "2.2.0" val topBraidVersion = "1.3.2" // 1.4.1 fails to validate some test schemas @@ -115,7 +114,7 @@ lazy val munit = "org.scalameta" %% "munit" lazy val nimbusJoseJwt = "com.nimbusds" % "nimbus-jose-jwt" % nimbusJoseJwtVersion lazy val pureconfig = "com.github.pureconfig" %% "pureconfig" % pureconfigVersion lazy val pureconfigCats = "com.github.pureconfig" %% "pureconfig-cats" % pureconfigVersion -lazy val scalaLogging = "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion +lazy val scalaReflect = "org.scala-lang" % "scala-reflect" % scalaCompilerVersion lazy val scalaTest = "org.scalatest" %% "scalatest" % scalaTestVersion lazy val scalaXml = "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion lazy val topBraidShacl = "org.topbraid" % "shacl" % topBraidVersion @@ -214,7 +213,6 @@ lazy val kernel = project log4cats, pureconfig, pureconfigCats, - scalaLogging, munit % Test, scalaTest % Test ), @@ -289,6 +287,7 @@ lazy val rdf = project jenaArq, jsonldjava, magnolia, + scalaReflect, topBraidShacl, akkaSlf4j % Test, akkaTestKit % Test, @@ -762,7 +761,6 @@ lazy val storage = project circeGenericExtras, logback, pureconfig, - scalaLogging, akkaHttpTestKit % Test, akkaTestKit % Test, mockito % Test, @@ -796,7 +794,6 @@ lazy val tests = project circeGenericExtras, fs2, logback, - scalaLogging, akkaTestKit % Test, akkaHttpTestKit % Test, awsSdk % Test, diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugin/PluginsLoader.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugin/PluginsLoader.scala index de59fa4700..0fc9465af1 100755 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugin/PluginsLoader.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugin/PluginsLoader.scala @@ -3,11 +3,11 @@ package ch.epfl.bluebrain.nexus.delta.plugin import cats.data.NonEmptyList import cats.effect.IO import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.plugin.PluginsLoader.PluginLoaderConfig import ch.epfl.bluebrain.nexus.delta.sdk.error.PluginError import ch.epfl.bluebrain.nexus.delta.sdk.error.PluginError.{ClassNotFoundError, MultiplePluginDefClassesFound, PluginLoadErrors} import ch.epfl.bluebrain.nexus.delta.sdk.plugin.PluginDef -import com.typesafe.scalalogging.Logger import io.github.classgraph.ClassGraph import java.io.{File, FilenameFilter} @@ -24,7 +24,7 @@ import scala.jdk.CollectionConverters._ * [[PluginsLoader]] configuration */ class PluginsLoader(loaderConfig: PluginLoaderConfig) { - private val logger: Logger = Logger[PluginsLoader] + private val logger = Logger[PluginsLoader] private val parentClassLoader = this.getClass.getClassLoader @@ -98,8 +98,7 @@ class PluginsLoader(loaderConfig: PluginLoaderConfig) { value => IO.pure(value) ) case Nil => - logger.warn(s"Jar file '$jar' does not contain a 'PluginDef' implementation.") - IO.none + logger.warn(s"Jar file '$jar' does not contain a 'PluginDef' implementation.").as(None) case multiple => IO.raiseError(MultiplePluginDefClassesFound(jar, multiple.toSet)) diff --git a/delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/RetryStrategy.scala b/delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/RetryStrategy.scala index 61b6026bbe..a2c55555ee 100644 --- a/delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/RetryStrategy.scala +++ b/delta/kernel/src/main/scala/ch/epfl/bluebrain/nexus/delta/kernel/RetryStrategy.scala @@ -1,7 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.kernel import cats.effect.{IO, Timer} -import com.typesafe.scalalogging.{Logger => ScalaLoggingLogger} import org.typelevel.log4cats.Logger import pureconfig.ConfigReader import pureconfig.error.{CannotConvert, ConfigReaderFailures, ConvertFailure} @@ -51,18 +50,6 @@ object RetryStrategy { } ) - /** - * Log errors when retrying - */ - def logError[E](logger: ScalaLoggingLogger, action: String): (E, RetryDetails) => IO[Unit] = { - case (err, WillDelayAndRetry(nextDelay, retriesSoFar, _)) => - val message = s"""Error $err while $action: retrying in ${nextDelay.toMillis}ms (retries so far: $retriesSoFar)""" - IO.delay(logger.warn(message)) - case (err, GivingUp(totalRetries, _)) => - val message = s"""Error $err while $action, giving up (total retries: $totalRetries)""" - IO.delay(logger.error(message)) - } - /** * Log errors when retrying */ @@ -106,27 +93,6 @@ object RetryStrategy { onError ) - /** - * Retry strategy which retries on all non fatal errors and just outputs a log when an error occurs - * - * @param config - * the retry configuration - * @param logger - * the logger to use - * @param action - * the action that was performed - */ - def retryOnNonFatal( - config: RetryStrategyConfig, - logger: ScalaLoggingLogger, - action: String - ): RetryStrategy[Throwable] = - RetryStrategy( - config, - (t: Throwable) => NonFatal(t), - (t: Throwable, d: RetryDetails) => logError(logger, action)(t, d) - ) - def retryOnNonFatal( config: RetryStrategyConfig, logger: Logger[IO], diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/BlazegraphSink.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/BlazegraphSink.scala index b23198692b..7b04a37b20 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/BlazegraphSink.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/BlazegraphSink.scala @@ -1,6 +1,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.indexing import cats.effect.IO +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.kernel.kamon.KamonMetricComponent import ch.epfl.bluebrain.nexus.delta.kernel.syntax.kamonSyntax import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.BlazegraphViews @@ -14,7 +15,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.model.BaseUri import ch.epfl.bluebrain.nexus.delta.sourcing.config.BatchConfig import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Elem import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Operation.Sink -import com.typesafe.scalalogging.Logger import fs2.Chunk import shapeless.Typeable @@ -62,8 +62,8 @@ final class BlazegraphSink( .bulk(namespace, bulk.queries) .redeemWith( err => - IO - .delay(logger.error(s"Indexing in blazegraph namespace $namespace failed", err)) + logger + .error(err)(s"Indexing in blazegraph namespace $namespace failed") .as(elements.map { _.failed(err) }), _ => IO.pure(markInvalidIdsAsFailed(elements, bulk.invalidIds)) ) @@ -83,7 +83,7 @@ final class BlazegraphSink( object BlazegraphSink { - private val logger: Logger = Logger[BlazegraphSink] + private val logger = Logger[BlazegraphSink] def apply(client: BlazegraphClient, batchConfig: BatchConfig, namespace: String)(implicit base: BaseUri) = new BlazegraphSink(client, batchConfig.maxElements, batchConfig.maxInterval, namespace = namespace) diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/IndexingViewDef.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/IndexingViewDef.scala index 6ee29468f2..5c504428ce 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/IndexingViewDef.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/IndexingViewDef.scala @@ -3,6 +3,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.indexing import cats.data.NonEmptyChain import cats.effect.{ContextShift, IO, Timer} import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.BlazegraphViews import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.model.BlazegraphViewState import ch.epfl.bluebrain.nexus.delta.sdk.stream.GraphResourceStream @@ -13,7 +14,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.query.SelectFilter import ch.epfl.bluebrain.nexus.delta.sourcing.state.GraphResource import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Operation.Sink import ch.epfl.bluebrain.nexus.delta.sourcing.stream._ -import com.typesafe.scalalogging.Logger /** * Definition of a Blazegraph view to build a projection @@ -26,7 +26,7 @@ sealed trait IndexingViewDef extends Product with Serializable { object IndexingViewDef { - private val logger: Logger = Logger[IndexingViewDef] + private val logger = Logger[IndexingViewDef] /** * Active view eligible to be run as a projection by the supervisor @@ -118,7 +118,7 @@ object IndexingViewDef { } yield projection IO.fromEither(compiled).onError { e => - IO.delay(logger.error(s"View '${v.ref}' could not be compiled.", e)) + logger.error(e)(s"View '${v.ref}' could not be compiled.") } } } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala index 186301b8b1..4085adba22 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/client/DeltaClient.scala @@ -9,6 +9,7 @@ import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes} import akka.stream.alpakka.sse.scaladsl.EventSource import cats.effect.{ContextShift, IO} import cats.implicits.{catsSyntaxApplicativeError, catsSyntaxFlatMapOps} +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model.CompositeViewSource.RemoteProjectSource import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.stream.CompositeBranch import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri @@ -24,7 +25,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.ElemStream import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset.Start import ch.epfl.bluebrain.nexus.delta.sourcing.stream.{Elem, RemainingElems} -import com.typesafe.scalalogging.Logger import io.circe.parser.decode import fs2._ @@ -74,7 +74,7 @@ trait DeltaClient { object DeltaClient { - private val logger: Logger = Logger[DeltaClient.type] + private val logger = Logger[DeltaClient.type] private val accept = Accept(`application/json`.mediaType, RdfMediaTypes.`application/ld+json`) @@ -144,8 +144,8 @@ object DeltaClient { decode[Elem[Unit]](sse.data) match { case Right(elem) => Stream.emit(elem) case Left(err) => - logger.error(s"Failed to decode sse event '$sse'", err) - Stream.empty + Stream.eval(logger.error(err)(s"Failed to decode sse event '$sse'")) >> + Stream.empty } } } diff --git a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/client/ElasticSearchClient.scala b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/client/ElasticSearchClient.scala index f666096fb0..74a3bc80ff 100644 --- a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/client/ElasticSearchClient.scala +++ b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/client/ElasticSearchClient.scala @@ -8,10 +8,10 @@ import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers.BasicHttpCredentials import cats.effect.{ContextShift, IO, Timer} import cats.syntax.all._ -import ch.epfl.bluebrain.nexus.delta.kernel.RetryStrategy import ch.epfl.bluebrain.nexus.delta.kernel.RetryStrategy.logError import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination import ch.epfl.bluebrain.nexus.delta.kernel.utils.UrlUtils +import ch.epfl.bluebrain.nexus.delta.kernel.{Logger, RetryStrategy} import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.client.ElasticSearchClient.BulkResponse.MixedOutcomes.Outcome import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.client.ElasticSearchClient._ import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.{EmptyResults, ResourcesSearchParams} @@ -25,7 +25,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults.{ScoredSearc import ch.epfl.bluebrain.nexus.delta.sdk.model.search.{AggregationResult, ResultEntry, SearchResults, SortList} import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, Name} import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ -import com.typesafe.scalalogging.Logger import io.circe._ import io.circe.syntax._ @@ -43,7 +42,7 @@ class ElasticSearchClient(client: HttpClient, endpoint: Uri, maxIndexPathLength: cs: ContextShift[IO] ) { import as.dispatcher - private val logger: Logger = Logger[ElasticSearchClient] + private val logger = Logger[ElasticSearchClient] private val serviceName = Name.unsafe("elasticsearch") private val scriptPath = "_scripts" private val docPath = "_doc" diff --git a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/IndexingViewDef.scala b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/IndexingViewDef.scala index 05957ec8ac..d044d45f95 100644 --- a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/IndexingViewDef.scala +++ b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/IndexingViewDef.scala @@ -3,6 +3,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.indexing import cats.data.NonEmptyChain import cats.effect.{ContextShift, IO, Timer} import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.ElasticSearchViews import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.client.IndexLabel import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.{contexts, DefaultMapping, DefaultSettings, ElasticSearchViewState} @@ -16,7 +17,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.query.SelectFilter import ch.epfl.bluebrain.nexus.delta.sourcing.state.GraphResource import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Operation.Sink import ch.epfl.bluebrain.nexus.delta.sourcing.stream._ -import com.typesafe.scalalogging.Logger import io.circe.JsonObject /** @@ -32,7 +32,7 @@ sealed trait IndexingViewDef extends Product with Serializable { object IndexingViewDef { - private val logger: Logger = Logger[IndexingViewDef] + private val logger = Logger[IndexingViewDef] private val defaultContext = ContextValue(contexts.elasticsearchIndexing, contexts.indexingMetadata) @@ -132,7 +132,7 @@ object IndexingViewDef { } yield projection IO.fromEither(compiled).onError { e => - IO.delay(logger.error(s"View '${v.ref}' could not be compiled.", e)) + logger.error(e)(s"View '${v.ref}' could not be compiled.") } } } diff --git a/delta/plugins/jira/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/jira/JiraClient.scala b/delta/plugins/jira/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/jira/JiraClient.scala index 291fbfa1ea..76353f5beb 100644 --- a/delta/plugins/jira/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/jira/JiraClient.scala +++ b/delta/plugins/jira/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/jira/JiraClient.scala @@ -3,6 +3,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.jira import akka.http.scaladsl.model.Uri import cats.effect.IO import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.plugins.jira.JiraError.{AccessTokenExpected, NoTokenError, RequestTokenExpected} import ch.epfl.bluebrain.nexus.delta.plugins.jira.OAuthToken.{AccessToken, RequestToken} import ch.epfl.bluebrain.nexus.delta.plugins.jira.config.JiraConfig @@ -12,7 +13,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.User import com.google.api.client.auth.oauth.{OAuthAuthorizeTemporaryTokenUrl, OAuthGetAccessToken, OAuthGetTemporaryToken, OAuthRsaSigner} import com.google.api.client.http.javanet.NetHttpTransport import com.google.api.client.http.{ByteArrayContent, GenericUrl} -import com.typesafe.scalalogging.Logger import io.circe.JsonObject import io.circe.syntax.EncoderOps import org.apache.commons.codec.binary.Base64 @@ -76,7 +76,7 @@ trait JiraClient { object JiraClient { - private val logger: Logger = Logger[JiraClient] + private val logger = Logger[JiraClient] private val accessTokenUrl = Uri.Path("/plugins/servlet/oauth/access-token") private val authorizationUrl = Uri.Path("/plugins/servlet/oauth/authorize") private val requestTokenUrl = Uri.Path("/plugins/servlet/oauth/request-token") @@ -117,49 +117,49 @@ object JiraClient { private val netHttpTransport = new NetHttpTransport() - override def requestToken()(implicit caller: User): IO[AuthenticationRequest] = - IO { - val tempToken = new JiraOAuthGetTemporaryToken(jiraConfig.base) - tempToken.consumerKey = jiraConfig.consumerKey - tempToken.signer = signer - tempToken.transport = netHttpTransport - tempToken.callback = "oob" - val response = tempToken.execute() - logger.debug(s"Request Token value: ${response.token}") - response.token + override def requestToken()(implicit caller: User): IO[AuthenticationRequest] = { + for { + token <- IO { + val tempToken = new JiraOAuthGetTemporaryToken(jiraConfig.base) + tempToken.consumerKey = jiraConfig.consumerKey + tempToken.signer = signer + tempToken.transport = netHttpTransport + tempToken.callback = "oob" + val response = tempToken.execute() + + response.token + } + _ <- logger.debug(s"Request Token value: $token") + _ <- store.save(caller, RequestToken(token)) + } yield { + val authorizationURL = + new OAuthAuthorizeTemporaryTokenUrl((jiraConfig.base / authorizationUrl).toString()) + authorizationURL.temporaryToken = token + AuthenticationRequest(Uri(authorizationURL.toString)) } - .flatMap { token => - store.save(caller, RequestToken(token)).as { - val authorizationURL = - new OAuthAuthorizeTemporaryTokenUrl((jiraConfig.base / authorizationUrl).toString()) - authorizationURL.temporaryToken = token - AuthenticationRequest(Uri(authorizationURL.toString)) - } - } - .adaptError { e => JiraError.from(e) } - - override def accessToken(verifier: Verifier)(implicit caller: User): IO[Unit] = - store - .get(caller) - .flatMap { - case None => IO.raiseError(NoTokenError) - case Some(_: AccessToken) => IO.raiseError(RequestTokenExpected) - case Some(RequestToken(value)) => - IO { - val accessToken = new JiraOAuthGetAccessToken(jiraConfig.base) - accessToken.consumerKey = jiraConfig.consumerKey - accessToken.signer = signer - accessToken.transport = netHttpTransport - accessToken.verifier = verifier.value - accessToken.temporaryToken = value - accessToken.execute().token - } - .flatMap { token => - logger.debug("Access Token:" + token) - store.save(caller, AccessToken(token)) - } - } - .adaptError { e => JiraError.from(e) } + }.adaptError { e => JiraError.from(e) } + + override def accessToken(verifier: Verifier)(implicit caller: User): IO[Unit] = { + for { + tokenOpt <- store.get(caller) + token <- tokenOpt match { + case None => IO.raiseError(NoTokenError) + case Some(_: AccessToken) => IO.raiseError(RequestTokenExpected) + case Some(RequestToken(value)) => + IO { + val accessToken = new JiraOAuthGetAccessToken(jiraConfig.base) + accessToken.consumerKey = jiraConfig.consumerKey + accessToken.signer = signer + accessToken.transport = netHttpTransport + accessToken.verifier = verifier.value + accessToken.temporaryToken = value + accessToken.execute().token + } + } + _ <- store.save(caller, AccessToken(token)) + _ <- logger.debug("Access Token:" + token) + } yield () + }.adaptError { e => JiraError.from(e) } override def createIssue(payload: JsonObject)(implicit caller: User): IO[JiraResponse] = requestFactory(caller).flatMap { factory => diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileRejection.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileRejection.scala index 1763ee67fb..2c6a60f187 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileRejection.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileRejection.scala @@ -20,7 +20,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext import ch.epfl.bluebrain.nexus.delta.sdk.syntax.httpResponseFieldsSyntax import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import ch.epfl.bluebrain.nexus.delta.sourcing.model.Tag.UserTag -import com.typesafe.scalalogging.Logger import io.circe.syntax._ import io.circe.{Encoder, JsonObject} @@ -34,8 +33,6 @@ sealed abstract class FileRejection(val reason: String, val loggedDetails: Optio object FileRejection { - private val logger: Logger = Logger[FileRejection] - /** * Rejection returned when a subject intends to retrieve a file at a specific revision, but the provided revision * does not exist. @@ -251,7 +248,6 @@ object FileRejection { Encoder.AsObject.instance { r => val tpe = ClassUtils.simpleName(r) val obj = JsonObject(keywords.tpe -> tpe.asJson, "reason" -> r.reason.asJson) - r.loggedDetails.foreach(loggedDetails => logger.error(s"${r.reason}. Details '$loggedDetails'")) r match { case WrappedAkkaRejection(rejection) => rejection.asJsonObject case WrappedStorageRejection(rejection) => rejection.asJsonObject diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala index 523ef630b6..0858b82946 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageRejection.scala @@ -17,7 +17,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.permissions.model.Permission import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext.ContextRejection import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import ch.epfl.bluebrain.nexus.delta.sourcing.model.Tag.UserTag -import com.typesafe.scalalogging.Logger import io.circe.syntax._ import io.circe.{Encoder, JsonObject} @@ -200,8 +199,6 @@ object StorageRejection { final case class ProjectContextRejection(rejection: ContextRejection) extends StorageFetchRejection("Something went wrong while interacting with another module.") - private val logger: Logger = Logger("StorageRejection") - implicit val storageJsonLdRejectionMapper: Mapper[JsonLdRejection, StorageRejection] = { case UnexpectedId(id, payloadIri) => UnexpectedStorageId(id, payloadIri) case JsonLdRejection.InvalidJsonLdFormat(id, rdfError) => InvalidJsonLdFormat(id, rdfError) @@ -213,7 +210,6 @@ object StorageRejection { Encoder.AsObject.instance { r => val tpe = ClassUtils.simpleName(r) val obj = JsonObject(keywords.tpe -> tpe.asJson, "reason" -> r.reason.asJson) - r.loggedDetails.foreach(logger.error(_)) r match { case StorageNotAccessible(_, details) => obj.add("details", details.asJson) case ProjectContextRejection(rejection) => rejection.asJsonObject diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/deletion/ProjectDeletionCoordinator.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/deletion/ProjectDeletionCoordinator.scala index 472bb6b544..4b7b567b72 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/deletion/ProjectDeletionCoordinator.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/deletion/ProjectDeletionCoordinator.scala @@ -2,7 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.sdk.deletion import cats.effect.{Clock, IO, Timer} import cats.syntax.all._ -import ch.epfl.bluebrain.nexus.delta.kernel.RetryStrategy +import ch.epfl.bluebrain.nexus.delta.kernel.{Logger, RetryStrategy} import ch.epfl.bluebrain.nexus.delta.kernel.utils.IOInstant import ch.epfl.bluebrain.nexus.delta.sdk.deletion.model.ProjectDeletionReport import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.ServiceAccount @@ -15,7 +15,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ElemStream, ProjectRef} import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset import ch.epfl.bluebrain.nexus.delta.sourcing.stream._ -import com.typesafe.scalalogging.Logger import fs2.Stream /** @@ -25,7 +24,7 @@ sealed trait ProjectDeletionCoordinator object ProjectDeletionCoordinator { - private val logger: Logger = Logger[ProjectDeletionCoordinator] + private val logger = Logger[ProjectDeletionCoordinator] /** * If deletion is disabled, we do nothing @@ -63,7 +62,7 @@ object ProjectDeletionCoordinator { private[deletion] def delete(project: ProjectState): IO[Unit] = for { - _ <- IO.delay(logger.warn(s"Starting deletion of project ${project.project}")) + _ <- logger.warn(s"Starting deletion of project ${project.project}") now <- IOInstant.now // Running preliminary tasks before deletion like deprecating and stopping views, // removing acl related to the project, etc... @@ -76,7 +75,7 @@ object ProjectDeletionCoordinator { _ <- IO.sleep(deletionConfig.propagationDelay) // Delete the events and states and save the deletion report _ <- deletionStore.deleteAndSaveReport(report) - _ <- IO.delay(logger.info(s"Project ${project.project} has been successfully deleted.")) + _ <- logger.info(s"Project ${project.project} has been successfully deleted.") } yield () private[deletion] def list(project: ProjectRef): IO[List[ProjectDeletionReport]] = @@ -118,7 +117,7 @@ object ProjectDeletionCoordinator { )(implicit clock: Clock[IO], timer: Timer[IO]): IO[ProjectDeletionCoordinator] = { val stream = apply(projects, deletionTasks, deletionConfig, serviceAccount, xas) stream match { - case Noop => IO.delay(logger.info("Projection deletion is disabled.")).as(Noop) + case Noop => logger.info("Projection deletion is disabled.").as(Noop) case active: Active => val metadata: ProjectionMetadata = ProjectionMetadata("system", "project-deletion", None, None) supervisor diff --git a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/PurgeElemFailures.scala b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/PurgeElemFailures.scala index a746d7d736..a89de312ff 100644 --- a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/PurgeElemFailures.scala +++ b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/PurgeElemFailures.scala @@ -1,11 +1,11 @@ package ch.epfl.bluebrain.nexus.delta.sourcing import cats.effect.{Clock, IO, Timer} +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.kernel.utils.IOInstant import ch.epfl.bluebrain.nexus.delta.sourcing.PurgeElemFailures.logger import ch.epfl.bluebrain.nexus.delta.sourcing.config.ProjectionConfig import ch.epfl.bluebrain.nexus.delta.sourcing.stream.{CompiledProjection, ExecutionStrategy, ProjectionMetadata, Supervisor} -import com.typesafe.scalalogging.Logger import doobie.implicits._ import doobie.postgres.implicits._ import fs2.Stream @@ -24,7 +24,7 @@ final class PurgeElemFailures private[sourcing] (xas: Transactors, ttl: FiniteDu | DELETE FROM public.failed_elem_logs | WHERE instant < $threshold """.stripMargin.update.run.transact(xas.write) - _ <- IO.whenA(deleted > 0)(IO.delay(logger.info(s"Deleted {} old indexing failures.", deleted))) + _ <- IO.whenA(deleted > 0)(logger.info(s"Deleted $deleted old indexing failures.")) } yield () } diff --git a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/projections/ProjectionRestartStore.scala b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/projections/ProjectionRestartStore.scala index 3ee2731656..2a5904fd55 100644 --- a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/projections/ProjectionRestartStore.scala +++ b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/projections/ProjectionRestartStore.scala @@ -2,6 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.sourcing.projections import cats.effect.{IO, Timer} import cats.implicits.toFlatMapOps +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors import ch.epfl.bluebrain.nexus.delta.sourcing.config.QueryConfig import ch.epfl.bluebrain.nexus.delta.sourcing.model.ElemStream @@ -12,7 +13,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.projections.model.ProjectionRestar import ch.epfl.bluebrain.nexus.delta.sourcing.projections.model.ProjectionRestart.{entityType, restartId} import ch.epfl.bluebrain.nexus.delta.sourcing.query.StreamingQuery import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Elem -import com.typesafe.scalalogging.Logger import doobie.implicits._ import doobie.postgres.implicits._ import io.circe.Json @@ -43,7 +43,7 @@ final class ProjectionRestartStore(xas: Transactors, config: QueryConfig)(implic sql"""DELETE FROM public.projection_restarts WHERE instant < $instant""".update.run .transact(xas.write) .flatTap { deleted => - IO.whenA(deleted > 0)(IO.delay(logger.info(s"Deleted $deleted projection restarts."))) + IO.whenA(deleted > 0)(logger.info(s"Deleted $deleted projection restarts.")) } .void @@ -66,6 +66,6 @@ final class ProjectionRestartStore(xas: Transactors, config: QueryConfig)(implic object ProjectionRestartStore { - private val logger: Logger = Logger[ProjectionRestartStore] + private val logger = Logger[ProjectionRestartStore] } diff --git a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/query/StreamingQuery.scala b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/query/StreamingQuery.scala index 853bddb465..44054a2b95 100644 --- a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/query/StreamingQuery.scala +++ b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/query/StreamingQuery.scala @@ -1,7 +1,8 @@ package ch.epfl.bluebrain.nexus.delta.sourcing.query import cats.effect.{ExitCase, IO, Timer} -import cats.implicits.{catsSyntaxApplicativeError, catsSyntaxFlatMapOps} +import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.sourcing.{Scope, Transactors} import ch.epfl.bluebrain.nexus.delta.sourcing.config.QueryConfig @@ -10,7 +11,6 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.{EntityType, Label, ProjectR import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Elem.{DroppedElem, SuccessElem} import ch.epfl.bluebrain.nexus.delta.sourcing.stream.{Elem, RemainingElems} -import com.typesafe.scalalogging.Logger import doobie.Fragments import doobie.implicits._ import doobie.postgres.implicits._ @@ -27,7 +27,7 @@ import scala.collection.mutable.ListBuffer */ object StreamingQuery { - private val logger: Logger = Logger[StreamingQuery.type] + private val logger = Logger[StreamingQuery.type] private val newState = "newState" @@ -163,11 +163,8 @@ object StreamingQuery { .evalMapChunk { e => e.evalMap { value => decodeValue(e.tpe, value).onError { err => - IO.delay( - logger.error( - s"An error occurred while decoding value with id '${e.id}' of type '${e.tpe}' in '$project'.", - err - ) + logger.error(err)( + s"An error occurred while decoding value with id '${e.id}' of type '${e.tpe}' in '$project'." ) } } @@ -263,17 +260,13 @@ object StreamingQuery { Chunk.buffer(buffer) } - private def logQuery[A, E](query: Query0[A]): ExitCase[E] => IO[Unit] = { - case ExitCase.Completed => - IO.delay( - logger.debug("Reached the end of the single evaluation of query '{}'.", query.sql) - ) - case ExitCase.Error(e) => - IO.delay(logger.error(s"Single evaluation of query '${query.sql}' failed.", e)) - case ExitCase.Canceled => - IO.delay( - logger.debug("Reached the end of the single evaluation of query '{}'.", query.sql) - ) + private def logQuery[A, E <: Throwable](query: Query0[A]): ExitCase[E] => IO[Unit] = { + case ExitCase.Completed => + logger.debug(s"Reached the end of the single evaluation of query '${query.sql}'.") + case ExitCase.Error(cause) => + logger.error(cause)(s"Single evaluation of query '${query.sql}' failed.") + case ExitCase.Canceled => + logger.debug(s"Reached the end of the single evaluation of query '${query.sql}'.") } private def stateFilter(projectRef: ProjectRef, offset: Offset, selectFilter: SelectFilter) = { diff --git a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/stream/Operation.scala b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/stream/Operation.scala index 25b49cf8db..492140e41f 100644 --- a/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/stream/Operation.scala +++ b/delta/sourcing-psql/src/main/scala/ch/epfl/bluebrain/nexus/delta/sourcing/stream/Operation.scala @@ -3,11 +3,11 @@ package ch.epfl.bluebrain.nexus.delta.sourcing.stream import cats.data.NonEmptyChain import cats.effect.{ContextShift, IO, Timer} import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.sourcing.model.ElemPipe import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Elem.{DroppedElem, FailedElem, SuccessElem} import ch.epfl.bluebrain.nexus.delta.sourcing.stream.ProjectionErr.{LeapingNotAllowedErr, OperationInOutMatchErr} -import com.typesafe.scalalogging.Logger import fs2.{Chunk, Pipe, Pull, Stream} import shapeless.Typeable @@ -205,7 +205,7 @@ object Operation { acc.andThen(e) } - private[stream] val logger: Logger = Logger[Operation] + private[stream] val logger = Logger[Operation] /** * Pipes represent individual steps in a [[Projection]] where [[SuccessElem]] values are processed to produce other @@ -261,10 +261,8 @@ object Operation { .eval( apply(value) .handleErrorWith { err => - IO - .delay( - logger.error(s"Error while applying pipe $name on element ${value.id}", err) - ) + logger + .error(err)(s"Error while applying pipe $name on element ${value.id}") .as(value.failed(err)) } ) diff --git a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/StringProcessLogger.scala b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/StringProcessLogger.scala index 75ca7f3368..272f87df2c 100644 --- a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/StringProcessLogger.scala +++ b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/StringProcessLogger.scala @@ -1,6 +1,6 @@ package ch.epfl.bluebrain.nexus.storage -import com.typesafe.scalalogging.Logger +import org.slf4j.LoggerFactory import scala.sys.process.ProcessLogger @@ -16,7 +16,7 @@ import scala.sys.process.ProcessLogger */ class StringProcessLogger(cmd: Seq[String], arg: Option[String]) extends ProcessLogger { - private val logger = Logger(cmd.mkString(" ")) + private val logger = LoggerFactory.getLogger(cmd.mkString(" ")) private val builder = new StringBuilder diff --git a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/attributes/AttributesCache.scala b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/attributes/AttributesCache.scala index dd144f9483..436f130d73 100644 --- a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/attributes/AttributesCache.scala +++ b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/attributes/AttributesCache.scala @@ -1,19 +1,18 @@ package ch.epfl.bluebrain.nexus.storage.attributes -import java.nio.file.Path -import java.time.Clock - import akka.actor.{ActorRef, ActorSystem} import akka.pattern.{ask, AskTimeoutException} import akka.util.Timeout import cats.effect.{ContextShift, Effect, IO} import cats.implicits._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.storage.File.FileAttributes import ch.epfl.bluebrain.nexus.storage.StorageError.{InternalError, OperationTimedOut} import ch.epfl.bluebrain.nexus.storage.attributes.AttributesCacheActor.Protocol._ import ch.epfl.bluebrain.nexus.storage.config.AppConfig.DigestConfig -import com.typesafe.scalalogging.Logger +import java.nio.file.Path +import java.time.Clock import scala.util.control.NonFatal trait AttributesCache[F[_]] { @@ -41,7 +40,8 @@ trait AttributesCache[F[_]] { } object AttributesCache { - private[this] val logger = Logger[this.type] + + private val logger = Logger[this.type] def apply[F[_], Source](implicit system: ActorSystem, @@ -65,15 +65,15 @@ object AttributesCache { .flatMap[FileAttributes] { case attributes: FileAttributes => F.pure(attributes) case other => - logger.error(s"Received unexpected reply from the file attributes cache: '$other'") - F.raiseError(InternalError("Unexpected reply from the file attributes cache")) + logger.error(s"Received unexpected reply from the file attributes cache: '$other'").to[F] >> + F.raiseError(InternalError("Unexpected reply from the file attributes cache")) } .recoverWith { case _: AskTimeoutException => F.raiseError(OperationTimedOut("reply from the file attributes cache timed out")) case NonFatal(th) => - logger.error("Exception caught while exchanging messages with the file attributes cache", th) - F.raiseError(InternalError("Exception caught while exchanging messages with the file attributes cache")) + logger.error(th)("Exception caught while exchanging messages with the file attributes cache").to[F] >> + F.raiseError(InternalError("Exception caught while exchanging messages with the file attributes cache")) } override def asyncComputePut(filePath: Path, algorithm: String): Unit = diff --git a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/AuthDirectives.scala b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/AuthDirectives.scala index 48e3bd3434..6f9349d7c3 100644 --- a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/AuthDirectives.scala +++ b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/AuthDirectives.scala @@ -3,10 +3,10 @@ package ch.epfl.bluebrain.nexus.storage.routes import akka.http.scaladsl.model.headers.OAuth2BearerToken import akka.http.scaladsl.server.Directive0 import akka.http.scaladsl.server.Directives._ +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.delta.kernel.jwt.AuthToken import ch.epfl.bluebrain.nexus.storage.StorageError._ import ch.epfl.bluebrain.nexus.storage.auth.AuthorizationMethod -import com.typesafe.scalalogging.Logger object AuthDirectives { @@ -19,8 +19,9 @@ object AuthDirectives { def validate(token: Option[AuthToken]): Directive0 = authorizationMethod.validate(token) match { case Left(error) => - logger.error("The user could not be validated.", error) - failWith(AuthenticationFailed) + onComplete(logger.error(error)("The user could not be validated.").unsafeToFuture()).flatMap { _ => + failWith(AuthenticationFailed) + } case Right(_) => pass } diff --git a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/Routes.scala b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/Routes.scala index 495bbb0fa6..c2f551f1a6 100644 --- a/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/Routes.scala +++ b/storage/src/main/scala/ch/epfl/bluebrain/nexus/storage/routes/Routes.scala @@ -4,6 +4,7 @@ import akka.http.scaladsl.model.headers.{`WWW-Authenticate`, HttpChallenges} import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler, Route} import cats.effect.IO +import ch.epfl.bluebrain.nexus.delta.kernel.Logger import ch.epfl.bluebrain.nexus.storage.StorageError._ import ch.epfl.bluebrain.nexus.storage.auth.AuthorizationMethod import ch.epfl.bluebrain.nexus.storage.config.AppConfig @@ -12,7 +13,6 @@ import ch.epfl.bluebrain.nexus.storage.routes.AuthDirectives._ import ch.epfl.bluebrain.nexus.storage.routes.PrefixDirectives._ import ch.epfl.bluebrain.nexus.storage.routes.instances._ import ch.epfl.bluebrain.nexus.storage.{AkkaSource, Rejection, StorageError, Storages} -import com.typesafe.scalalogging.Logger import scala.util.control.NonFatal @@ -42,11 +42,14 @@ object Routes { case err: PathInvalid => complete(err: StorageError) case err: StorageError => - logger.error("Exception caught during routes processing", err) - completeGeneric() + onComplete(logger.error(err)("Exception caught during routes processing").unsafeToFuture()) { _ => + completeGeneric() + } case NonFatal(err) => - logger.error("Exception caught during routes processing", err) - completeGeneric() + onComplete(logger.error(err)("Exception caught during routes processing").unsafeToFuture()) { _ => + completeGeneric() + } + } } @@ -54,13 +57,10 @@ object Routes { * @return * a complete RejectionHandler for all library and code rejections */ - final val rejectionHandler: RejectionHandler = { - val custom = RejectionHandling.apply { r: Rejection => - logger.debug(s"Handling rejection '$r'") + final val rejectionHandler: RejectionHandler = + RejectionHandling.apply { r: Rejection => r - } - custom withFallback RejectionHandling.notFound withFallback RejectionHandler.default - } + } withFallback RejectionHandling.notFound withFallback RejectionHandler.default /** * Wraps the provided route with rejection and exception handling.