Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Apr 13 19:02
    codecov[bot] commented #276
  • Apr 13 19:01
    codecov[bot] commented #276
  • Apr 13 18:57
    scala-steward opened #276
  • Apr 12 05:05
    codecov[bot] commented #275
  • Apr 12 05:00
    scala-steward closed #260
  • Apr 12 05:00
    scala-steward commented #260
  • Apr 12 05:00
    scala-steward opened #275
  • Apr 09 11:44
    iRevive commented #273
  • Apr 09 05:29
    joesan opened #274
  • Apr 08 07:15
    sergeykolbasov commented #237
  • Apr 08 07:14
    sergeykolbasov commented #257
  • Apr 07 13:53
    kubukoz commented #273
  • Apr 07 13:43
    iRevive commented #273
  • Apr 07 13:37
    codecov[bot] commented #273
  • Apr 07 13:36
    codecov[bot] commented #273
  • Apr 07 13:32
    codecov[bot] commented #273
  • Apr 07 13:32
    iRevive synchronize #273
  • Apr 07 11:56
    iRevive commented #273
  • Apr 06 22:42
    kubukoz commented #273
  • Apr 06 21:42
    sergeykolbasov commented #273
Charles Dabadie
@CharlesD91
On top of it we use your .withAsync, so that the log is not felt
Sergey Kolbasov
@sergeykolbasov

Ah, I see

It's also one possible solution. Other two I have in mind are temporary log file and in-memory queue

Latter is simulated with async logger, indeed
Charles Dabadie
@CharlesD91
For the first option you would still have to block at some point when you have to repatriate the logs from the temporary log file to the fixed main one ?
Sergey Kolbasov
@sergeykolbasov
yeah, true

I'd be glad to review PR with this functionality in case if you wish to make it :smile:

I wonder if it's possible to generalize it so it would play nicely with the current implementation, but I'm open-minded anyway

Charles Dabadie
@CharlesD91
Cool :)
Last thing, in our custom implementation we are cheating a bit and we are using fs2.Stream to simplify the periodical tasks
Is it a dependency you would consider adding to the Odin project ?
Sergey Kolbasov
@sergeykolbasov
What's up with Timer for periodical tasks?
Odin uses it in async logger i.e.
Charles Dabadie
@CharlesD91
fs2.Stream basically handles the infinite recursive Timer loop for you. But it is a minor optimization, and I could use Timer directly
also it handles the stopping of the loop nicely via a SignallingRef
Sergey Kolbasov
@sergeykolbasov

Resource with Fiber cancellation works as well, I think it's almost single liner or smth

AsyncLogger example:

Resource
      .make {
        for {
          queue <- ConcurrentQueue.withConfig[F, LoggerMessage](queueCapacity, ChannelType.MPSC)
          logger = AsyncLogger(queue, timeWindow, inner)
          fiber <- logger.runF //it returns a fiber with inf timer loop
        } yield {
          (fiber, logger)
        }
      } {
        case (fiber, _) => fiber.cancel //on resource release we should cancel the fiber
      }
      .map {
        case (_, logger) => logger
      }
Charles Dabadie
@CharlesD91
Ok cool, I will use this. Thank you !
Sergey Kolbasov
@sergeykolbasov
Thanks!
Charles Dabadie
@CharlesD91
Hi @sergeykolbasov !
How are you these days ?
It is a WIP for now, but the main logic is there. I will try to finish this next week.
Sergey Kolbasov
@sergeykolbasov

Hi @CharlesD91

Thanks for PR, I'll take a look on it tmrw/weekend

Diem
@bi0h4ck
Hi, I have Logger[F] in a trait WithLogger, a class A extends WithLogger. Is there any way that I can customize the log message to print out className A since by default, className that has Logger[F] which is WithLogger is printed out?
Sergey Kolbasov
@sergeykolbasov
Hi @bi0h4ck
How do you call logger itself? Do you call it directly? Position is derived during call of .debug/info/warn/etc as implicit parameter
Diem
@bi0h4ck

I didn’t call it directly. I have a function logAndReturn that takes error: SomeError and return SomeError. In this function, I call Logger[F].error to log error messages and then return SomeError.

So in the service layer for instance, when logAndReturn is called, className/functionName of WithLogger#logAndReturn is printed out. But I want the service className is printed out

Sergey Kolbasov
@sergeykolbasov
Okay, got it. Then I suggest to modify a signature of your wrapper function a bit to include an implicit parameter of type https://github.com/valskalla/odin/blob/master/core/src/main/scala/io/odin/meta/Position.scala
then it'll be propagated to logger call as implicit parameter as well
so it would be something like
def logAndReturn(e: SomeError)(implicit pos: io.odin.meta.Position): F[SomeError]

Essentially, in the case when implicit is missing it's automatically derived here:
https://github.com/valskalla/odin/blob/master/core/src/main/scala/io/odin/meta/Position.scala#L14-L24

using macro of sourcefile library

Which means that correct position will be derived in the place of invocation of your wrapper method
Diem
@bi0h4ck
I see. I was trying to modify Position in LoggerMessage but sourcecode.File gives me File.type so I couldn’t access value
Anyway, I will try out your suggestion. Thanks so much for the help.
Sergey Kolbasov
@sergeykolbasov
glad to help :)
Diem
@bi0h4ck

I modified the Position like this
object Position { implicit def derivePosition( implicit fileName: sourcecode.File, packageName: sourcecode.Pkg, line: sourcecode.Line ): Position = io.odin.meta.Position(fileName.value, fileName.value, packageName.value, line.value) } and I got the className printed out as I want.

Thank you so much :)

By the way, our team loves your awesome logging algebra Odin
Sergey Kolbasov
@sergeykolbasov
Thanks for your kind words 😌
Diem
@bi0h4ck
Hi @sergeykolbasov, Do you think it’s a bad idea to have slf4j logging for some non-algebra places and odin for some places with effect F? If it is, what is the better way to work around this?
Sergey Kolbasov
@sergeykolbasov

Hi @bi0h4ck

You have couple of options.
One is to pass around Logger[IO] (or any other effect) and call it with finalizing .unsafeRunSync() (or async version) to evaluate right away. That way you might use the single instance of logger which would make your life easier.

Or use slf4j with LoggerBinder:
https://github.com/valskalla/odin#slf4j-bridge

Generally, I'd suggest to stick to F as long as possible, because logging itself is a side-effect and it's way easier to i.e. test it when you have each call as a value
slf4j bridge is rather a workaround for libraries you depend upon that use corresponding API and you wish to use Odin as a backend for it
Diem
@bi0h4ck
I thought about having slf4j and then pull in the slf4j bridge since we don’t define the effect until the end, so we can’t evaluate it right away. Thanks for response!!! :)
Jamal CHAQOURI
@redarqas_twitter
hi @sergeykolbasov is there an API to change the logging level at runtime ?
Sergey Kolbasov
@sergeykolbasov

Hi @redarqas_twitter

Sadly you can't mutate existing logger, but create a copy of one using withMinLevel syntax

Jamal CHAQOURI
@redarqas_twitter
thank you @sergeykolbasov
Ivano Pagano
@ivanopagano
hello, I hope this is a good place to ask questions... I'm following the example to test with the WriterTLogger provided with the library
I stumble into an unexpected issue with upcasting of the instance to a more general Logger[WriterTIO]
the compiler keeps telling me that WriterTLogger[WriterTIO] can't be assigned as a Logger[WriterTIO]
has anyone ever found this unexpected behaviour?
Ivano Pagano
@ivanopagano
nevermind, I managed to figure out the signatures
Sergey Kolbasov
@sergeykolbasov

out of curiosity, and for the sake of future generations

@ivanopagano what was the problem & solution for you? :)

Ivano Pagano
@ivanopagano
late to reply, ooops
I messed the type parameter as you can see from my example above, putting WriterTLogger[WriterTIO] (WriterTIO being the alias to my WriterT[IO, A, B])
while the type expected the actual effect F[_] without wrapping, i.e. WriterTLogger[IO]
Jakub Kozłowski
@kubukoz
Hey, I'm not sure the slf4j integration is correctly described - slf4j doesn't seem to be able to see the var with the version
if you look at the generated bytecode you'll see that it's not even a field, a getter is generated instead