Skip to content

Commit

Permalink
Adds log4s logging to free and tagless (#512)
Browse files Browse the repository at this point in the history
* Adds log4s logging to free and tagless

* Aligned packages and objects and fix typo

* Adds documentation

* Setting version to 0.6.2

* Improvement build.sbt and minor changes in documentation

* Fix wrong compilation tut documentation

* Adds deprecated to default implicit

* Sort packages in one line

* Very minor grammar changes

You could use either both, depending on your requirements, and the
usage would be quite similar.

You could use either, or both, depending on your requirements, and the
usage would be quite similar.

If that is not accurate, just take out the or both and change to:

You could use either, depending on your requirements, and the usage
would be quite similar.
  • Loading branch information
eperinan committed Jan 17, 2018
1 parent cd7ece2 commit 288535c
Show file tree
Hide file tree
Showing 13 changed files with 345 additions and 19 deletions.
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ lazy val config = jvmModule("config")
lazy val logging = module("logging")
.dependsOn(core)
.jvmSettings(
libraryDependencies += %%("journal-core")
libraryDependencies ++= Seq(
%%("journal-core"),
%%("log4s")
)
)
.jsSettings(
libraryDependencies += %%%("slogging")
Expand Down
39 changes: 36 additions & 3 deletions docs/src/main/tut/docs/patterns/logging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,43 @@ The set of abstract operations of the `Logging` algebra are specified as follows
}
```

Each one of the operations corresponds to variations of `debug`, `error`, `info`, and `warn` which cover most use cases when performing logging in an application.
Each one of the operations correspond to variations of `debug`, `error`, `info`, and `warn` which cover most use cases when performing logging in an application.

The _frees-logging_ module contains built-in interpreters for both Scala.jvm and Scala.js which you may use out of the box.
The JVM handler interpreter is based on the [Verizon's Journal Library](https://github.com/Verizon/journal) and the JS handler in [slogging](https://github.com/jokade/slogging).
The JVM handler interpreter is based on the [Verizon's Journal Library](https://github.com/Verizon/journal) and [Log4s wrapper](https://github.com/Log4s/log4s).
In addition, the JS handler interpreter is based on [slogging](https://github.com/jokade/slogging).

### Wrappers available

Freestyle logging supports two wrappers for logging messages, `journal` and `log4s`. These wrappers are only available for `free` and `tagless` in JVM.

You could use either, or both, depending on your requirements, and the usage would be quite similar.

To use `log4s`:

```tut:book
import freestyle.free._
import freestyle.free.implicits._
import freestyle.free.logging._
import freestyle.free.loggingJVM.log4s.implicits._
@module trait App {
val log: LoggingM
}
```

To use `journal`:

```tut:book
import freestyle.free._
import freestyle.free.implicits._
import freestyle.free.logging._
import freestyle.free.loggingJVM.journal.implicits._
@module trait App {
val log: LoggingM
}
```

### Example

Expand All @@ -56,7 +89,7 @@ import cats.implicits._
import scala.util.Try
```

We will define a simple algebra with a stub handler that returns a list of customer Id's for illustration purposes:
We will define a simple algebra with a stub handler that returns a list of customer Ids for illustration purposes:

```tut:book
@free trait CustomerService {
Expand Down
20 changes: 20 additions & 0 deletions modules/logging/jvm/src/main/scala/free/implicits.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2017-2018 47 Degrees, LLC. <http://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package freestyle.free.loggingJVM

@deprecated("Use freestyle.free.loggingJVM.journal.implicits or freestyle.free.loggingJVM.log4s.implicits instead", "0.6.2")
object implicits extends freestyle.tagless.loggingJVM.journal.Implicits
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
* limitations under the License.
*/

package freestyle.free
package freestyle.free.loggingJVM.journal

object loggingJVM {

object implicits extends freestyle.tagless.loggingJVM.Implicits

}
object implicits extends freestyle.tagless.loggingJVM.journal.Implicits
19 changes: 19 additions & 0 deletions modules/logging/jvm/src/main/scala/free/log4s.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2017-2018 47 Degrees, LLC. <http://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package freestyle.free.loggingJVM.log4s

object implicits extends freestyle.tagless.loggingJVM.log4s.Implicits
20 changes: 20 additions & 0 deletions modules/logging/jvm/src/main/scala/tagless/implicits.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2017-2018 47 Degrees, LLC. <http://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package freestyle.tagless.loggingJVM

@deprecated("Use freestyle.tagless.loggingJVM.journal.implicits or freestyle.tagless.loggingJVM.log4s.implicits instead", "0.6.2")
object implicits extends freestyle.tagless.loggingJVM.journal.Implicits
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
* limitations under the License.
*/

package freestyle.tagless
package freestyle.tagless.loggingJVM

import cats.Applicative
import freestyle.logging._
import freestyle.tagless.logging._
import journal._
import _root_.journal._

object loggingJVM {
object journal {

sealed abstract class TaglessLoggingMHandler[M[_]] extends LoggingM.Handler[M] {

Expand Down
80 changes: 80 additions & 0 deletions modules/logging/jvm/src/main/scala/tagless/log4s.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2017-2018 47 Degrees, LLC. <http://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package freestyle.tagless.loggingJVM

import cats.Applicative
import freestyle.logging._
import freestyle.tagless.logging._
import org.log4s._

object log4s {

sealed abstract class TaglessLoggingMHandler[M[_]] extends LoggingM.Handler[M] {

import sourcecode.{File, Line}

protected def withLogger[A](f: Logger => A): M[A]

def debug(msg: String, srcInfo: Boolean)(implicit line: Line, file: File): M[Unit] =
withLogger(_.debug(formatMessage(msg, srcInfo, line, file)))

def debugWithCause(msg: String, cause: Throwable, srcInfo: Boolean)(
implicit
line: Line,
file: File): M[Unit] =
withLogger(_.debug(cause)(formatMessage(msg, srcInfo, line, file)))

def error(msg: String, srcInfo: Boolean)(implicit line: Line, file: File): M[Unit] =
withLogger(_.error(formatMessage(msg, srcInfo, line, file)))

def errorWithCause(msg: String, cause: Throwable, srcInfo: Boolean)(
implicit
line: Line,
file: File): M[Unit] =
withLogger(_.error(cause)(formatMessage(msg, srcInfo, line, file)))

def info(msg: String, srcInfo: Boolean)(implicit line: Line, file: File): M[Unit] =
withLogger(_.info(formatMessage(msg, srcInfo, line, file)))

def infoWithCause(msg: String, cause: Throwable, srcInfo: Boolean)(
implicit
line: Line,
file: File): M[Unit] =
withLogger(_.info(cause)(formatMessage(msg, srcInfo, line, file)))

def warn(msg: String, srcInfo: Boolean)(implicit line: Line, file: File): M[Unit] =
withLogger(_.warn(formatMessage(msg, srcInfo, line, file)))

def warnWithCause(msg: String, cause: Throwable, srcInfo: Boolean)(
implicit
line: Line,
file: File): M[Unit] =
withLogger(_.warn(cause)(formatMessage(msg, srcInfo, line, file)))

}

trait Implicits {
implicit def taglessLoggingApplicative[M[_]: Applicative](
implicit log: Logger = getLogger("")): LoggingM.Handler[M] = new TaglessLoggingMHandler[M] {

protected def withLogger[A](f: Logger => A): M[A] = Applicative[M].pure(f(log))

}
}

object implicits extends Implicits
}
79 changes: 79 additions & 0 deletions modules/logging/jvm/src/test/scala/free/LoggingTestsJournal.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2017-2018 47 Degrees, LLC. <http://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package freestyle.free

import cats.instances.future._
import cats.{Id, Monad}
import freestyle.free.implicits._
import freestyle.free.loggingJVM.implicits._
import org.scalatest.{AsyncWordSpec, Matchers}

import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NoStackTrace

class LoggingTestsJournal extends AsyncWordSpec with Matchers {

implicit override def executionContext = ExecutionContext.Implicits.global

import algebras._

"Logging Freestyle free integration journal" should {

case object Cause extends Exception("kaboom") with NoStackTrace

"allow a log message to be interleaved inside a program monadic flow" in {
val program = for {
a <- app.nonLogging.x
_ <- app.loggingM.debug("Debug Message", sourceAndLineInfo = true)
_ <- app.loggingM.debugWithCause("Debug Message", Cause)
_ <- app.loggingM.error("Error Message")
_ <- app.loggingM.errorWithCause("Error Message", Cause)
_ <- app.loggingM.info("Info Message")
_ <- app.loggingM.infoWithCause("Info Message", Cause)
_ <- app.loggingM.warn("Warning Message")
_ <- app.loggingM.warnWithCause("Warning Message", Cause)
b <- FreeS.pure(1)
} yield a + b
program.interpret[Future] map { _ shouldBe 2 }
}

"not depend on MonadError, thus allowing use of Monads without MonadError, like Id, for test algebras" in {
val program = for {
a <- app.nonLogging.x
_ <- app.loggingM.info("Info Message")
_ <- app.loggingM.infoWithCause("Info Message", Cause)
b <- FreeS.pure(1)
} yield a + b
program.interpret[TestAlgebra].run("configHere") shouldBe 2
}

"allow injecting a Logger instance" in {
val program = for {
a <- FreeS.pure(1)
_ <- app.loggingM.info("Info Message")
_ <- app.loggingM.error("Error Message")
b <- FreeS.pure(1)
} yield a + b

implicit val logger = journal.Logger("Potatoes")

program
.interpret[TestAlgebra]
.run("configHere") shouldEqual 2
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import org.scalatest.{AsyncWordSpec, Matchers}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NoStackTrace

class LoggingTests extends AsyncWordSpec with Matchers {
class LoggingTestsLog4s extends AsyncWordSpec with Matchers {

implicit override def executionContext = ExecutionContext.Implicits.global

import algebras._

"Logging Freestyle free integration" should {
"Logging Freestyle free integration log4s" should {

case object Cause extends Exception("kaboom") with NoStackTrace

Expand Down
Loading

0 comments on commit 288535c

Please sign in to comment.