Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 37 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,42 @@ jobs:
strategy:
fail-fast: false
matrix:
java: [8, 11, 17]
scala: [2.11.x, 2.12.x, 2.13.x, 3.x]
java: [ 8, 11, 17, 21 ]
scala: [ 2.11.x, 2.12.x, 2.13.x, 3.x ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: coursier/cache-action@v6
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: ${{matrix.java}}
- uses: sbt/setup-sbt@v1
- name: Test
run: |
sbt ++${{matrix.scala}} test
git diff --exit-code # check scalariform
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: coursier/cache-action@v6
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: ${{matrix.java}}
- uses: sbt/setup-sbt@v1
- name: Test
run: |
sbt ++${{matrix.scala}} test
git diff --exit-code # check scalariform

integration-test:
strategy:
fail-fast: false
matrix:
java: [ 8, 11, 17, 21 ]
scala: [ 2.13.x, 3.x ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: coursier/cache-action@v6
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: ${{matrix.java}}
- uses: sbt/setup-sbt@v1
- name: Test
run: |
sbt ++${{matrix.scala}} integration-test/test
git diff --exit-code # check scalariform
136 changes: 89 additions & 47 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,53 +1,95 @@
import Library.{logbackClassic, mockitoScala, scalaTest}
import _root_.com.github.sbt.osgi.SbtOsgi
import sbt.url

// basics

name := "scala-logging"
crossScalaVersions := Seq("3.3.5", "2.11.12", "2.12.20", "2.13.16")
scalaVersion := crossScalaVersions.value.head
ThisBuild / versionScheme := Some("early-semver")
scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-language:_",
"-encoding", "UTF-8",
"-Ywarn-unused"
)
incOptions := incOptions.value.withLogRecompileOnMacro(false)
val scala213 = "2.13.16"
val scala3 = "3.7.3"
val scala2 = Seq("2.11.12", "2.12.20", scala213)
val isScala3 = Def.setting {
CrossVersion.partialVersion(scalaVersion.value).exists(_._1 != 2)
}
libraryDependencies ++= Dependencies.scalaLogging(scalaVersion.value, isScala3.value)
initialCommands := """|import com.typesafe.scalalogging._
|import org.slf4j.{ Logger => Underlying, _ }""".stripMargin

// OSGi

enablePlugins(SbtOsgi)
osgiSettings
OsgiKeys.bundleSymbolicName := "com.typesafe.scala-logging"
OsgiKeys.privatePackage := Seq()
OsgiKeys.exportPackage := Seq("com.typesafe.scalalogging*")

// publishing

organization := "com.typesafe.scala-logging"
licenses := Seq("Apache 2.0 License" -> url("http://www.apache.org/licenses/LICENSE-2.0.html"))
homepage := Some(url("https://github.com/lightbend/scala-logging"))
Test / publishArtifact := false
pomIncludeRepository := (_ => false)
scmInfo := Some(
ScmInfo(url("https://github.com/lightbend/scala-logging"), "scm:git:git@github.com:lightbend/scala-logging.git")
)
developers := List(
Developer(
id = "hseeberger",
name = "Heiko Seeberger",
email = "",
url = url("http://heikoseeberger.de")
),
Developer(
id = "analytically",
name = "Mathias Bogaert",
email = "",
url = url("http://twitter.com/analytically")

val scalacOption = Def.setting {
if (isScala3.value) Seq.empty else Seq("-language:_", "-Ywarn-unused")
}

lazy val root = (project in file(".")).aggregate(core, scala2macros)

lazy val core = (project in file("core"))
.enablePlugins(SbtOsgi)
.settings(
name := "scala-logging",
organization := "com.typesafe.scala-logging",
crossScalaVersions := Seq(scala3) ++ scala2,
scalaVersion := crossScalaVersions.value.head,
ThisBuild / versionScheme := Some("early-semver"),
scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-encoding", "UTF-8"
) ++ scalacOption.value,
incOptions := incOptions.value.withLogRecompileOnMacro(false),
libraryDependencies ++= Dependencies.scalaLogging(scalaVersion.value, isScala3.value),
initialCommands :=
"""|import com.typesafe.scalalogging._
|import org.slf4j.{ Logger => Underlying, _ }""".stripMargin
).settings(
// OSGi
osgiSettings
).settings(
OsgiKeys.bundleSymbolicName := "com.typesafe.scala-logging",
OsgiKeys.privatePackage := Seq(),
OsgiKeys.exportPackage := Seq("com.typesafe.scalalogging*"),

// publishing
licenses := Seq("Apache 2.0 License" -> url("http://www.apache.org/licenses/LICENSE-2.0.html")),
homepage := Some(url("https://github.com/lightbend/scala-logging")),
Test / publishArtifact := false,
pomIncludeRepository := (_ => false),
scmInfo := Some(
ScmInfo(url("https://github.com/lightbend/scala-logging"), "scm:git:git@github.com:lightbend/scala-logging.git")
),
developers := List(
Developer(
id = "hseeberger",
name = "Heiko Seeberger",
email = "",
url = url("http://heikoseeberger.de")
),
Developer(
id = "analytically",
name = "Mathias Bogaert",
email = "",
url = url("http://twitter.com/analytically")
)
))
.dependsOn(scala2macros)

lazy val scala2macros = project
.settings(
name := "scala2macros",
scalaVersion := scala213,
crossScalaVersions := scala2,
libraryDependencies ++= Dependencies.scalaLogging(scalaVersion.value, false),
)

lazy val `integration-test` = project.in(file("integration-test"))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is expected that external dependencies should be used, especially to test CrossVersion.for2_13Use3, Currently only local testing

Copy link
Collaborator Author

@jxnu-liguobin jxnu-liguobin Sep 25, 2025

Choose a reason for hiding this comment

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

@SethTisue I will test CrossVersion.for2_13Use3 and CrossVersion.for3Use2_13 locally and release 4.0.0-RC1, what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand the motivation for testing CrossVersion.for2_13Use3 and CrossVersion.for3Use2_13? if the library is published for both 2 and 3, then 2 users should use the 2 version, 3 users should use the 3 version

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is it because the macro for 2 is defined in 3? Because it's mentioned in the Scala documentation, to be honest, I'm not sure if it's necessary.

Copy link
Collaborator

@SethTisue SethTisue Sep 26, 2025

Choose a reason for hiding this comment

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

Is it because the macro for 2 is defined in 3?

There's no such thing — Scala 2 macros and Scala 3 macros are entirely separate systems. There is zero interoperability of macros in either direction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you for clarifying. Can I merge it? I have already preserved the 3.x branch.

.settings(
publish / skip := true,
scalaVersion := scala3,
crossScalaVersions := Seq(scala3, scala213),
scalacOptions ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 13)) => Seq("-Ytasty-reader")
case _ => Seq.empty
}
},
libraryDependencies ++= Seq(
logbackClassic % "test",
mockitoScala % "test",
scalaTest % "test"
)
)
)
.dependsOn(core)
85 changes: 85 additions & 0 deletions core/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.typesafe.scalalogging

