Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jun 14 18:11
    codecov[bot] commented #319
  • Jun 14 18:11
    codecov[bot] commented #318
  • Jun 14 18:09
    codecov[bot] commented #319
  • Jun 14 18:09
    codecov[bot] commented #318
  • Jun 14 18:09
    codecov[bot] commented #265
  • Jun 14 18:03
    scala-steward opened #319
  • Jun 14 18:03
    scala-steward opened #318
  • Jun 14 18:03
    codecov[bot] commented #265
  • Jun 14 18:02
    scala-steward synchronize #265
  • Jun 14 17:12
    sergeykolbasov commented #271
  • Jun 14 17:03

    github-actions[bot] on master

    Update documentation skip-check… (compare)

  • Jun 14 16:59

    sergeykolbasov on v0.12.0

    (compare)

  • Jun 14 16:59

    sergeykolbasov on master

    fix docs (compare)

  • Jun 14 16:37

    github-actions[bot] on master

    Update documentation skip-check… (compare)

  • Jun 14 16:35

    sergeykolbasov on v0.12.0

    (compare)

  • Jun 14 16:25
    sergeykolbasov closed #311
  • Jun 14 16:25
    sergeykolbasov closed #304
  • Jun 14 16:25
    sergeykolbasov closed #303
  • Jun 14 16:25
    sergeykolbasov closed #302
  • Jun 14 16:25
    sergeykolbasov closed #301
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
Jakub Kozłowski
@kubukoz
btw. is there a logstash integration somewhere? I guess it would mostly be decoding the logs to logstash's format as JSON and sending them with a http client like sttp
Sergey Kolbasov
@sergeykolbasov

slf4j doesn't seem to be able to see the var with the version

damn Java >_>

@kubukoz

Nope, there is no logstash integration. At Zalando we ship logs with a separate agent as a part of Kubernetes deployment, so it never was a priority for us to have such functionality in this lib.

However, it's not the first time I hear that question, so I'm open for contributions :)

Sergey Kolbasov
@sergeykolbasov
Hm, I don't think it's possible to define java-compatible static field
Jakub Kozłowski
@kubukoz
Yeah, I tried to do it in Java and refer to the Scala sources but hit a bug in bloop
Can't remember what sbt did...
Well, it compiled but I'm not sure it worked.
Sergey Kolbasov
@sergeykolbasov

@kubukoz

I think I solved that issue with StaticLoggerBinder.

You need a plain Java class:

package org.slf4j.impl;

import oh.boi.ExternalLogger;

public class StaticLoggerBinder extends ExternalLogger {
    public static String REQUESTED_API_VERSION = "1.7";
    private static StaticLoggerBinder instance = new StaticLoggerBinder();

    public static StaticLoggerBinder getSingleton() {
        return instance;
    }
}

together with a Scala one:

package oh.boi

import cats.effect.{ContextShift, Clock, Effect, IO, Timer}
import io.odin._
import io.odin.slf4j.OdinLoggerBinder

import scala.concurrent.ExecutionContext

class ExternalLogger extends OdinLoggerBinder[IO] {

  val ec: ExecutionContext = scala.concurrent.ExecutionContext.global
  implicit val timer: Timer[IO] = IO.timer(ec)
  implicit val clock: Clock[IO] = timer.clock
  implicit val cs: ContextShift[IO] = IO.contextShift(ec)
  implicit val F: Effect[IO] = IO.ioEffect

  val loggers: PartialFunction[String, Logger[IO]] = {
    case "some.external.package.SpecificClass" =>
      consoleLogger[IO](minLevel = Level.Warn) //disable noisy external logs
    case _ => //if wildcard case isn't provided, default logger is no-op
      consoleLogger[IO]()
  }
}
I'll update documentation later
Jakub Kozłowski
@kubukoz
that's what I tried to do ;)
Sergey Kolbasov
@sergeykolbasov
well, works for me
Rohan Sircar
@rohan-sircar
Hi, if you don't mind me asking, how is scala.js support coming along?
Sergey Kolbasov
@sergeykolbasov

Hello

Sorry, didn't test it yet. In theory there is a PR opened, but have to check it out

Rohan Sircar
@rohan-sircar
Will be awesome when it comes out. But take your time.
Nice package name btw - package oh.boi . I put wow.doge in one of my projects.
Sergey Kolbasov
@sergeykolbasov
such wov, very amaze :)
Rohan Sircar
@rohan-sircar
very logging, much functional, many thanks
I had a few questions, I went through the documentation and couldn't find the answers there but maybe I missed it.
  1. In the Slf4j bridge, is there a built in way to do a catch all of all the classes under a package, or would I need to use something like a regex?
    val loggers: PartialFunction[String, Logger[IO]] = {
     case "org.asynchttpclient.netty.channel.DefaultChannelPool" =>
       consoleLogger[IO](minLevel = Level.Warn)
     case _ => //if wildcard case isn't provided, default logger is no-op
       consoleLogger[IO]()
    }
    Suppose I wanted to catch all classes under org.asynchttpclient under one case clause.
Rohan Sircar
@rohan-sircar

2 - Is the logger instance supposed to be passed around, or should each class create it's own logger instance?
3 - I've been unable to integrate the Resource monad in my code that uses Monix Task, so I'm using the unsafe method for getting the logger instance -

val logger = consoleLogger().withAsyncUnsafe()

But I'm not sure what unsafe means here, does it refer to flushing the loggers buffer? Is it possible to flush the buffer in a shutdown hook thus making it safe?