Add a debug flag and make debug message hidden by default (#60)

* [cli] add a debug flag to control logging

* [core] show entering a directory as a debug message
This commit is contained in:
Paul Campbell 2019-06-14 20:00:22 +01:00 committed by GitHub
parent a780c5fdfe
commit e3675b5394
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 49 additions and 10 deletions

View file

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [[https://keepachangelog.com/en/1.0.0/][Keep a Changelog]], and this project adheres to The format is based on [[https://keepachangelog.com/en/1.0.0/][Keep a Changelog]], and this project adheres to
[[https://semver.org/spec/v2.0.0.html][Semantic Versioning]]. [[https://semver.org/spec/v2.0.0.html][Semantic Versioning]].
* [0.5.0] - ????-??-??
** Added
- ~-d~, ~--debug~ flag for log messages
* [0.4.0] - 2019-06-11 * [0.4.0] - 2019-06-11
** Added ** Added

View file

@ -21,6 +21,7 @@ hash of the file contents.
-p, --prefix <value> Prefix within the S3 Bucket -p, --prefix <value> Prefix within the S3 Bucket
-i, --include <value> Include matching paths -i, --include <value> Include matching paths
-x, --exclude <value> Exclude matching paths -x, --exclude <value> Exclude matching paths
-d, --debug Enable debug logging
-v, --verbose <value> Verbosity level (1-5) -v, --verbose <value> Verbosity level (1-5)
#+end_example #+end_example

View file

@ -12,14 +12,14 @@ object Main extends IOApp {
Config(source = Paths.get(".").toFile) Config(source = Paths.get(".").toFile)
override def run(args: List[String]): IO[ExitCode] = { override def run(args: List[String]): IO[ExitCode] = {
val logger = new PrintLogger[IO](1) val exitCaseLogger = new PrintLogger[IO](1, false)
ParseArgs(args, defaultConfig) ParseArgs(args, defaultConfig)
.map(Program[IO]) .map(Program[IO])
.getOrElse(IO(ExitCode.Error)) .getOrElse(IO(ExitCode.Error))
.guaranteeCase { .guaranteeCase {
case Canceled => logger.warn("Interrupted") case Canceled => exitCaseLogger.warn("Interrupted")
case Error(e) => logger.error(e.getMessage) case Error(e) => exitCaseLogger.error(e.getMessage)
case Completed => logger.info("Done") case Completed => exitCaseLogger.info("Done")
} }
} }

View file

@ -35,6 +35,9 @@ object ParseArgs {
.unbounded() .unbounded()
.action((str,c) => c.copy(filters = c.filters ++ str.map(Exclude))) .action((str,c) => c.copy(filters = c.filters ++ str.map(Exclude)))
.text("Exclude matching paths"), .text("Exclude matching paths"),
opt[Unit]('d', "debug")
.action((_, c) => c.copy(debug = true))
.text("Enable debug logging"),
opt[Int]('v', "verbose") opt[Int]('v', "verbose")
.validate(i => .validate(i =>
if (i >= 1 && i <= 5) Right(Unit) if (i >= 1 && i <= 5) Right(Unit)

View file

@ -3,9 +3,11 @@ package net.kemitix.s3thorp.cli
import cats.Monad import cats.Monad
import net.kemitix.s3thorp.domain.Logger import net.kemitix.s3thorp.domain.Logger
class PrintLogger[M[_]: Monad](verbosity: Int) extends Logger[M] { class PrintLogger[M[_]: Monad](verbosity: Int, isDebug: Boolean) extends Logger[M] {
override def debug(message: => String): M[Unit] = Monad[M].pure(println(s"[ DEBUG] $message")) override def debug(message: => String): M[Unit] =
if (isDebug) Monad[M].pure(println(s"[ DEBUG] $message"))
else Monad[M].unit
override def info(message: => String): M[Unit] = Monad[M].pure(println(s"[ INFO] $message")) override def info(message: => String): M[Unit] = Monad[M].pure(println(s"[ INFO] $message"))

View file

@ -10,7 +10,7 @@ import net.kemitix.s3thorp.domain.{Config, Logger}
object Program { object Program {
def apply[M[_]: Monad](config: Config): M[ExitCode] = { def apply[M[_]: Monad](config: Config): M[ExitCode] = {
implicit val logger: Logger[M] = new PrintLogger[M](config.verbose) implicit val logger: Logger[M] = new PrintLogger[M](config.verbose, config.debug)
for { for {
_ <- logger.info("S3Thorp - hashed sync for s3") _ <- logger.info("S3Thorp - hashed sync for s3")
_ <- Sync.run[M](config, S3ClientBuilder.defaultClient) _ <- Sync.run[M](config, S3ClientBuilder.defaultClient)

View file

@ -12,9 +12,8 @@ class ParseArgsTest extends FunSpec {
val defaultConfig: Config = Config(source = source) val defaultConfig: Config = Config(source = source)
describe("parse - source") { describe("parse - source") {
def invokeWithSource(path: String) = { def invokeWithSource(path: String) =
ParseArgs(List("--source", path, "--bucket", "bucket"), defaultConfig) ParseArgs(List("--source", path, "--bucket", "bucket"), defaultConfig)
}
describe("when source is a directory") { describe("when source is a directory") {
val result = invokeWithSource(pathTo(".")) val result = invokeWithSource(pathTo("."))
@ -45,6 +44,33 @@ class ParseArgsTest extends FunSpec {
} }
} }
describe("parse - debug") {
def invokeWithDebug(debug: String) = {
val strings = List("--source", pathTo("."), "--bucket", "bucket", debug)
.filter(_ != "")
ParseArgs(strings, defaultConfig).map(_.debug)
}
describe("when no debug flag") {
val debugFlag = invokeWithDebug("")
it("debug should be false") {
assert(debugFlag.contains(false))
}
}
describe("when long debug flag") {
val debugFlag = invokeWithDebug("--debug")
it("debug should be true") {
assert(debugFlag.contains(true))
}
}
describe("when short debug flag") {
val debugFlag = invokeWithDebug("-d")
it("debug should be true") {
assert(debugFlag.contains(true))
}
}
}
private def pathTo(value: String): String = private def pathTo(value: String): String =
Try(Resource(this, value)) Try(Resource(this, value))
.map(_.getCanonicalPath) .map(_.getCanonicalPath)

View file

@ -41,7 +41,7 @@ object LocalFileStream {
.flatMap(lfs => acc.map(s => s ++ lfs))) .flatMap(lfs => acc.map(s => s ++ lfs)))
for { for {
_ <- logger.info(s"- Entering: $file") _ <- logger.debug(s"- Entering: $file")
fs <- dirPaths(file) fs <- dirPaths(file)
lfs <- recurse(fs) lfs <- recurse(fs)
_ <- logger.debug(s"- Leaving : $file") _ <- logger.debug(s"- Leaving : $file")

View file

@ -9,6 +9,7 @@ final case class Config(
filters: List[Filter] = List(), filters: List[Filter] = List(),
multiPartThreshold: Long = 1024 * 1024 * 5, multiPartThreshold: Long = 1024 * 1024 * 5,
maxRetries: Int = 3, maxRetries: Int = 3,
debug: Boolean = false,
source: File source: File
) { ) {
require(source.isDirectory, s"Source must be a directory: $source") require(source.isDirectory, s"Source must be a directory: $source")