import org.slf4j.Marker
class LoggerImpl {

// Error

def error(message: String): Unit = macro Scala2LoggerMacro.errorMessage

def error(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.errorMessageCause

def error(message: String, args: Any*): Unit = macro Scala2LoggerMacro.errorMessageArgs

def error(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.errorMessageMarker

def error(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.errorMessageCauseMarker

def error(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.errorMessageArgsMarker

def whenErrorEnabled(body: Unit): Unit = macro Scala2LoggerMacro.errorCode

// Warn

def warn(message: String): Unit = macro Scala2LoggerMacro.warnMessage

def warn(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.warnMessageCause

def warn(message: String, args: Any*): Unit = macro Scala2LoggerMacro.warnMessageArgs

def warn(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.warnMessageMarker

def warn(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.warnMessageCauseMarker

def warn(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.warnMessageArgsMarker

def whenWarnEnabled(body: Unit): Unit = macro Scala2LoggerMacro.warnCode

// Info

def info(message: String): Unit = macro Scala2LoggerMacro.infoMessage

def info(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.infoMessageCause

def info(message: String, args: Any*): Unit = macro Scala2LoggerMacro.infoMessageArgs

def info(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.infoMessageMarker

def info(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.infoMessageCauseMarker

def info(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.infoMessageArgsMarker

def whenInfoEnabled(body: Unit): Unit = macro Scala2LoggerMacro.infoCode

// Debug

def debug(message: String): Unit = macro Scala2LoggerMacro.debugMessage

def debug(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.debugMessageCause

def debug(message: String, args: Any*): Unit = macro Scala2LoggerMacro.debugMessageArgs

def debug(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.debugMessageMarker

def debug(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.debugMessageCauseMarker

def debug(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.debugMessageArgsMarker

def whenDebugEnabled(body: Unit): Unit = macro Scala2LoggerMacro.debugCode

// Trace

def trace(message: String): Unit = macro Scala2LoggerMacro.traceMessage

def trace(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.traceMessageCause

def trace(message: String, args: Any*): Unit = macro Scala2LoggerMacro.traceMessageArgs

def trace(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.traceMessageMarker

def trace(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.traceMessageCauseMarker

def trace(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.traceMessageArgsMarker

def whenTraceEnabled(body: Unit): Unit = macro Scala2LoggerMacro.traceCode
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.typesafe.scalalogging

import org.slf4j.Marker

class LoggerTakingImplicitImpl[A] private[scalalogging] {

// Error

def error(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessage[A]

def error(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageCause[A]

def error(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageArgs[A]

def error(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageMarker[A]

def error(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageCauseMarker[A]

def error(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageArgsMarker[A]

def whenErrorEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorCode[A]

// Warn

def warn(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessage[A]

def warn(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageCause[A]

def warn(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageArgs[A]

def warn(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageMarker[A]

def warn(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageCauseMarker[A]

def warn(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageArgsMarker[A]

def whenWarnEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnCode[A]

// Info

def info(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessage[A]

def info(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageCause[A]

def info(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageArgs[A]

def info(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageMarker[A]

def info(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageCauseMarker[A]

def info(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageArgsMarker[A]

def whenInfoEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoCode[A]

// Debug

def debug(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessage[A]

def debug(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageCause[A]

def debug(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageArgs[A]

def debug(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageMarker[A]

def debug(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageCauseMarker[A]

def debug(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageArgsMarker[A]

def whenDebugEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugCode[A]

// Trace

def trace(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessage[A]

def trace(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageCause[A]

def trace(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageArgs[A]

def trace(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageMarker[A]

def trace(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageCauseMarker[A]

def trace(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageArgsMarker[A]

def whenTraceEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceCode[A]
}
Loading