Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade ZIO Logging #782

Merged
merged 3 commits into from
Sep 23, 2021
Merged

Conversation

vagroz
Copy link
Collaborator

@vagroz vagroz commented Sep 21, 2021

This PR brings changes of tofu-zio-logging according to the new Module Pattern 2.0. Plain logging with encapsulated FiberRef context will be especially useful.
I've written the documentation how to use it. Pls check my grammar.

Also fix logging documentation:

  1. move tofu.logging.recipes to Receipes category
  2. make page Loggable typeclass as copy-paste from the old docs

}
```
Run the program and look at the output:
```json lines
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it's better to write this example using ConsoleContextLayout for readability. Even on 23'' screen I have to scroll it right now to see the main stuff.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok just remove extra fields

@derive(loggable)
final case class Context(requestId: Int)
```
Here we use [Tofu Derevo](https://github.com/tofu-tf/derevo) for automatic derivation `Loggable` instance.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to see the link to Loggable page here.

```
Here we use [Tofu Derevo](https://github.com/tofu-tf/derevo) for automatic derivation `Loggable` instance.

The main idea of this approach is to store your in ZIO [FiberRef](https://zio.dev/docs/datatypes/fiber/fiberref).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if someone would want to store the Context not in FiberRef, but in R itself (which is blasphemy of course)? Should we have a note about this approach here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should. But I've never use the R as a context. It may be useful with TF and WithContext monad, but I'm not good in TF, so I'm not able to write a good example with that approach.

Now I can note that this is one of possible ways

import tofu.logging.{LoggedValue, Logging}
import zio._

class ZUniversalContextLogging[R](name: String, fctx: (LoggedValue => Unit) => URIO[R, Unit])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fctx: (LoggedValue => Unit) => URIO[R, Unit]

We definitely need a scaladoc with a note on unsafety of this argument

Copy link
Member

@Odomontois Odomontois Sep 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel we can simplify that down to
ctxLog: URIO[R, LoggedValue]
and use direct flatMap in the write methods instead of callback approach

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I've got it. I'll fix

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -37,6 +39,34 @@ class ZLogsSuite extends AnyFlatSpec with Matchers {
LogTree(ctx)
} should ===(List.fill(2)(expected))
}

"ZLogs plain with context" should "log the context" in {
type CtxService = FiberRef[(FooService, BarService)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to rework this spec? It's kinda confusing when I see context which is named as some service or something.

Copy link
Collaborator Author

@vagroz vagroz Sep 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context which is named as some service

Look, actually FiberRef[(FooService, BarService)] is a service providing the context (FooService, BarService), right?
From ZIO docs:

Has[A] represents a dependency on a service of type A

And val logLayer: URLayer[Has[CtxService], Has[ZLogging.Make]] below depends on this
In production the service would be more complex like

trait CtxService {
  def getContext: UIO[(GlobalSate, FiberState)]

  def setReadiness(v: Boolean): UIO[Unit]

 //... etc
}

import zio._

class ZUniversalContextLogs[R: Loggable] extends ZLogging.ZMake[R] {
private def useContextValue(f: LoggedValue => Unit): URIO[R, Unit] = ZIO.access[R](f(_))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach is a little bit troublesome, since we imply some unexeptional effect. Call of f should probably be wrapped by the effectTotal. I suppose this is the main concern of @FunFunFine towards LoggedValue => Unit in the previous thread.
Still URIO[R, LoggedValue] should work safely

@Odomontois Odomontois merged commit 29221d2 into tofu-tf:master Sep 23, 2021
@Odomontois Odomontois added the enhancement New feature or request label Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants