Skip to content

Commit

Permalink
Merge pull request #7 from jpbnetley/feature/logging
Browse files Browse the repository at this point in the history
Feature/logging
  • Loading branch information
jpbnetley authored Jan 25, 2020
2 parents 174188d + 5d477f5 commit c0d6b51
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 15 deletions.
8 changes: 5 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ name := "Mongo-csv-importer"
version := "0.1"

libraryDependencies ++= Seq(
"org.mongodb.scala" %% "mongo-scala-driver" % "2.8.0",
"io.monix" %% "monix" % "3.1.0",
"org.typelevel" %% "cats-core" % "2.1.0"
"org.mongodb.scala" %% "mongo-scala-driver" % "2.8.0",
"io.monix" %% "monix" % "3.1.0",
"org.typelevel" %% "cats-core" % "2.1.0",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"
)

scalaVersion := "2.13.1"
11 changes: 11 additions & 0 deletions src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d %green([%thread]) %highlight(%level) %logger{50} - %msg%n</pattern>
</layout>
</appender>
<logger name="com.base22" level="TRACE"/>
<root level="error">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
10 changes: 7 additions & 3 deletions src/main/scala/Util/DataBuilder/DataBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package Util.DataBuilder
import org.bson.Document
import cats.implicits._
import monix.eval.Task
import Util.Logging.log


