Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-Configurable loggers #736

Merged
merged 56 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
264fba3
LogFilter types
justcoon May 26, 2023
51c0ec1
FilteredLogger
justcoon May 28, 2023
9fbce31
ReconfigurableLoggerSpec - wip
justcoon May 28, 2023
46a0e6c
ReconfigurableLoggerSpec - wip
justcoon May 30, 2023
b0072ab
ReconfigurableLogger
justcoon May 30, 2023
8a6ff7a
LogFilter, LogFormat, LoggerNameExtractor, LogGroup - sealed and cust…
justcoon May 31, 2023
d936391
LogFilter, LogFormat, LoggerNameExtractor, LogGroup - sealed and cust…
justcoon Jun 1, 2023
aba4a2a
LogFilter, LogFormat, LoggerNameExtractor, LogGroup - sealed and cust…
justcoon Jun 1, 2023
7f646c1
tests
justcoon Jun 1, 2023
b014b93
fmt
justcoon Jun 1, 2023
3a79cee
ReconfigurableLogger
justcoon Jun 1, 2023
3eea40d
ReconfigurableLogger
justcoon Jun 4, 2023
2680f94
http api - wip
justcoon Jun 6, 2023
780cfb2
http api - wip
justcoon Jun 7, 2023
7a3040c
http api - wip
justcoon Jun 10, 2023
6407859
LogFilter, LogFormat, LoggerNameExtractor, LogGroup - sealed and cust…
justcoon Jun 11, 2023
2c1303c
http api - wip
justcoon Jun 11, 2023
0e25b56
http api - wip
justcoon Jun 12, 2023
3e5089a
http api - wip
justcoon Jun 13, 2023
cc10971
ReconfigurableLogger
justcoon Jun 14, 2023
fef5576
LoggerConfigurer
justcoon Jun 15, 2023
821a203
LoggerConfigurer
justcoon Jun 16, 2023
343b3b5
LoggerConfigurer
justcoon Jun 16, 2023
bb6aa44
ReconfigurableLogger
justcoon Jun 17, 2023
929daa2
http api - wip
justcoon Jun 19, 2023
4c9953e
fmt
justcoon Jun 20, 2023
a8e0cfb
fix
justcoon Jun 20, 2023
f9dd304
LoggerLayers - wip
justcoon Jun 21, 2023
f9cc585
LoggerLayers - wip
justcoon Jun 22, 2023
89bf86f
LoggerLayers - wip
justcoon Jun 22, 2023
b5434ac
slf4j and jpl loggers as case class
justcoon Jun 24, 2023
2f9fe72
LoggerLayers - wip
justcoon Jun 24, 2023
caf07c1
LoggerLayers - wip
justcoon Jun 26, 2023
999aba9
ReconfigurableLogger
justcoon Jun 27, 2023
6c7b154
removed deprecated code
justcoon Jun 28, 2023
dcdcc37
ReconfigurableLogger
justcoon Jun 28, 2023
553e82f
LoggerLayers
justcoon Jun 28, 2023
b36de96
LoggerLayers
justcoon Jun 30, 2023
7d7a13f
ReconfigurableLogger
justcoon Jul 4, 2023
5d8c3c5
fmt fixes
justcoon Jul 11, 2023
1a74af4
Configs updates
justcoon Jul 11, 2023
15a7015
Configs updates
justcoon Jul 14, 2023
dc87ea4
filter
justcoon Jul 14, 2023
67063b8
moved http api to examples
justcoon Aug 13, 2023
3abe4c4
fmt fix
justcoon Oct 15, 2023
051f282
ConfigurableLogger - moved to examples
justcoon Oct 15, 2023
75ffc58
doc updates
justcoon Oct 28, 2023
fee6452
merge fixes
justcoon Nov 23, 2023
07ed580
dep. upgrades
justcoon Dec 24, 2023
725dfff
LoggerReconfigureApp with logger.conf
justcoon Dec 24, 2023
89d097c
benchmarks, docs
justcoon Dec 25, 2023
8182163
zio-http updates
justcoon Dec 25, 2023
cef3251
ConfigurableLoggerApp
justcoon Dec 25, 2023
21f975e
examples and docs updates
justcoon Dec 26, 2023
e3c09c6
benchmarks
justcoon Dec 26, 2023
a3c6c78
LoggerFactory typo fix
justcoon Jan 18, 2024
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
85 changes: 50 additions & 35 deletions benchmarks/src/main/scala/zio/logging/FilterBenchmarks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class FilterBenchmarks {
val runtime = Runtime.default

val unfilteredLogging: ZLayer[Any, Nothing, Unit] =
Runtime.removeDefaultLoggers >>> consoleLogger(ConsoleLoggerConfig(LogFormat.default, LogFilter.acceptAll))
Runtime.removeDefaultLoggers >>> makeSystemOutLogger(LogFormat.default.toLogger).install

val handWrittenFilteredLogging: ZLayer[Any, Nothing, Unit] = {
val loggerNameGroup: LogGroup[Any, String] = LoggerNameExtractor.loggerNameAnnotationOrTrace.toLogGroup()
Expand All @@ -37,40 +37,45 @@ class FilterBenchmarks {
}
}
)
Runtime.removeDefaultLoggers >>> consoleLogger(ConsoleLoggerConfig(LogFormat.default, filter))
Runtime.removeDefaultLoggers >>> makeSystemOutLogger(LogFormat.default.toLogger)
.filter(filter)
.install
}

