Skip to content

Commit 3cf98ff

Browse files
authored
Config file (#15)
* Add --config-file support (json-log-viewer.yml)
1 parent ee14b51 commit 3cf98ff

File tree

28 files changed

+323
-74
lines changed

28 files changed

+323
-74
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ cat log.txt | node ./json-log-viewer/js/target/scala-3.3.1/json-log-viewer-opt/m
4444

4545
# frontend-laminar
4646

47-
```~fastOptJS::webpack```
47+
```~fastLinkJS::webpack```
4848

4949
# k9s plugin
5050

build.sbt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ val fs2Version = "3.11.0"
2020

2121
lazy val `json-log-viewer` = crossProject(JSPlatform, JVMPlatform)
2222
.in(file("json-log-viewer"))
23-
// .jvmEnablePlugins(JavaAppPackaging)
23+
.jvmEnablePlugins(JavaAppPackaging)
2424
.settings(
2525
name := "json-log-viewer",
2626
organization := "ru.d10xa",
@@ -35,6 +35,8 @@ lazy val `json-log-viewer` = crossProject(JSPlatform, JVMPlatform)
3535
"io.circe" %%% "circe-core" % circeVersion,
3636
"io.circe" %%% "circe-literal" % circeVersion % Test,
3737
"io.circe" %%% "circe-parser" % circeVersion,
38+
"io.circe" %%% "circe-generic" % circeVersion,
39+
"io.circe" %%% "circe-yaml-scalayaml" % "0.16.0",
3840
"com.lihaoyi" %%% "fansi" % "0.5.0",
3941
"org.scala-lang.modules" %%% "scala-parser-combinators" % "2.4.0",
4042
"org.scalameta" %% "munit" % "0.7.29" % Test
@@ -47,9 +49,7 @@ lazy val `json-log-viewer` = crossProject(JSPlatform, JVMPlatform)
4749
)
4850
.jsSettings(
4951
publish / skip := true,
50-
scalaJSUseMainModuleInitializer := true,
5152
fork := false,
52-
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) }
5353
)
5454

5555
lazy val `make-logs` = project
@@ -79,8 +79,9 @@ lazy val `frontend-laminar` = project
7979
"com.github.plokhotnyuk.jsoniter-scala" %%% "jsoniter-scala-core" % "2.28.4",
8080
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.28.4" % "provided"
8181
),
82-
Compile / fastOptJS / scalaJSLinkerConfig ~= { _.withSourceMap(false) },
83-
Compile / fullOptJS / scalaJSLinkerConfig ~= { _.withSourceMap(true) },
82+
Compile / fastLinkJS / scalaJSLinkerConfig ~= { _.withSourceMap(true) },
83+
Compile / fullLinkJS / scalaJSLinkerConfig ~= { _.withSourceMap(true) },
84+
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
8485
scalaJSUseMainModuleInitializer := true,
8586
(Test / requireJsDomEnv) := true,
8687
useYarn := true

frontend-laminar/src/main/resources/index-fastopt.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<link rel="stylesheet" href="./app.css">
88
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
99
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
10-
<script type="text/javascript" src="../../../target/scala-3.4.0/frontend-laminar-fastopt/main.js"></script>
10+
<script type="text/javascript" src="../../../target/scala-3.5.0/frontend-laminar-fastopt/main.js"></script>
1111
</head>
1212
<body>
1313
<div id="app-container"></div>

frontend-laminar/src/main/resources/index-fullopt.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8">
55
<title>[FULL] json-log-viewer</title>
66
<link rel="stylesheet" href="./app.css">
7-
<script type="text/javascript" src="../../../target/scala-3.4.0/frontend-laminar-opt/main.js"></script>
7+
<script type="text/javascript" src="../../../target/scala-3.5.0/frontend-laminar-opt/main.js"></script>
88
</head>
99
<body>
1010
<div id="app-container"></div>

frontend-laminar/src/main/scala/App.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ import fansi.ErrorMode
99
import org.scalajs.dom
1010
import org.scalajs.dom.HTMLButtonElement
1111
import org.scalajs.dom.HTMLDivElement
12-
import ru.d10xa.jsonlogviewer.Config
13-
import ru.d10xa.jsonlogviewer.Config
14-
import ru.d10xa.jsonlogviewer.Config.FormatIn
15-
import ru.d10xa.jsonlogviewer.Config.FormatIn.Json
16-
import ru.d10xa.jsonlogviewer.Config.FormatIn.Logfmt
17-
import ru.d10xa.jsonlogviewer.DeclineOpts
12+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn
13+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn.Json
14+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn.Logfmt
15+
import ru.d10xa.jsonlogviewer.decline.Config
16+
import ru.d10xa.jsonlogviewer.decline.Config
17+
import ru.d10xa.jsonlogviewer.decline.DeclineOpts
1818
import ru.d10xa.jsonlogviewer.query.QueryCompiler
1919

