This is an automated email from the ASF dual-hosted git repository.
aradzinski pushed a commit to branch NLPCRAFT-170
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/NLPCRAFT-170 by this push:
new 97034e0 WIP.
97034e0 is described below
commit 97034e0fe424e9716af658ff604a5983f03ebf97
Author: Aaron Radzinski <[email protected]>
AuthorDate: Sat Dec 5 19:18:48 2020 -0800
WIP.
---
.../nlpcraft/model/tools/cmdline/NCCli.scala | 208 +++++++++++++++++----
.../model/tools/cmdline/NCCliProbeBeacon.scala | 6 +-
2 files changed, 181 insertions(+), 33 deletions(-)
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
index 7667f10..5628b98 100644
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
@@ -76,14 +76,16 @@ object NCCli extends App {
private final val CMD_NAME = Pattern.compile("(^\\s*[\\w-]+)(\\s)")
private final val CMD_PARAM = Pattern.compile("(\\s)(--?[\\w-]+)")
- // Number of server services that need to be started + 1 progress start.
+ // Number of server and probe services that need to be started + 1
progress start.
// Used for progress bar functionality.
// +==================================================================+
// | MAKE SURE TO UPDATE THIS VAR WHEN NUMBER OF SERVICES IS CHANGED. |
// +==================================================================+
private final val NUM_SRV_SERVICES = 30 /*services*/ + 1 /*progress start*/
+ private final val NUM_PRB_SERVICES = 21 /*services*/ + 1 /*progress start*/
private final val SRV_BEACON_PATH = ".nlpcraft/server_beacon"
+ private final val PRB_BEACON_PATH = ".nlpcraft/probe_beacon"
private final val HIST_PATH = ".nlpcraft/.cli_history"
private final lazy val VER = NCVersion.getCurrent
@@ -146,6 +148,9 @@ object NCCli extends App {
case class NoLocalServer()
extends IllegalStateException(s"Local REST server not found.")
+ case class NoLocalProbe()
+ extends IllegalStateException(s"Local probe not found.")
+
case class MissingParameter(cmd: Command, paramId: String)
extends IllegalArgumentException(
s"Missing mandatory parameter $C${"'" + cmd.params.find(_.id ==
paramId).get.names.head + "'"}$RST, " +
@@ -517,10 +522,29 @@ object NCCli extends App {
case class ReplState(
var isServerOnline: Boolean = false,
+ var isProbeOnline: Boolean = false,
var accessToken: Option[String] = None,
var serverLog: Option[File] = None,
+ var probeLog: Option[File] = None,
var probes: List[Probe] = Nil // List of connected probes.
- )
+ ) {
+ /**
+ * Resets server sub-state.
+ */
+ def resetServer(): Unit = {
+ isServerOnline = false
+ serverLog = None
+ probes = Nil
+ }
+
+ /**
+ * Resets probe sub-state.
+ */
+ def resetProbe(): Unit = {
+ isProbeOnline = false
+ probeLog = None
+ }
+ }
@volatile private var state = ReplState()
@@ -1007,7 +1031,7 @@ object NCCli extends App {
),
Command(
name = "tail-server",
- group = "1. Server Commands",
+ group = "1. Server & Probe Commands",
synopsis = s"Shows last N lines from the local REST server log.",
desc = Some(
s"Only works for the server started via this script."
@@ -1030,8 +1054,32 @@ object NCCli extends App {
)
),
Command(
+ name = "tail-probe",
+ group = "1. Server & Probe Commands",
+ synopsis = s"Shows last N lines from the local probe log.",
+ desc = Some(
+ s"Only works for the probe started via this script."
+ ),
+ body = cmdTailProbe,
+ params = Seq(
+ Parameter(
+ id = "lines",
+ names = Seq("--lines", "-l"),
+ value = Some("num"),
+ desc =
+ s"Number of the probe log lines from the end to
display. Default is 20."
+ )
+ ),
+ examples = Seq(
+ Example(
+ usage = Seq(s"$PROMPT $SCRIPT_NAME tail-probe --lines=20
"),
+ desc = s"Prints last 20 lines from the local probe log."
+ )
+ )
+ ),
+ Command(
name = "start-server",
- group = "1. Server Commands",
+ group = "1. Server & Probe Commands",
synopsis = s"Starts local REST server.",
desc = Some(
s"REST server is started in the external JVM process with both
stdout and stderr piped out into log file. " +
@@ -1083,7 +1131,7 @@ object NCCli extends App {
),
Command(
name = "restart-server",
- group = "1. Server Commands",
+ group = "1. Server & Probe Commands",
synopsis = s"Restarts local REST server.",
desc = Some(
s"This command is equivalent to executing
${y("'stop-server'")} and then ${y("'start-server'")} commands with " +
@@ -1135,7 +1183,7 @@ object NCCli extends App {
),
Command(
name = "info-server",
- group = "1. Server Commands",
+ group = "1. Server & Probe Commands",
synopsis = s"Info about local REST server.",
body = cmdInfoServer
),
@@ -1177,7 +1225,7 @@ object NCCli extends App {
),
Command(
name = "ping-server",
- group = "1. Server Commands",
+ group = "1. Server & Probe Commands",
synopsis = s"Pings local REST server.",
desc = Some(
s"REST server is pinged using ${y("'/health'")} REST call to
check its online status."
@@ -1204,7 +1252,7 @@ object NCCli extends App {
),
Command(
name = "stop-server",
- group = "1. Server Commands",
+ group = "1. Server & Probe Commands",
synopsis = s"Stops local REST server.",
desc = Some(
s"Local REST server must be started via
${y(s"'$SCRIPT_NAME''")} or other compatible way."
@@ -1413,6 +1461,8 @@ object NCCli extends App {
private final val SUGSYN_CMD = CMDS.find(_.name == "sugsyn").get
private final val STOP_SRV_CMD = CMDS.find(_.name == "stop-server").get
private final val START_SRV_CMD = CMDS.find(_.name == "start-server").get
+ private final val STOP_PRB_CMD = CMDS.find(_.name == "stop-probe").get
+ private final val START_PRB_CMD = CMDS.find(_.name == "start-probe").get
/**
*
@@ -1653,6 +1703,34 @@ object NCCli extends App {
}
/**
+ *
+ * @param path
+ * @param lines
+ */
+ private def tailFile(path: String, lines: Int): Unit =
+ try
+ managed(new ReversedLinesFileReader(new File(path),
StandardCharsets.UTF_8)) acquireAndGet { in ⇒
+ var tail = List.empty[String]
+
+ breakable {
+ for (_ ← 0 until lines)
+ in.readLine() match {
+ case null ⇒ break
+ case line ⇒ tail ::= line
+ }
+ }
+
+ val cnt = tail.size
+
+ logln(bb(w(s"+----< ${K}Last $cnt log lines $W>---")))
+ tail.foreach(line ⇒ logln(s"${bb(w("| "))} $line"))
+ logln(bb(w(s"+----< ${K}Last $cnt log lines $W>---")))
+ }
+ catch {
+ case e: Exception ⇒ error(s"Failed to read log file:
${e.getLocalizedMessage}")
+ }
+
+ /**
* @param cmd Command descriptor.
* @param args Arguments, if any, for this command.
* @param repl Whether or not executing from REPL.
@@ -1673,30 +1751,34 @@ object NCCli extends App {
throw InvalidParameter(cmd, "lines")
loadServerBeacon() match {
- case Some(beacon) ⇒
- try
- managed(new ReversedLinesFileReader(new
File(beacon.logPath), StandardCharsets.UTF_8)) acquireAndGet { in ⇒
- var tail = List.empty[String]
-
- breakable {
- for (_ ← 0 until lines)
- in.readLine() match {
- case null ⇒ break
- case line ⇒ tail ::= line
- }
- }
-
- val cnt = tail.size
+ case Some(beacon) ⇒ tailFile(beacon.logPath, lines)
+ case None ⇒ throw NoLocalServer()
+ }
+ }
- logln(bb(w(s"+----< ${K}Last $cnt server log lines
$W>---")))
- tail.foreach(line ⇒ logln(s"${bb(w("| "))} $line"))
- logln(bb(w(s"+----< ${K}Last $cnt server log lines
$W>---")))
- }
+ /**
+ * @param cmd Command descriptor.
+ * @param args Arguments, if any, for this command.
+ * @param repl Whether or not executing from REPL.
+ */
+ private def cmdTailProbe(cmd: Command, args: Seq[Argument], repl:
Boolean): Unit = {
+ val lines = args.find(_.parameter.id == "lines") match {
+ case Some(arg) ⇒
+ try
+ Integer.parseInt(arg.value.get)
catch {
- case e: Exception ⇒ error(s"Failed to read log file:
${e.getLocalizedMessage}")
+ case _: Exception ⇒ throw InvalidParameter(cmd, "lines")
}
- case None ⇒ throw NoLocalServer()
+ case None ⇒ 20 // Default.
+ }
+
+ if (lines <= 0)
+ throw InvalidParameter(cmd, "lines")
+
+ loadProbeBeacon() match {
+ case Some(beacon) ⇒ tailFile(beacon.logPath, lines)
+ case None ⇒ throw NoLocalProbe()
}
}
@@ -1824,9 +1906,9 @@ object NCCli extends App {
case Some(beacon) ⇒
state.isServerOnline = true
- val baseUrl = "http://" + beacon.restEndpoint
-
try {
+ val baseUrl = "http://" + beacon.restEndpoint
+
// Attempt to signin with the default account.
if (autoSignIn && state.accessToken.isEmpty)
httpPostResponseJson(
@@ -1853,12 +1935,74 @@ object NCCli extends App {
catch {
case _: Exception ⇒
// Reset REPL state.
- state = ReplState()
+ state.resetServer()
}
case None ⇒
// Reset REPL state.
- state = ReplState()
+ state.resetServer()
+ }
+
+ beaconOpt
+ }
+
+ /**
+ * Loads and returns probe beacon file.
+ *
+ * @return
+ */
+ private def loadProbeBeacon(): Option[NCCliProbeBeacon] = {
+ val beaconOpt = try {
+ val beacon = (
+ managed(
+ new ObjectInputStream(
+ new FileInputStream(
+ new File(SystemUtils.getUserHome, PRB_BEACON_PATH)
+ )
+ )
+ ) acquireAndGet {
+ _.readObject()
+ }
+ )
+ .asInstanceOf[NCCliProbeBeacon]
+
+ ProcessHandle.of(beacon.pid).asScala match {
+ case Some(ph) ⇒
+ beacon.ph = ph
+
+ // See if we can detect probe log if server was started by
this script.
+ val files = new File(SystemUtils.getUserHome,
".nlpcraft").listFiles(new FilenameFilter {
+ override def accept(dir: File, name: String): Boolean =
+ name.startsWith(s".pid_$ph")
+ })
+
+ if (files.size == 1) {
+ val split = files(0).getName.split("_")
+
+ if (split.size == 4) {
+ val logFile = new File(SystemUtils.getUserHome,
s".nlpcraft/probe_log_${split(3)}.txt")
+
+ if (logFile.exists())
+ beacon.logPath = logFile.getAbsolutePath
+ }
+ }
+
+ Some(beacon)
+
+ case None ⇒
+ // Attempt to clean up stale beacon file.
+ new File(SystemUtils.getUserHome, PRB_BEACON_PATH).delete()
+
+ None
+ }
+ }
+ catch {
+ case _: Exception ⇒ None
+ }
+
+ beaconOpt match {
+ case Some(_) ⇒ state.isProbeOnline = true
+ case None ⇒ state.resetProbe()
}
beaconOpt
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliProbeBeacon.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliProbeBeacon.scala
index 8730016..73e0df8 100644
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliProbeBeacon.scala
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCliProbeBeacon.scala
@@ -26,6 +26,8 @@ package org.apache.nlpcraft.model.tools.cmdline
* @param downLink
* @param jarsFolder
* @param models
+ * @param logPath
+ * @param ph
*/
case class NCCliProbeBeacon (
pid: Long,
@@ -34,5 +36,7 @@ case class NCCliProbeBeacon (
upLink: String,
downLink: String,
jarsFolder: String,
- models: String
+ models: String,
+ @transient var logPath: String = null,
+ @transient var ph: ProcessHandle = null
)