All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kadai.log.json.JsonMessage.scala Maven / Gradle / Ivy

The newest version!
package kadai.log
package json

import io.circe.{ Encoder, Json }

import scala.reflect.ClassTag

/**
 * A Jsonable message. JsonLayout knows how to encode this payload.
 */
case class JsonMessage[A](value: A, json: List[(String, Json)]) extends LogMessage[A]

object JsonMessage {
  val Default = "msg" // preserves backwards-compatibility

  // need to fully qualify the JSON objects with a root qualifiers due to limitations in ElasticSearch indexing
  final case class Qualified[A](fields: A => List[(String, Json)])

  object Qualified extends LowPriorityImplicits {
    def apply[A: Qualified]: Qualified[A] =
      implicitly[Qualified[A]]

    /**
     * Override the default name used, uses an EncodeJson for the object, eg:
     *
     * { name: { (encoded json object } }
     */
    def by[A](name: String)(implicit ev: Encoder[A]): Qualified[A] =
      Qualified { a => List(name -> ev(a)) }

    /**
     * Control the list of top level names that are output and their individual representations. Eg:
     *
     * List("foo" -> fooJson, "bar" -> barJson, "baz" -> bazJson)
     *
     * will output:
     *
     * {
     *   foo: (encoded fooJson)
     *   bar: (encoded barJson)
     *   baz: (encoded bazJson)
     * }
     */
    def using[A](f: A => List[(String, Json)]): Qualified[A] =
      Qualified(f)
  }
}

sealed trait LowPriorityImplicits {
  import JsonMessage.Qualified

  implicit val QualifiedString: Qualified[String] =
    Qualified.by(JsonMessage.Default)

  implicit def QualifiedOption[A: Qualified]: Qualified[Option[A]] =
    Qualified { _.fold(List[(String, Json)]())(Qualified[A].fields) }

  implicit def QualifiedTuple2[A: Qualified, B: Qualified]: Qualified[(A, B)] =
    new Qualified({ case (a, b) => Qualified[A].fields(a) ::: Qualified[B].fields(b) })

  implicit def QualifiedTuple3[A: Qualified, B: Qualified, C: Qualified]: Qualified[(A, B, C)] =
    new Qualified({ case (a, b, c) => Qualified[A].fields(a) ::: Qualified[B].fields(b) ::: Qualified[C].fields(c) })

  implicit def QualifiedTuple4[A: Qualified, B: Qualified, C: Qualified, D: Qualified]: Qualified[(A, B, C, D)] =
    new Qualified({ case (a, b, c, d) => Qualified[A].fields(a) ::: Qualified[B].fields(b) ::: Qualified[C].fields(c) ::: Qualified[D].fields(d) })

  /** Fallback to simple class name. */
  implicit def defaultQualified[A: ClassTag: Encoder]: JsonMessage.Qualified[A] =
    Qualified.by[A](implicitly[ClassTag[A]].runtimeClass.getSimpleName)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy