Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

43 time range filter #260

Merged
merged 12 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ logfiles/
.idea/
**/.flattened-pom.xml
/develop-logging.properties
/target/
4 changes: 1 addition & 3 deletions app/src/main/scala/app/logorrr/conf/LogoRRRGlobals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ object LogoRRRGlobals extends CanLog {

private val hostServicesProperty = new SimpleObjectProperty[LogoRRRHostServices]()

def persist(): Unit = {
persist(LogoRRRGlobals.getSettings)
}
def persist(): Unit = persist(LogoRRRGlobals.getSettings)

def persist(settings: Settings): Unit = {
Fs.write(FilePaths.settingsFilePath, ConfigWriter[Settings].to(settings).render(renderOptions))
Expand Down
96 changes: 81 additions & 15 deletions app/src/main/scala/app/logorrr/conf/mut/MutLogFileSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package app.logorrr.conf.mut

import app.logorrr.conf.BlockSettings
import app.logorrr.io.FileId
import app.logorrr.model.{LogEntryInstantFormat, LogFileSettings}
import app.logorrr.model.{LogEntry, LogFileSettings, TimestampSettings}
import app.logorrr.util.LogoRRRFonts
import app.logorrr.views.search.Filter
import app.logorrr.views.search.{AnyFilter, Filter, FilterButton, Fltr}
import javafx.beans.binding.{BooleanBinding, StringBinding}
import javafx.beans.property._
import javafx.collections.FXCollections
import javafx.collections.transformation.FilteredList
import javafx.collections.{FXCollections, ObservableList}

import java.time.format.DateTimeFormatter
import scala.jdk.CollectionConverters._

object MutLogFileSettings {
Expand All @@ -22,37 +24,95 @@ object MutLogFileSettings {
s.firstOpenedProperty.set(logFileSettings.firstOpened)
s.setDividerPosition(logFileSettings.dividerPosition)
s.setFilters(logFileSettings.filters)
s.someLogEntrySettingsProperty.set(logFileSettings.someLogEntryInstantFormat)
s.someTimestampSettings.set(logFileSettings.someTimestampSettings)
logFileSettings.someTimestampSettings match {
case Some(sts) => s.setDateTimeFormatter(sts.dateTimeFormatter)
case None =>
}
s.setAutoScroll(logFileSettings.autoScroll)
s.setLowerTimestamp(logFileSettings.lowerTimestamp)
s.setUpperTimestamp(logFileSettings.upperTimestamp)
s
}
}


class MutLogFileSettings {

var someUnclassifiedFilter: Option[(Filter, FilterButton)] = None
var filterButtons: Map[Filter, FilterButton] = Map[Filter, FilterButton]()

/**
* Filters are only active if selected.
*
* UnclassifiedFilter gets an extra handling since it depends on other filters
*
* @return
*/
def computeCurrentFilter(): Fltr = {
new AnyFilter(someUnclassifiedFilter.map(fst => if (fst._2.isSelected) Set(fst._1) else Set()).getOrElse(Set()) ++
filterButtons.filter(fst => fst._2.isSelected).keySet)
}

/**
* Reduce current displayed log entries by applying text filters and consider also the time stamp range.
*
* @param filteredList list to filter
*/
def updateActiveFilter(filteredList: FilteredList[LogEntry]): Unit = {
filteredList.setPredicate((entry: LogEntry) =>
(entry.someInstant match {
case None => true // if instant is not set, return true
case Some(value) =>
val asMilli = value.toEpochMilli
getLowTimestampBoundary <= asMilli && asMilli <= getHighTimestampBoundary
}) && computeCurrentFilter().matches(entry.value))
}


private val fileIdProperty = new SimpleObjectProperty[FileId]()
private val firstOpenedProperty = new SimpleLongProperty()
private val someTimestampSettings = new SimpleObjectProperty[Option[TimestampSettings]](None)
private val dateTimeFormatterProperty = new SimpleObjectProperty[DateTimeFormatter](TimestampSettings.DefaultFormatter)

val fontSizeProperty = new SimpleIntegerProperty()
val blockSizeProperty = new SimpleIntegerProperty()
val selectedLineNumberProperty = new SimpleIntegerProperty()
val firstVisibleTextCellIndexProperty = new SimpleIntegerProperty()
val lastVisibleTextCellIndexProperty = new SimpleIntegerProperty()
val dividerPositionProperty = new SimpleDoubleProperty()
val fontSizeProperty = new SimpleIntegerProperty()
private val lowerTimestampProperty = new SimpleLongProperty(LogFileSettings.DefaultLowerTimestamp)
private val upperTimestampProperty = new SimpleLongProperty(LogFileSettings.DefaultUpperTimestamp)

def setLowerTimestamp(lowerValue: Long): Unit = lowerTimestampProperty.set(lowerValue)

def getLowTimestampBoundary: Long = lowerTimestampProperty.get()

def setUpperTimestamp(upperValue: Long): Unit = upperTimestampProperty.set(upperValue)

def getHighTimestampBoundary: Long = upperTimestampProperty.get()

val dividerPositionProperty = new SimpleDoubleProperty()
val autoScrollActiveProperty = new SimpleBooleanProperty()
val filtersProperty = new SimpleListProperty[Filter](FXCollections.observableArrayList())
val someLogEntrySettingsProperty = new SimpleObjectProperty[Option[LogEntryInstantFormat]](None)
val blockSizeProperty = new SimpleIntegerProperty()

def getSomeTimestampSettings: Option[TimestampSettings] = someTimestampSettings.get()

def getDateTimeFormatter: DateTimeFormatter = dateTimeFormatterProperty.get()

def setDateTimeFormatter(dateTimeFormatter: DateTimeFormatter): Unit = dateTimeFormatterProperty.set(dateTimeFormatter)

def setFilters(filters: Seq[Filter]): Unit = {
filtersProperty.setAll(filters.asJava)
}

def getFilters: ObservableList[Filter] = filtersProperty.get()


val hasLogEntrySettingBinding: BooleanBinding = new BooleanBinding {
bind(someLogEntrySettingsProperty)
bind(someTimestampSettings)

override def computeValue(): Boolean = {
Option(someLogEntrySettingsProperty.get()).exists(_.isDefined)
Option(someTimestampSettings.get()).exists(_.isDefined)
}
}

Expand All @@ -66,8 +126,12 @@ class MutLogFileSettings {
override def computeValue(): String = LogoRRRFonts.jetBrainsMono(fontSizeProperty.get())
}

def setLogEntryInstantFormat(lef: LogEntryInstantFormat): Unit = {
someLogEntrySettingsProperty.set(Option(lef))
def setSomeLogEntryInstantFormat(someLef: Option[TimestampSettings]): Unit = {
someTimestampSettings.set(someLef)
someLef match {
case Some(value) => setDateTimeFormatter(value.dateTimeFormatter)
case None => setDateTimeFormatter(null)
}
}

def setAutoScroll(autoScroll: Boolean): Unit = autoScrollActiveProperty.set(autoScroll)
Expand Down Expand Up @@ -101,12 +165,14 @@ class MutLogFileSettings {
, firstOpenedProperty.get()
, dividerPositionProperty.get()
, fontSizeProperty.get()
, filtersProperty.get().asScala.toSeq
, getFilters.asScala.toSeq
, BlockSettings(blockSizeProperty.get())
, someLogEntrySettingsProperty.get()
, someTimestampSettings.get()
, autoScrollActiveProperty.get()
, firstVisibleTextCellIndexProperty.get()
, lastVisibleTextCellIndexProperty.get())
, lastVisibleTextCellIndexProperty.get()
, lowerTimestampProperty.get()
, upperTimestampProperty.get())
lfs
}
}
Expand Down
30 changes: 21 additions & 9 deletions app/src/main/scala/app/logorrr/io/IoManager.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package app.logorrr.io

import app.logorrr.model.{LogEntry, LogEntryInstantFormat}
import app.logorrr.model.{LogEntry, TimestampSettings}
import app.logorrr.util.{CanLog, OsUtil}
import javafx.collections.{FXCollections, ObservableList}

import java.io._
import java.nio.file.{Files, Path}
import java.time.{Duration, Instant}
import java.util
import java.util.zip.{ZipEntry, ZipInputStream}
import scala.util.{Failure, Success, Try}
Expand Down Expand Up @@ -58,7 +59,7 @@ object IoManager extends CanLog {
val arraylist = new java.util.ArrayList[LogEntry]()
toSeq(mkReader(asBytes)).map(l => {
lineNumber = lineNumber + 1
arraylist.add(LogEntry(lineNumber, l, None))
arraylist.add(LogEntry(lineNumber, l, None, None))
})
FXCollections.observableList(arraylist)

Expand All @@ -69,22 +70,34 @@ object IoManager extends CanLog {
val arraylist = new java.util.ArrayList[LogEntry]()
fromPathUsingSecurityBookmarks(logFile).map(l => {
lineNumber = lineNumber + 1
arraylist.add(LogEntry(lineNumber, l, None))
arraylist.add(LogEntry(lineNumber, l, None, None))
})
FXCollections.observableList(arraylist)
}

def from(logFile: Path, logEntryTimeFormat: LogEntryInstantFormat): ObservableList[LogEntry] = {
def from(logFile: Path, logEntryTimeFormat: TimestampSettings): ObservableList[LogEntry] = {
var lineNumber: Int = 0
var someFirstEntryTimestamp: Option[Instant] = None
val arraylist = new util.ArrayList[LogEntry]()
fromPathUsingSecurityBookmarks(logFile).map(l => {
lineNumber = lineNumber + 1
arraylist.add(LogEntry(lineNumber, l, LogEntryInstantFormat.parseInstant(l, logEntryTimeFormat)))
val someInstant: Option[Instant] = TimestampSettings.parseInstant(l, logEntryTimeFormat)
if (someFirstEntryTimestamp.isEmpty) {
someFirstEntryTimestamp = someInstant
}

val diffFromStart: Option[Duration] = for {
firstEntry <- someFirstEntryTimestamp
instant <- someInstant
} yield Duration.between(firstEntry, instant)

// first entry
arraylist.add(LogEntry(lineNumber, l, someInstant, diffFromStart))
})
FXCollections.observableList(arraylist)
}

def readEntries(path : Path, someLogEntryInstantFormat: Option[LogEntryInstantFormat]): ObservableList[LogEntry] = {
def readEntries(path: Path, someLogEntryInstantFormat: Option[TimestampSettings]): ObservableList[LogEntry] = {
if (isPathValid(path)) {
Try(someLogEntryInstantFormat match {
case None => IoManager.from(path)
Expand All @@ -102,7 +115,7 @@ object IoManager extends CanLog {
}
}

def isPathValid(path : Path): Boolean =
def isPathValid(path: Path): Boolean =
if (OsUtil.isMac) {
Files.exists(path)
} else {
Expand Down Expand Up @@ -143,7 +156,6 @@ object IoManager extends CanLog {
}



def isZip(path : Path) : Boolean = path.getFileName.toString.endsWith(".zip")
def isZip(path: Path): Boolean = path.getFileName.toString.endsWith(".zip")

}
14 changes: 10 additions & 4 deletions app/src/main/scala/app/logorrr/model/LogEntry.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
package app.logorrr.model


import java.time.Instant
import java.time.{Duration, Instant}

/**
* represents one line in a log file
*
* @param lineNumber line number of this log entry
* @param value contens of line in plaintext
* @param lineNumber line number of this log entry
* @param value contens of line in plaintext
* @param someInstant a timestamp if there is any
* */
case class LogEntry(lineNumber: Int
, value: String
, someInstant: Option[Instant])
, someInstant: Option[Instant]
, someDurationSinceFirstInstant: Option[Duration]) {

/** returns a copy of this log entry without timestamp information */
def withOutTimestamp(): LogEntry = copy(someInstant = None, someDurationSinceFirstInstant = None)

}
46 changes: 0 additions & 46 deletions app/src/main/scala/app/logorrr/model/LogEntryInstantFormat.scala

This file was deleted.

16 changes: 11 additions & 5 deletions app/src/main/scala/app/logorrr/model/LogFileSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ object LogFileSettings {
private val DefaultSelectedIndex = 0
private val DefaultDividerPosition = 0.5
private val DefaultBlockSettings = BlockSettings(10)
private val DefaultLogFormat: Option[LogEntryInstantFormat] = None
private val DefaultLogFormat: Option[TimestampSettings] = None
private val DefaultAutoScroll = false
private val DefaultFirstViewIndex = -1
private val DefaultLastViewIndex = -1
val DefaultLowerTimestamp: Int = 0
val DefaultUpperTimestamp: Long = Instant.now().toEpochMilli
private val FinestFilter: Filter = new Filter("FINEST", Color.GREY, true)
private val InfoFilter: Filter = new Filter("INFO", Color.GREEN, true)
private val WarningFilter: Filter = new Filter("WARNING", Color.ORANGE, true)
Expand All @@ -41,7 +43,9 @@ object LogFileSettings {
, DefaultLogFormat
, DefaultAutoScroll
, DefaultFirstViewIndex
, DefaultLastViewIndex)
, DefaultLastViewIndex
, DefaultLowerTimestamp
, Instant.now().toEpochMilli)
}

}
Expand All @@ -62,7 +66,7 @@ object LogFileSettings {
* @param fontSize font size to use
* @param filters filters which should be applied
* @param blockSettings settings for the left view
* @param someLogEntryInstantFormat used timestamp format
* @param someTimestampSettings used timestamp format
* @param autoScroll true if 'follow mode' is active
* @param firstVisibleTextCellIndex which index is the first visible on the screen (depending on resolution, window size ...)
* @param lastVisibleTextCellIndex which index is the last visible on the screen (depending on resolution, window size ...)
Expand All @@ -74,10 +78,12 @@ case class LogFileSettings(fileId: FileId
, fontSize: Int
, filters: Seq[Filter]
, blockSettings: BlockSettings
, someLogEntryInstantFormat: Option[LogEntryInstantFormat]
, someTimestampSettings: Option[TimestampSettings]
, autoScroll: Boolean
, firstVisibleTextCellIndex: Int
, lastVisibleTextCellIndex: Int) {
, lastVisibleTextCellIndex: Int
, lowerTimestamp: Long
, upperTimestamp: Long) {

val path: Path = fileId.asPath.toAbsolutePath

Expand Down
Loading