20+
import scala.util.matching.Regex
21+
2022
object App {
2123

2224
val jsonLogSample: String =
@@ -48,7 +50,7 @@ object App {
4850
FormatIn.Json
4951
)
5052

51-
val splitPattern = "([^\"]\\S*|\".+?\")\\s*".r
53+
val splitPattern: Regex = "([^\"]\\S*|\".+?\")\\s*".r
5254
def splitArgs(s: String): Seq[String] =
5355
splitPattern
5456
.findAllMatchIn(s)
@@ -64,7 +66,7 @@ object App {
6466
case Right(value) => Some(value)
6567
} yield DeclineOpts.command
6668
.parse(splitArgs(cli))
67-
.map(cfg => cfg.copy(filter = filter, formatIn = formatIn))
69+
.map(cfg => cfg.copy(filter = filter, formatIn = Some(formatIn)))
6870

6971
def main(args: Array[String]): Unit = {
7072
lazy val container = dom.document.getElementById("app-container")

frontend-laminar/src/main/scala/ViewElement.scala

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import com.raquo.laminar.DomApi
55
import com.raquo.laminar.api.L.{*, given}
66
import com.raquo.laminar.api.L
77
import ru.d10xa.jsonlogviewer.Application
8-
import ru.d10xa.jsonlogviewer.Config
9-
import ru.d10xa.jsonlogviewer.TimestampConfig
10-
import ru.d10xa.jsonlogviewer.Config
118
import ru.d10xa.jsonlogviewer.JsonDetector
129
import ru.d10xa.jsonlogviewer.JsonPrefixPostfix
1310
import ru.d10xa.jsonlogviewer.JsonLogLineParser
14-
import ru.d10xa.jsonlogviewer.TimestampConfig
1511
import ru.d10xa.jsonlogviewer.TimestampFilter
1612
import ru.d10xa.jsonlogviewer.ColorLineFormatter
1713
import ru.d10xa.jsonlogviewer.LogViewerStream
1814
import ru.d10xa.jsonlogviewer.LogLineFilter
1915
import fs2.*
20-
import ru.d10xa.jsonlogviewer.Config.FormatIn
16+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn
17+
import ru.d10xa.jsonlogviewer.decline.Config
18+
import ru.d10xa.jsonlogviewer.decline.Config
19+
import ru.d10xa.jsonlogviewer.decline.TimestampConfig
20+
import ru.d10xa.jsonlogviewer.decline.TimestampConfig
2121
import ru.d10xa.jsonlogviewer.logfmt.LogfmtLogLineParser
2222

2323
import scala.util.chaining.scalaUtilChainingOps
@@ -31,8 +31,9 @@ object ViewElement {
3131
case (string, Right(c)) =>
3232
val jsonPrefixPostfix = JsonPrefixPostfix(JsonDetector())
3333
val logLineParser = c.formatIn match
34-
case FormatIn.Json => JsonLogLineParser(c, jsonPrefixPostfix)
35-
case FormatIn.Logfmt => LogfmtLogLineParser(c)
34+
case Some(FormatIn.Logfmt) => LogfmtLogLineParser(c)
35+
case Some(FormatIn.Json) => JsonLogLineParser(c, jsonPrefixPostfix)
36+
case other => throw new IllegalStateException(s"Unsupported format-in value: $other")
3637

3738
fs2.Stream
3839
.emits(string.split("\n"))
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ru.d10xa.jsonlogviewer.decline
2+
3+
import cats.data.Validated
4+
import cats.data.Validated
5+
import cats.effect.IO
6+
import cats.effect.IO
7+
import cats.effect.IO
8+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn
9+
10+
class ConfigInitImpl extends ConfigInit {
11+
12+
override def initConfig(c: Config): IO[Config] = {
13+
IO.pure(
14+
c.copy(
15+
formatIn = c.formatIn.orElse(Some(FormatIn.Json)),
16+
filter = c.filter
17+
)
18+
)
19+
}
20+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package ru.d10xa.jsonlogviewer.decline
2+
3+
import cats.data.Validated
4+
import cats.effect.IO
5+
import ru.d10xa.jsonlogviewer.ConfigYamlReader
6+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn
7+
import cats.syntax.all.*
8+
9+
import java.io.File
10+
11+
class ConfigInitImpl extends ConfigInit {
12+
13+
override def initConfig(c: Config): IO[Config] = {
14+
def findConfigFile(baseName: String, extensions: List[String]): Option[String] = {
15+
extensions.collectFirst {
16+
case ext if new File(s"$baseName.$ext").exists() =>
17+
s"$baseName.$ext"
18+
}
19+
}
20+
21+
val configFileOpt: Option[String] = c.configFile.map(_.file).orElse {
22+
findConfigFile("json-log-viewer", List("yml", "yaml", "YML", "YAML"))
23+
}
24+
25+
val configIO: IO[Option[ConfigYaml]] = configFileOpt match {
26+
case Some(file) if new File(file).exists() =>
27+
ConfigYamlReader.fromYamlFile(file).flatMap {
28+
case Validated.Valid(config) =>
29+
config.some.pure[IO]
30+
case Validated.Invalid(errors) =>
31+
IO.raiseError(
32+
new IllegalArgumentException(errors.toList.mkString(", "))
33+
)
34+
}
35+
case Some(file) =>
36+
IO.raiseError(new IllegalArgumentException(s"Configuration file not found: $file"))
37+
case None =>
38+
None.pure[IO]
39+
}
40+
configIO.map {
41+
case Some(config) =>
42+
c.copy(
43+
filter = c.filter.orElse(config.filter),
44+
formatIn =
45+
c.formatIn.orElse(config.formatIn).orElse(Some(FormatIn.Json))
46+
)
47+
case None => c
48+
}
49+
}
50+
}
Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package ru.d10xa.jsonlogviewer
22

3+
import cats.data.Validated
34
import cats.effect.*
45
import com.monovore.decline.Opts
56
import com.monovore.decline.effect.CommandIOApp
67
import fs2.*
78
import fs2.io.*
8-
import ru.d10xa.jsonlogviewer.Config.FormatIn
9+
import ru.d10xa.jsonlogviewer.decline.Config
10+
import ru.d10xa.jsonlogviewer.decline.Config.FormatIn
11+
import ru.d10xa.jsonlogviewer.decline.DeclineOpts
912
import ru.d10xa.jsonlogviewer.logfmt.LogfmtLogLineParser
13+
import _root_.io.circe.yaml.scalayaml.parser
14+
import cats.syntax.all.*
15+
import ru.d10xa.jsonlogviewer.decline.ConfigInitImpl
16+
import ru.d10xa.jsonlogviewer.decline.ConfigYaml
1017

1118
object Application
1219
extends CommandIOApp(
@@ -20,16 +27,21 @@ object Application
2027
.filter(_.nonEmpty)
2128

2229
def main: Opts[IO[ExitCode]] = DeclineOpts.config.map { c =>
23-
val jsonPrefixPostfix = JsonPrefixPostfix(JsonDetector())
24-
val logLineParser = c.formatIn match
25-
case FormatIn.Json => JsonLogLineParser(c, jsonPrefixPostfix)
26-
case FormatIn.Logfmt => LogfmtLogLineParser(c)
30+
new ConfigInitImpl().initConfig(c).flatMap { updatedConfig =>
31+
IO {
32+
val jsonPrefixPostfix = JsonPrefixPostfix(JsonDetector())
33+
val logLineParser = updatedConfig.formatIn match {
34+
case Some(FormatIn.Logfmt) => LogfmtLogLineParser(updatedConfig)
35+
case _ => JsonLogLineParser(updatedConfig, jsonPrefixPostfix)
36+
}
2737

28-
stdinLinesStream
29-
.through(LogViewerStream.stream[IO](c, logLineParser))
30-
.through(text.utf8.encode)
31-
.through(io.stdout)
32-
.compile
33-
.drain
34-
.as(ExitCode.Success)
38+
stdinLinesStream
39+
.through(LogViewerStream.stream[IO](updatedConfig, logLineParser))
40+
.through(text.utf8.encode)
41+
.through(io.stdout)
42+
.compile
43+
.drain
44+
.as(ExitCode.Success)
45+
}.flatten
46+
}
3547
}

json-log-viewer/shared/src/main/scala/ru/d10xa/jsonlogviewer/ColorLineFormatter.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ru.d10xa.jsonlogviewer
33
import fansi.ErrorMode.Strip
44
import fansi.EscapeAttr
55
import fansi.Str
6+
import ru.d10xa.jsonlogviewer.decline.Config
67

78
class ColorLineFormatter(c: Config) extends OutputLineFormatter:
89
private val strEmpty: Str = Str("")

0 commit comments

Comments
 (0)