Skip to content

Commit dbd2d34

Browse files
authored
Add commands (#19)
* Add commands
1 parent c3dd287 commit dbd2d34

File tree

10 files changed

+108
-8
lines changed

10 files changed

+108
-8
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package ru.d10xa.jsonlogviewer.shell
2+
3+
import cats.effect.*
4+
import fs2.*
5+
6+
import java.io.*
7+
8+
class ShellImpl extends Shell {
9+
10+
def mergeCommands(commands: List[String]): Stream[IO, String] = Stream.empty
11+
12+
}

json-log-viewer/jvm/src/main/scala/ru/d10xa/jsonlogviewer/decline/ConfigInitImpl.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ class ConfigInitImpl extends ConfigInit {
4747
c.copy(
4848
filter = c.filter.orElse(config.filter),
4949
formatIn =
50-
c.formatIn.orElse(config.formatIn).orElse(Some(FormatIn.Json))
50+
c.formatIn.orElse(config.formatIn).orElse(Some(FormatIn.Json)),
51+
configYaml = Some(config)
5152
)
5253
case None => c
5354
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package ru.d10xa.jsonlogviewer.shell
2+
3+
import cats.effect.*
4+
import fs2.*
5+
6+
import java.io.*
7+
8+
class ShellImpl extends Shell {
9+
10+
def createProcess(command: String): Resource[IO, Process] =
11+
Resource.make(IO {
12+
new ProcessBuilder("sh", "-c", command)
13+
.redirectErrorStream(true)
14+
.start()
15+
})(process => IO(process.destroy()).void)
16+
17+
def runInfiniteCommand(command: String): Stream[IO, String] =
18+
Stream.resource(createProcess(command)).flatMap { process =>
19+
fs2.io
20+
.readInputStream(
21+
IO(process.getInputStream),
22+
4096,
23+
closeAfterUse = false
24+
)
25+
.through(text.utf8.decode)
26+
.through(text.lines)
27+
.onFinalize(IO {
28+
process.waitFor()
29+
}.void)
30+
}
31+
32+
def mergeCommands(commands: List[String]): Stream[IO, String] = {
33+
val streams = commands.map(runInfiniteCommand)
34+
Stream.emits(streams).parJoin(math.max(1, commands.length))
35+
}
36+
37+
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import cats.syntax.all.*
1515
import ru.d10xa.jsonlogviewer.decline.ConfigInit
1616
import ru.d10xa.jsonlogviewer.decline.ConfigInitImpl
1717
import ru.d10xa.jsonlogviewer.decline.ConfigYaml
18+
import ru.d10xa.jsonlogviewer.shell.ShellImpl
1819

1920
object Application
2021
extends CommandIOApp(
@@ -37,8 +38,14 @@ object Application
3738
case Some(FormatIn.Logfmt) => LogfmtLogLineParser(updatedConfig)
3839
case _ => JsonLogLineParser(updatedConfig, jsonPrefixPostfix)
3940
}
40-
41-
stdinLinesStream
41+
val commandsOpt = updatedConfig.configYaml.flatMap(_.commands).filter(_.nonEmpty)
42+
val stream = commandsOpt match {
43+
case Some(cmds) if cmds.nonEmpty =>
44+
new ShellImpl().mergeCommands(cmds)
45+
case _ =>
46+
stdinLinesStream
47+
}
48+
stream
4249
.through(LogViewerStream.stream[IO](updatedConfig, logLineParser))
4350
.through(text.utf8.encode)
4451
.through(io.stdout)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import scala.util.matching.Regex
1010

1111
final case class Config(
1212
configFile: Option[ConfigFile],
13+
configYaml: Option[ConfigYaml],
1314
timestamp: TimestampConfig,
1415
grep: List[ConfigGrep],
1516
filter: Option[QueryAST],

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@ import ru.d10xa.jsonlogviewer.query.QueryAST
44

55
case class ConfigYaml(
66
filter: Option[QueryAST],
7-
formatIn: Option[Config.FormatIn]
7+
formatIn: Option[Config.FormatIn],
8+
commands: Option[List[String]]
89
)
10+
11+
object ConfigYaml:
12+
val empty: ConfigYaml = ConfigYaml(None, None, None)

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ object ConfigYamlLoader {
1616
.mkString("\n")
1717
.trim
1818
if (uncommentedContent.isEmpty) {
19-
Validated.valid(ConfigYaml(None, None))
19+
Validated.valid(ConfigYaml.empty)
2020
} else {
2121
parser.parse(content) match {
2222
case Left(error) =>
@@ -61,8 +61,20 @@ object ConfigYamlLoader {
6161
}
6262
case None => Validated.valid(None)
6363
}
64+
val commandsValidated: ValidatedNel[String, Option[List[String]]] =
65+
fields.get("commands") match {
66+
case Some(jsonValue) =>
67+
jsonValue.as[List[String]] match {
68+
case Left(_) =>
69+
Validated.invalidNel("Invalid 'commands' field format")
70+
case Right(cmds) =>
71+
Validated.valid(Some(cmds))
72+
}
73+
case None => Validated.valid(None)
74+
}
6475

65-
(filterValidated, formatInValidated).mapN(ConfigYaml.apply)
76+
(filterValidated, formatInValidated, commandsValidated)
77+
.mapN(ConfigYaml.apply)
6678
}
6779
}
6880
}

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ object DeclineOpts {
4747
.option[String]("format-in", help = "json, logfmt")
4848
.mapValidated(FormatInValidator.toValidatedFormatIn)
4949
.orNone
50-
50+
5151
val formatOut: Opts[Option[FormatOut]] = Opts
5252
.option[String]("format-out", help = "pretty, raw")
5353
.mapValidated(FormatOutValidator.toValidatedFormatOut)
@@ -64,7 +64,25 @@ object DeclineOpts {
6464

6565
val config: Opts[Config] =
6666
(configFile, timestampConfig, grepConfig, filterConfig, formatIn, formatOut)
67-
.mapN(Config.apply)
67+
.mapN {
68+
case (
69+
configFile,
70+
timestampConfig,
71+
grepConfig,
72+
filterConfig,
73+
formatIn,
74+
formatOut
75+
) =>
76+
Config(
77+
configFile = configFile,
78+
configYaml = None,
79+
timestamp = timestampConfig,
80+
grep = grepConfig,
81+
filter = filterConfig,
82+
formatIn = formatIn,
83+
formatOut = formatOut
84+
)
85+
}
6886

6987
val command: Command[Config] = Command(
7088
name = "json-log-viewer",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package ru.d10xa.jsonlogviewer.shell
2+
import fs2.*
3+
import cats.effect.*
4+
5+
trait Shell {
6+
def mergeCommands(commands: List[String]): Stream[IO, String]
7+
}

json-log-viewer/shared/src/test/scala/ru/d10xa/jsonlogviewer/query/LogLineQueryPredicateImplTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class LogLineQueryPredicateImplTest extends munit.FunSuite {
8383

8484
private val config: Config = Config(
8585
configFile = None,
86+
configYaml = None,
8687
timestamp = TimestampConfig(
8788
fieldName = "@timestamp",
8889
None,

0 commit comments

Comments
 (0)