val filterConfig: LogFilter.LogLevelByNameConfig = LogFilter.LogLevelByNameConfig(
LogLevel.Debug,
"a.b.c" -> LogLevel.Info,
"a.b.d" -> LogLevel.Warning,
"e" -> LogLevel.Info,
"f.g" -> LogLevel.Error,
"f" -> LogLevel.Info
)

val filterByLogLevelAndNameLogging: ZLayer[Any, Nothing, Unit] =
Runtime.removeDefaultLoggers >>> consoleLogger(
ConsoleLoggerConfig(
LogFormat.default,
LogFilter.logLevelByName(
LogLevel.Debug,
"a.b.c" -> LogLevel.Info,
"a.b.d" -> LogLevel.Warning,
"e" -> LogLevel.Info,
"f.g" -> LogLevel.Error,
"f" -> LogLevel.Info
)
)
)
Runtime.removeDefaultLoggers >>> makeSystemOutLogger(LogFormat.default.toLogger)
.filter(filterConfig.toFilter)
.install

val cachedFilterByLogLevelAndNameLogging: ZLayer[Any, Nothing, Unit] =
Runtime.removeDefaultLoggers >>> consoleLogger(
ConsoleLoggerConfig(
LogFormat.default,
LogFilter
.logLevelByName(
LogLevel.Debug,
"a.b.c" -> LogLevel.Info,
"a.b.d" -> LogLevel.Warning,
"e" -> LogLevel.Info,
"f.g" -> LogLevel.Error,
"f" -> LogLevel.Info
)
.cached
Runtime.removeDefaultLoggers >>> makeSystemOutLogger(LogFormat.default.toLogger)
.filter(filterConfig.toFilter.cached)
.install

val reconfigurableFilterByLogLevelAndNameLogging: ZLayer[Any, Nothing, Unit] =
Runtime.removeDefaultLoggers >>> ReconfigurableLogger
.make[Any, Nothing, String, Any, ConsoleLoggerConfig](
ZIO.succeed(ConsoleLoggerConfig(LogFormat.default, filterConfig)),
(config, _) => makeSystemOutLogger(config.format.toLogger).filter(config.toFilter)
)
)
.installUnscoped[Any]

val reconfigurableCachedFilterByLogLevelAndNameLogging: ZLayer[Any, Nothing, Unit] =
Runtime.removeDefaultLoggers >>> ReconfigurableLogger
.make[Any, Nothing, String, Any, ConsoleLoggerConfig](
ZIO.succeed(ConsoleLoggerConfig(LogFormat.default, filterConfig)),
(config, _) => makeSystemOutLogger(config.format.toLogger).filter(config.toFilter.cached)
)
.installUnscoped[Any]

val names: List[String] = List(
"a",
Expand Down Expand Up @@ -108,15 +113,17 @@ class FilterBenchmarks {
}

/**
* 2022/10/28 Initial results
* 2023/12/26 Initial results
*
* jmh:run -i 3 -wi 3 -f1 -t1 .*FilterBenchmarks.*
*
* Benchmark Mode Cnt Score Error Units
* FilterBenchmarks.cachedFilterByLogLevelAndNameLog thrpt 3 16623.054 ± 15855.331 ops/s
* FilterBenchmarks.filterByLogLevelAndNameLog thrpt 3 18048.598 ± 3868.976 ops/s
* FilterBenchmarks.handWrittenFilterLog thrpt 3 16352.488 ± 2316.372 ops/s
* FilterBenchmarks.noFilteringLog thrpt 3 15104.002 ± 3857.108 ops/s
* Benchmark Mode Cnt Score Error Units
* FilterBenchmarks.cachedFilterByLogLevelAndNameLog thrpt 3 14795.547 ± 1372.850 ops/s
* FilterBenchmarks.filterByLogLevelAndNameLog thrpt 3 15093.994 ± 1230.494 ops/s
* FilterBenchmarks.handWrittenFilterLog thrpt 3 13157.888 ± 10193.287 ops/s
* FilterBenchmarks.noFilteringLog thrpt 3 11043.746 ± 230.514 ops/s
* FilterBenchmarks.reconfigurableCachedFilterByLogLevelAndNameLog thrpt 3 7532.412 ± 415.760 ops/s
* FilterBenchmarks.reconfigurableFilterByLogLevelAndNameLog thrpt 3 7482.096 ± 628.534 ops/s
*/

@Benchmark
Expand All @@ -135,4 +142,12 @@ class FilterBenchmarks {
def cachedFilterByLogLevelAndNameLog(): Unit =
testLoggingWith(cachedFilterByLogLevelAndNameLogging)

@Benchmark
def reconfigurableFilterByLogLevelAndNameLog(): Unit =
testLoggingWith(reconfigurableFilterByLogLevelAndNameLogging)

@Benchmark
def reconfigurableCachedFilterByLogLevelAndNameLog(): Unit =
testLoggingWith(reconfigurableCachedFilterByLogLevelAndNameLogging)

}
8 changes: 5 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
.settings(enableZIO(enableStreaming = true))
.settings(
libraryDependencies ++= Seq(
"dev.zio" %%% "zio-parser" % zioParser
"dev.zio" %%% "zio-parser" % zioParser,
"dev.zio" %%% "zio-prelude" % zioPrelude
)
)
.jvmSettings(
Expand Down Expand Up @@ -198,8 +199,9 @@ lazy val examplesCore = project
.settings(
publish / skip := true,
libraryDependencies ++= Seq(
"dev.zio" %% "zio-metrics-connectors" % zioMetricsConnectorsVersion,
"dev.zio" %% "zio-config-typesafe" % zioConfig
"dev.zio" %% "zio-metrics-connectors-prometheus" % zioMetricsConnectorsVersion,
"dev.zio" %% "zio-http" % zioHttp,
"dev.zio" %% "zio-config-typesafe" % zioConfig
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ object ConsoleLoggerConfigSpec extends ZIOSpecDefault {
assertTrue(true)
}
},
test("equals config with same sources") {

// "%highlight{%timestamp{yyyy-MM-dd'T'HH:mm:ssZ} %fixed{7}{%level} [%fiberId] %name:%line %message %cause}" //FIXME

val logFormat =
"%highlight{%timestamp %fixed{7}{%level} [%fiberId] %name:%line %message %cause}"

val configProvider: ConfigProvider = ConfigProvider.fromMap(
Map(
"logger/format" -> logFormat,
"logger/filter/rootLevel" -> LogLevel.Info.label,
"logger/filter/mappings/zio.logging.example.LivePingService" -> LogLevel.Debug.label
),
"/"
)

import zio.prelude._
for {
c1 <- configProvider.load(ConsoleLoggerConfig.config.nested("logger"))
c2 <- configProvider.load(ConsoleLoggerConfig.config.nested("logger"))
} yield assertTrue(
c1.format == c2.format,
c1 === c2
)
},
test("fail on invalid filter config") {
val logFormat =
"%highlight{%timestamp{yyyy-MM-dd'T'HH:mm:ssZ} %fixed{7}{%level} [%fiberId] %name:%line %message %cause}"
Expand Down
27 changes: 27 additions & 0 deletions core/jvm/src/test/scala/zio/logging/FileLoggerConfigSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ object FileLoggerConfigSpec extends ZIOSpecDefault {
assertTrue(loadedConfig.bufferedIOSize.isEmpty)
}
},
test("equals config with same sources") {

val logFormat =
"%highlight{%timestamp %fixed{7}{%level} [%fiberId] %name:%line %message %cause}"

val configProvider: ConfigProvider = ConfigProvider.fromMap(
Map(
"logger/format" -> logFormat,
"logger/path" -> "file:///tmp/test.log",
"logger/autoFlushBatchSize" -> "2",
"logger/bufferedIOSize" -> "4096",
"logger/rollingPolicy/type" -> "TimeBasedRollingPolicy",
"logger/filter/rootLevel" -> LogLevel.Info.label,
"logger/filter/mappings/zio.logging.example.LivePingService" -> LogLevel.Debug.label
),
"/"
)

import zio.prelude._
for {
c1 <- configProvider.load(ConsoleLoggerConfig.config.nested("logger"))
c2 <- configProvider.load(ConsoleLoggerConfig.config.nested("logger"))
} yield assertTrue(
c1.format == c2.format,
c1 === c2
)
},
test("fail on invalid charset and filter config") {
val logFormat =
"%highlight{%timestamp{yyyy-MM-dd'T'HH:mm:ssZ} %fixed{7}{%level} [%fiberId] %name:%line %message %cause}"
Expand Down
139 changes: 138 additions & 1 deletion core/jvm/src/test/scala/zio/logging/LogFilterSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@ package zio.logging
import zio.logging.test.TestService
import zio.test.ZTestLogger.LogEntry
import zio.test._
import zio.{ Cause, Chunk, Config, ConfigProvider, FiberId, FiberRefs, LogLevel, LogSpan, Runtime, Trace, ZIO, ZLogger }
import zio.{
Cause,
Chunk,
Config,
ConfigProvider,
FiberId,
FiberRefs,
LogLevel,
LogSpan,
Runtime,
Trace,
ZIO,
ZIOAspect,
ZLogger
}

object LogFilterSpec extends ZIOSpecDefault {

Expand Down Expand Up @@ -399,6 +413,129 @@ object LogFilterSpec extends ZIOSpecDefault {
"**" -> LogLevel.Info
)
)
},
test("log filters by log level and name from same configuration should be equal") {

val configProvider = ConfigProvider.fromMap(
Map(
"logger/rootLevel" -> LogLevel.Debug.label,
"logger/mappings/a" -> LogLevel.Info.label,
"logger/mappings/a.b.c" -> LogLevel.Warning.label,
"logger/mappings/e.f" -> LogLevel.Error.label
),
"/"
)

import zio.prelude._

for {
f1 <- configProvider
.load(LogFilter.LogLevelByNameConfig.config.nested("logger"))
.map(LogFilter.logLevelByName)
f2 <- configProvider
.load(LogFilter.LogLevelByNameConfig.config.nested("logger"))
.map(LogFilter.logLevelByName)
f3 <- configProvider
.load(LogFilter.LogLevelByNameConfig.config.nested("logger"))
.map(LogFilter.logLevelByName)
.map(_.cached)
f4 <- configProvider
.load(LogFilter.LogLevelByNameConfig.config.nested("logger"))
.map(LogFilter.logLevelByName)
.map(_.cached)
} yield assertTrue(f1 === f2, f3 === f4)
},
test("and") {

val filter = LogFilter.causeNonEmpty.and(LogFilter.logLevel(LogLevel.Info))

def testFilter(level: LogLevel, cause: Cause[_], expected: Boolean) =
assertTrue(
filter(
Trace.empty,
FiberId.None,
level,
() => "",
cause,
FiberRefs.empty,
List.empty,
Map.empty
) == expected
)

testFilter(LogLevel.Info, Cause.fail("fail"), true) && testFilter(
LogLevel.Info,
Cause.empty,
false
) && testFilter(LogLevel.Debug, Cause.fail("fail"), false)
},
test("or") {

val filter = LogFilter.causeNonEmpty.or(LogFilter.logLevel(LogLevel.Info))

def testFilter(level: LogLevel, cause: Cause[_], expected: Boolean) =
assertTrue(
filter(
Trace.empty,
FiberId.None,
level,
() => "",
cause,
FiberRefs.empty,
List.empty,
Map.empty
) == expected
)

testFilter(LogLevel.Info, Cause.fail("fail"), true) && testFilter(LogLevel.Info, Cause.empty, true) && testFilter(
LogLevel.Debug,
Cause.fail("fail"),
true
) && testFilter(LogLevel.Debug, Cause.empty, false)
},
test("not") {

val filter = LogFilter.causeNonEmpty.and(LogFilter.logLevel(LogLevel.Info)).not

def testFilter(level: LogLevel, cause: Cause[_], expected: Boolean) =
assertTrue(
filter(
Trace.empty,
FiberId.None,
level,
() => "",
cause,
FiberRefs.empty,
List.empty,
Map.empty
) == expected
)

testFilter(LogLevel.Info, Cause.fail("fail"), false) && testFilter(
LogLevel.Info,
Cause.empty,
true
) && testFilter(LogLevel.Debug, Cause.fail("fail"), true)
},
test("cached") {
val logOutputRef = new java.util.concurrent.atomic.AtomicReference[Chunk[LogEntry]](Chunk.empty)

val filter = LogFilter
.logLevelByGroup(
LogLevel.Info,
LogGroup.loggerName,
"zio.logger1" -> LogLevel.Debug,
"zio.logging.test" -> LogLevel.Warning
)
.cached
.asInstanceOf[LogFilter.CachedFilter[String]]

(for {
_ <- ZIO.logDebug("debug") @@ ZIOAspect.annotated(loggerNameAnnotationKey, "zio.logger1")
res1 = filter.cache.get(List("zio", "logger1") -> LogLevel.Debug)
_ <- ZIO.logDebug("debug") @@ ZIOAspect.annotated(loggerNameAnnotationKey, "zio.logger2")
res2 = filter.cache.get(List("zio", "logger2") -> LogLevel.Debug)
} yield assertTrue(res1 == true, res2 == false)).provideLayer(testLogger(logOutputRef, filter))
}
)
}
Loading