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

zio.logging.LogContext.scala Maven / Gradle / Ivy

/*
 * Copyright 2019-2024 John A. De Goes and the ZIO Contributors
 *
 * 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 zio.logging

/**
 * A `LogContext` stores context associated with logging operations.
 */
final case class LogContext private (private val map: Map[LogAnnotation[_], Any]) { self =>

  /**
   * Merges this context with the specified context.
   */
  def ++(that: LogContext): LogContext = self merge that

  /**
   * Annotates the context with the specified annotation and value, returning
   * the new context.
   */
  def annotate[A](annotation: LogAnnotation[A], newA: A): LogContext =
    get(annotation) match {
      case None       => new LogContext(map + (annotation -> newA))
      case Some(oldA) => new LogContext(map + (annotation -> annotation.combine(oldA, newA)))
    }

  /**
   * Renders value for given annotation
   */
  def apply[A](logAnnotation: LogAnnotation[A]): Option[String] =
    get(logAnnotation).map(logAnnotation.render(_))

  /**
   * Retrieves the specified annotation from the context.
   */
  def get[A](annotation: LogAnnotation[A]): Option[A] =
    map.get(annotation).map(_.asInstanceOf[A])

  /**
   * Retrieves the specified annotation by name from the context, return rendered value.
   */
  def get(name: String): Option[String] =
    map.collectFirst {
      case (annotation: LogAnnotation[Any], value: Any) if (annotation.name == name) =>
        annotation.render(value)
    }

  /**
   * Merges this context with the specified context.
   */
  def merge(that: LogContext): LogContext = {
    val allKeys = self.map.keySet ++ that.map.keySet

    new LogContext(
      allKeys.foldLeft(Map.empty[LogAnnotation[_], Any]) { case (map, annotation) =>
        map +
          (annotation -> ((self.map.get(annotation), that.map.get(annotation)) match {
            case (Some(l), Some(r)) =>
              annotation.combine(l.asInstanceOf[annotation.Type], r.asInstanceOf[annotation.Type])
            case (None, Some(r))    => r
            case (Some(l), None)    => l
            case (None, None)       => throw new IllegalStateException("Impossible")
          }))
      }
    )
  }

  /**
   * Renders all log annotations in the context.
   */
  def asMap: Map[String, String] =
    map.asInstanceOf[Map[LogAnnotation[Any], Any]].map { case (annotation, value) =>
      annotation.name -> annotation.render(value)
    }
}

object LogContext {

  /**
   * An empty context.
   */
  val empty: LogContext = new LogContext(Map())
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy