Skip to content

Commit

Permalink
Merge pull request #2 from TinkoffCreditSystems/master
Browse files Browse the repository at this point in the history
upd
  • Loading branch information
FunFunFine authored Jan 26, 2020
2 parents 8ac012e + 754c7bf commit a13566d
Show file tree
Hide file tree
Showing 21 changed files with 149 additions and 45 deletions.
23 changes: 14 additions & 9 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Publish._, Dependencies._
import com.typesafe.sbt.SbtGit.git

val libVersion = "0.6.1"
val libVersion = "0.6.2"

lazy val setMinorVersion = minorVersion := {
CrossVersion.partialVersion(scalaVersion.value) match {
Expand Down Expand Up @@ -105,9 +105,20 @@ lazy val loggingLayout = project
)
.dependsOn(loggingStr)

lazy val loggingUtil = project
.in(file("logging/util"))
.settings(
defaultSettings,
publishName := "logging-util",
libraryDependencies += slf4j,
)
.dependsOn(loggingStr, concurrent)



lazy val logging = project
.dependsOn(loggingStr, loggingDer, loggingLayout)
.aggregate(loggingStr, loggingDer, loggingLayout)
.dependsOn(loggingStr, loggingDer, loggingLayout, loggingUtil)
.aggregate(loggingStr, loggingDer, loggingLayout, loggingUtil)
.settings(defaultSettings)

lazy val env = project
Expand Down Expand Up @@ -285,12 +296,6 @@ lazy val defaultScalacOptions = scalacOptions ++= Seq(
"-language:implicitConversions", // Allow definition of implicit functions called views
"-unchecked", // Enable additional warnings where generated code depends on assumptions.

// Inlining options. More at https://www.lightbend.com/blog/scala-inliner-optimizer, https://github.com/scala/scala/pull/4858, https://github.com/scala/bug/issues/8790
"-opt:l:method", // Enable intra-method optimizations: unreachable-code,simplify-jumps,compact-locals,copy-propagation,redundant-casts,box-unbox,nullness-tracking,closure-invocations,allow-skip-core-module-init,assume-modules-non-null,allow-skip-class-loading.
"-opt:l:inline", // Enable cross-method optimizations (note: inlining requires -opt-inline-from): l:method,inline.
"-opt-inline-from:tofu.**", // Patterns for classfile names from which to allow inlining
"-opt-warnings:none", // No optimizer warnings.

// "-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access. (SHOULD BE USED ONLY IN DEV)
"-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
"-Xlint:delayedinit-select", // Selecting member of DelayedInit.
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/tofu/Guarantee.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ trait Finally[F[_], Exit[_]] extends Guarantee[F] {
object Finally extends FinallyInstanceChain[Finally]

trait FinallyInstanceChain[T[f[_], exit[_]] >: Finally[f, exit]] {
final implicit def fromBracket[F[_], E](implicit F: Bracket[F, E]): Finally[F, TConst[ExitCase[E], *]] =
final implicit def fromBracket[F[_], E](implicit F: Bracket[F, E]): T[F, TConst[ExitCase[E], *]] =
new Finally[F, TConst[ExitCase[E], *]] {
def finallyCase[A, B, C](init: F[A])(action: A => F[B])(release: (A, ExitCase[E]) => F[C]): F[B] =
F.bracketCase(init)(action) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/tofu/syntax/bracket.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ object bracket {

def bracketAlways[B, C](
use: A => F[B]
)(release: A => F[C])(implicit F: Applicative[F], FG: Guarantee[F]): F[B] =
)(release: A => F[C])(FG: Guarantee[F]): F[B] =
FG.bracket(fa)(use) { case (a, _) => release(a) }

def guaranteeIncomplete[B](release: F[B])(implicit F: Applicative[F], FG: Guarantee[F]): F[A] =
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/scala/tofu/syntax/context.scala
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package tofu.syntax

import cats.Monad
import tofu._

object context {
def context[F[_]](implicit ctx: Context[F]): F[ctx.Ctx] = ctx.context

def hasContext[F[_], C](implicit ctx: F HasContext C): F[C] = ctx.context

def ask[F[_]] = new AskPA[F](true)

class AskPA[F[_]](val __ : Boolean) extends AnyVal {
def apply[C, A](f: C => A)(implicit ctx: F HasContext C): F[A] = ctx.ask(f)
}

def askF[F[_]] = new AskFPA[F](true)

class AskFPA[F[_]](val __ : Boolean) extends AnyVal {
def apply[C, A](f: C => F[A])(implicit ctx: F HasContext C, M: Monad[F]): F[A] = ctx.askF(f)
}

def runContext[F[_]] = new RunContextPA[F]

class RunContextPA[F[_]] {
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/scala/tofu/syntax/error.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import tofu.Raise.ContravariantRaise

object raise {
implicit final class RaiseOps[E](private val err: E) extends AnyVal {
def raise[F[_], A](implicit raise: Raise[F, E]): F[A] = raise.raise(err)
def raise[F[_], A](implicit raise: ContravariantRaise[F, E]): F[A] = raise.raise(err)
}

implicit final class RaiseMonadOps[F[_], A](private val fa: F[A]) extends AnyVal {
def verified[E](p: A => Boolean)(err: E)(implicit raise: Raise[F, E], F: Monad[F]): F[A] =
def verified[E](p: A => Boolean)(err: E)(implicit raise: ContravariantRaise[F, E], F: Monad[F]): F[A] =
F.flatMap(fa)(a => if (p(a)) F.pure(a) else raise.raise(err))
}

Expand All @@ -23,7 +23,7 @@ object raise {
def toRaise[F[_]](
implicit
app: Applicative[F],
raise: Raise[F, E]
raise: ContravariantRaise[F, E]
): F[A] =
either match {
case Left(err) => raise.raise(err)
Expand Down
13 changes: 13 additions & 0 deletions core/src/test/scala/tofu/GuaranteeSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package tofu

import cats.effect.ExitCase

object GuaranteeSuite {

def summonInstancesForBracket[F[_]: BracketThrow](): Unit = {
implicitly[Guarantee[F]]
implicitly[Finally[F, TConst[ExitCase[Throwable], *]]]
()
}

}
13 changes: 13 additions & 0 deletions env/src/main/scala/tofu/env/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,19 @@ sealed trait Env[E, +A] {
def timeoutTo[B >: A](dur: FiniteDuration, backup: Env[E, B]): Env[E, B] =
mapTask2(backup)(_.timeoutTo(dur, _))

/** Times the Env execution, returning its duration and the computed value in case of success.
* Delegates to underlying [[monix.eval.Task.timed]].
* Usage example:
* {{{
* for {
* r <- Env.delay(1 + 1).timed
* (duration, value) = r
* _ <- Env.delay(println("executed in " + duration.toMillis + " ms"))
* } yield value
* }}}*/
def timed: Env[E, (FiniteDuration, A)] =
mapTask(_.timed)

// concurrency
def doOnCancel(callback: Env[E, Unit]): Env[E, A] =
Env(ctx => run(ctx).doOnCancel(callback.run(ctx)))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package tofu.logging

trait LogsVOps[I[_], F[_]]
trait LogsVOps[+I[_], F[_]]
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package tofu.logging

trait LogsVOps[I[_], F[_]] { self: Logs[I, F] =>
trait LogsVOps[+I[_], F[_]] { self: Logs[I, F] =>
final def named[name <: String with Singleton](
implicit name: ValueOf[name]
): I[ServiceLogging[F, name]] =
Expand Down
6 changes: 3 additions & 3 deletions logging/structured/src/main/scala/tofu/logging/Logging.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import cats.{Applicative, Apply, FlatMap}
import com.github.ghik.silencer.silent
import org.slf4j.{Logger, LoggerFactory, Marker}
import tofu.higherKind
import tofu.higherKind.{Embed, RepresentableK}
import tofu.higherKind.{Embed, Function2K, RepresentableK}
import tofu.logging.impl.EmbedLogging
import tofu.syntax.functionK._
import tofu.syntax.monoidalK._

import scala.reflect.ClassTag

Expand Down Expand Up @@ -94,7 +94,7 @@ object Logging {

/** having two logging implementation call `first` after `second` */
def combine[F[_]: Apply](first: Logging[F], second: Logging[F]): Logging[F] =
loggingRepresentable.map2K(first, second)(makeFunctionK(t => t.first *> t.second))
first.zipWithK(second)(Function2K[F, F, F](_ *> _))

private[logging] def loggerForService[S](implicit ct: ClassTag[S]): Logger =
LoggerFactory.getLogger(ct.runtimeClass)
Expand Down
6 changes: 3 additions & 3 deletions logging/structured/src/main/scala/tofu/logging/Logs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import tofu.syntax.monadic._

import scala.reflect.ClassTag

trait Logs[I[_], F[_]] extends LogsVOps[I, F] {
trait Logs[+I[_], F[_]] extends LogsVOps[I, F] {
def forService[Svc: ClassTag]: I[Logging[F]]
def byName(name: String): I[Logging[F]]

Expand Down Expand Up @@ -53,15 +53,15 @@ object Logs {
def byName(name: String): I[Logging[F]] = logging.pure[I]
}

def empty[I[_]: Applicative, F[_]: Applicative]: Logs[I, F] = const(Logging.empty[F])
def empty[I[_]: Applicative, F[_]: Applicative]: Logs[I, F] = const[I, F](Logging.empty[F])

def combine[I[_]: Apply, F[_]: Apply](las: Logs[I, F], lbs: Logs[I, F]): Logs[I, F] = new Logs[I, F] {
def forService[Svc: ClassTag]: I[Logging[F]] = las.forService.map2(lbs.forService)(Logging.combine[F])
def byName(name: String): I[Logging[F]] = las.byName(name).map2(lbs.byName(name))(Logging.combine[F])
}

implicit def logsMonoid[I[_]: Applicative, F[_]: Applicative]: Monoid[Logs[I, F]] = new Monoid[Logs[I, F]] {
def empty: Logs[I, F] = Logs.empty
def empty: Logs[I, F] = Logs.empty[I, F]
def combine(x: Logs[I, F], y: Logs[I, F]): Logs[I, F] = Logs.combine(x, y)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@ class ContramapLoggable[A, B](val self: Loggable.Base[A], val f: B => A) extends
self.putField(f(a), name, input)
override def logVia(a: B, addParam: (String, Any) => Unit): Unit = self.logVia(f(a), addParam)
override def logShow(a: B): String = self.logShow(f(a))
override def loggedValue(a: B): LoggedValue = self.loggedValue(f(a))
override def contramap[C](g: C => B): Loggable[C] = self.contramap(AndThen(g).andThen(f))
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ class HiddenLoggable[A](val self: Loggable.Base[A]) extends Loggable[A] {
def fields[I, V, R, M](a: A, input: I)(implicit receiver: LogRenderer[I, V, R, M]): R = self.fields(a, input)
def putValue[I, V, R, M](a: A, v: V)(implicit r: LogRenderer[I, V, R, M]): M = self.putValue(a, v)
override def logVia(a: A, addParam: (String, Any) => Unit): Unit = self.logVia(a, addParam)
override def loggedValue(a: A): LoggedValue = self.loggedValue(a)
}
28 changes: 21 additions & 7 deletions logging/structured/src/test/scala/tofu/logging/LoggableSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ class LoggableSuite extends FlatSpec with Matchers {
implicit val testIntLoggable: Loggable[TestInt] = new Loggable[Int] {
def fields[I, V, R, S](a: Int, i: I)(implicit r: LogRenderer[I, V, R, S]): R =
i.sub("missing")(r.zero) |+|
i.sub("sign")(
(v: V) =>
r.coalesce(
v => v.whenVal(a < 0)(v.putString("negative")),
v => v.whenVal(a > 0)(v.putString("positive")),
v
)) |+|
i.sub("sign")((v: V) =>
r.coalesce(
v => v.whenVal(a < 0)(v.putString("negative")),
v => v.whenVal(a > 0)(v.putString("positive")),
v
)
) |+|
r.sub("value", i)(_.putInt(a.toLong))
def putValue[I, V, R, S](a: Int, v: V)(implicit r: LogRenderer[I, V, R, S]): S = v.putInt(a.toLong)
def logShow(a: Int): String = a.toString
Expand Down Expand Up @@ -49,6 +49,20 @@ class LoggableSuite extends FlatSpec with Matchers {
1.asRight[String].logShow shouldBe "1"
}

"hide after named" should "hide value in message" in {
case class ResponseTime(value: Int)

val hideAfterNamed: Loggable[ResponseTime] =
Loggable.intLoggable.named("responseTime").hide.contramap(_.value)

val namedAfterHide: Loggable[ResponseTime] =
Loggable.intLoggable.hide.named("responseTime").contramap(_.value)

val sample = ResponseTime(1337)

assert(hideAfterNamed.loggedValue(sample).toString.isEmpty)
assert(namedAfterHide.loggedValue(sample).toString.isEmpty)
}
}

object LoggableSuite {
Expand Down
43 changes: 43 additions & 0 deletions logging/util/src/main/scala/tofu/logging/atom/AtomLogger.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package tofu.logging.atom
import java.time.Instant
import java.util.concurrent.TimeUnit

import cats.effect.Clock
import cats.{Applicative, FlatMap}
import tofu.concurrent.Atom
import tofu.higherKind.Embed
import tofu.logging.{LoggedValue, Logging, Logs}
import tofu.syntax.monadic._

import scala.reflect.{ClassTag, classTag}

final case class LogLine(
loggerName: String,
level: Logging.Level,
message: String,
timestamp: Instant,
values: Vector[LoggedValue],
)

class AtomLogging[F[_]: FlatMap: Clock](log: Atom[F, Vector[LogLine]], name: String) extends Logging[F] {
override def write(level: Logging.Level, message: String, values: LoggedValue*): F[Unit] =
Clock[F].realTime(TimeUnit.MILLISECONDS).flatMap { time =>
log.update(
_ :+ LogLine(
loggerName = name,
level = level,
message = message,
timestamp = Instant.ofEpochMilli(time),
values = values.toVector
)
)
}

}

final case class AtomLogs[I[_]: Applicative, F[_]: FlatMap: Clock](flog: F[Atom[F, Vector[LogLine]]])
extends Logs[I, F] {
def forService[Svc: ClassTag]: I[Logging[F]] = byName(classTag[Svc].runtimeClass.getName)
def byName(name: String): I[Logging[F]] =
Embed.of(flog.map[Logging[F]](new AtomLogging[F](_, name))).pure[I]
}
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object Dependencies {

val catsEffect = "2.0.0"

val catsTagless = "0.10"
val catsTagless = "0.11"

val monocle = "2.0.1"

Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.3.6
sbt.version = 1.3.7
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
package tofu.logging
package tofu.logging.zlogs

import org.slf4j.LoggerFactory
import tofu.logging.{Loggable, Logging}
import tofu.logging.Logging.loggerForService
import tofu.logging.impl.{UIOZLogging, URIOZLoggingImpl}
import zio.{UIO, URIO}

import tofu.logging.zlogs.impl.{UIOZLogging, URIOZLoggingImpl}
import zio.UIO
import scala.reflect.ClassTag

trait ZLogs[R] extends Logs[UIO, URIO[R, *]]

object ZLogs {
val uio: Logs[UIO, UIO] = new Logs[UIO, UIO] {
val uio: ZLogs[Any] = new ZLogs[Any] {
def forService[Svc: ClassTag]: UIO[Logging[UIO]] =
UIO.effectTotal(new UIOZLogging(loggerForService[Svc]))
def byName(name: String): UIO[Logging[UIO]] = UIO.effectTotal(new UIOZLogging(LoggerFactory.getLogger(name)))
}

def withContext[R: Loggable]: Logs[UIO, URIO[R, *]] = new Logs[UIO, URIO[R, *]] {
def forService[Svc: ClassTag]: UIO[Logging[URIO[R, *]]] =
def withContext[R: Loggable]: ZLogs[R] = new ZLogs[R] {
def forService[Svc: ClassTag]: UIO[ZLogging[R]] =
UIO.effectTotal(new URIOZLoggingImpl(loggerForService[Svc]))
override def byName(name: String): UIO[Logging[URIO[R, *]]] =
override def byName(name: String): UIO[ZLogging[R]] =
UIO.effectTotal(new URIOZLoggingImpl[R](LoggerFactory.getLogger(name)))
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package tofu.logging.impl
package tofu.logging.zlogs.impl

import org.slf4j.Logger
import tofu.logging.LoggedValue
import tofu.logging.impl.LoggingImpl
import zio.UIO

class UIOZLogging(logger: Logger) extends LoggingImpl[UIO](logger) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package tofu.logging.impl
package tofu.logging.zlogs.impl

import tofu.logging.{Loggable, LoggedValue}
import org.slf4j.{Logger, Marker}
import tofu.logging.impl.{ContextMarker, LoggingImpl}
import zio.{UIO, URIO}

class URIOZLoggingImpl[R: Loggable](logger: Logger) extends LoggingImpl[URIO[R, *]](logger) {
Expand Down
8 changes: 8 additions & 0 deletions zio/logging/src/main/scala/tofu/logging/zlogs/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package tofu.logging

import zio.{UIO, URIO}

package object zlogs {
type ZLogs[R] = Logs[UIO, URIO[R, *]]
type ZLogging[R] = Logging[URIO[R, *]]
}

0 comments on commit a13566d

Please sign in to comment.