object DataBuilder {
Expand All @@ -13,17 +14,19 @@ object DataBuilder {
* @return bsonDocument as String
*/
def buildMongoDocuments(headers: Option[List[String]], lineItems: List[String]): Task[Either[Exception, List[Document]]] = Task {
log.debug("finding headers")
val header = Either.fromOption(headers, new Exception("No Headers found for csv"))
header.map(headers => buildJsonObject(headers, lineItems))
}

/** Checks of the line items are the same length as the headers, otherwise adds NULL for the missing headers
*
* @param lineRow the single line item that is comma separated (csv)
* @param maxIndex
* @param maxIndex the max index for the line items
* @return Csv with null for empty items
*/
def handleShortColumnHeader(lineRow: String, maxIndex: Int): List[String] = {
@scala.annotation.tailrec
def loopOverCsvString(acc: List[String], currentIndex: Int, maxIndex: Int): List[String] = {
if(currentIndex == maxIndex)
acc
Expand Down Expand Up @@ -53,7 +56,7 @@ object DataBuilder {

/** Parses json with no Nulls
*
* @param currentIndex
* @param currentIndex position of the parser
* @param headerText for each object
* @param item value for the header text
* @param maxIndex max length of the csv file
Expand All @@ -79,7 +82,7 @@ object DataBuilder {

/** Parses json with that contains a Null
*
* @param currentIndex
* @param currentIndex value for the parser
* @param headerText for each object
* @param item value for the header text
* @param maxIndex max length of the csv file
Expand All @@ -105,6 +108,7 @@ object DataBuilder {
* @return List[Document]
*/
def buildJsonObject(headerValue: List[String], lineItems: List[String]): List[Document] = {
log.debug("Parsing json")
val maxHeaderIndex = headerValue.length - 1
val jsonObjects = lineItems.map { line =>
val nonEmptyCsvLine = handleShortColumnHeader(line, maxHeaderIndex)
Expand Down
4 changes: 3 additions & 1 deletion src/main/scala/Util/DataBuilder/Processing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.bson.Document
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.reflect.io.File
import Util.Logging.log

object Processing {

Expand All @@ -30,7 +31,7 @@ object Processing {
lineItems = fileLines.drop(1)
collectionName = file.name.replace(".csv", "").toLowerCase
documentResult <- EitherT(buildMongoDocuments(headers, lineItems))
db <- EitherT.right[Exception](database.getDatabase())
db <- EitherT.right[Exception](database.getDatabase)
dbInsert <- EitherT.rightT[Task, Exception](db.getCollection[Document](collectionName).insertMany(documentResult))
} yield {
println(s"Inserting into db: $dbInsert")
Expand All @@ -39,6 +40,7 @@ object Processing {
}).value
}.map { result =>
val (errors, _) = result.separate
log.error(errors.headOption.fold("No error found")(_.getMessage))
errors.headOption.toLeft(())
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/Util/Database/Database.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ case object Database {
*
* @return
*/
def getDatabase: Task[MongoDatabase] = Task {
database
}
def getDatabase: Task[MongoDatabase] = Task(database)

/** Closes the mongo connection
*
Expand Down
22 changes: 19 additions & 3 deletions src/main/scala/Util/File/FileHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import monix.eval.Task

import scala.io.Source
import scala.reflect.io.{Directory, File, Path}
import Util.Logging.log

object FileHelper {
/** Gets csv files
Expand All @@ -15,11 +16,13 @@ object FileHelper {
* @return
*/
def getCsvFiles(dir: Directory, skipFiles: List[File] = List.empty[File]): Task[Either[Exception, List[File]]] = {
log.debug("Skipping files that are not csv items")
Task {
val okFileExtensions = List("csv")
Right(dir.files.filter(file => okFileExtensions.contains(file.extension)).toList)
}.onErrorHandle { e =>
val message = s"Could not read files from path: ${e.getMessage}"
log.error(message, e)
Left(new Exception(message))
}
}
Expand All @@ -30,11 +33,16 @@ object FileHelper {
* @return line items
*/
def extractCsvFileLines(file: File): Task[Either[Exception, List[String]]] = Task{

try {
log.debug("Reading in file")
val reader = Source.fromFile(file.toURI, StandardCharsets.ISO_8859_1.name())
Right(reader.getLines().toList)
} catch {
case e: Exception => Left(new Exception("Failed to extract csv files: "+ e.getMessage, e))
case e: Exception =>
val message = "Failed to extract csv files: "+ e.getMessage
log.error(message)
Left(new Exception(message, e))
}
}

Expand All @@ -45,7 +53,12 @@ object FileHelper {
* @return optional found file
*/
def findFile(dir: Directory, fileName: String): Task[Either[Exception, File]] = Task {
Either.fromOption(dir.files.toList.find(_.name == fileName), new Exception("File not found: "+ fileName))
log.debug("Finding file by name")
Either.fromOption(dir.files.toList.find(_.name == fileName), {
val error = new Exception("File not found: " + fileName)
log.error(error.getMessage)
error
})
}

/** Casts a string to a url
Expand All @@ -55,10 +68,13 @@ object FileHelper {
*/
def toDirectory(dir: String): Either[Exception, Directory] = {
try{
log.debug("Build directory from path string")
val directory = File(Path(dir))
Right(Directory(directory))
} catch {
case e: Exception => Left(new Exception(s"Could not convert to Directory $dir", e))
case e: Exception =>
val error = new Exception(s"Could not convert to Directory $dir", e)
Left(error)
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/scala/Util/Logging.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package Util

import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory

object Logging {
val log: Logger = Logger(LoggerFactory.getLogger("Mongo csv importer"))
}
11 changes: 9 additions & 2 deletions src/main/scala/Util/UserPrompt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Util.Models.UserInput
import cats.data.EitherT
import cats.implicits._
import monix.eval.Task
import Util.Logging.log

object UserPrompt {

Expand All @@ -14,6 +15,7 @@ object UserPrompt {
*/
def promptUser(): Task[Either[Exception, UserInput]] = {
try {
log.debug("Prompting user for input...")
println("Please enter the path to the csv files: ")
(for {
directory <- EitherT.fromEither[Task](FileHelper.toDirectory(scala.io.StdIn.readLine()))
Expand All @@ -28,24 +30,29 @@ object UserPrompt {
} catch {
case e: Exception =>
val message = s"Could not read user input: ${e.getMessage}"
log.error(message)
Task.now(Left(new Exception(message)))
}
}

/** Prompts the user to add files to skip
*
* @param inputItems
* @param inputItems the items that will skipped
* @return skipped items list
*/
def addSkipItems(inputItems: List[String]): Either[Exception, List[String]] = {
try {
log.debug("Prompting user to enter files to skip")
println("Please enter any files to skip (enter :q to exit) eg. filename.extension: ")
val input = scala.io.StdIn.readLine()
if (input.equals(":q"))
Right(inputItems)
else addSkipItems(inputItems :+ input)
} catch {
case e: Exception => Left(new Exception("Could not read user input: "+e.getMessage, e))
case e: Exception =>
val message = "Could not read user input: "+e.getMessage
log.error(message)
Left(new Exception(message, e))
}
}

Expand Down

0 comments on commit c0d6b51

Please sign in to comment.