B4J Question Daily log like jServer for other B4J apps

alwaysbusy

Expert
Licensed User
jServer has a great system to create a log per day. I was wondering if there is an easy way to do this for our own logs too. At this moment I'm using this snippet to redirect the output:

B4X:
Sub RedirectOutput (Dir As String, FileName As String)
#if RELEASE
   Dim out As OutputStream = File.OpenOutput(Dir, FileName, False) 'Set to True to append the logs
   Dim ps As JavaObject
   ps.InitializeNewInstance("java.io.PrintStream", Array(out, True, "utf8"))
   Dim jo As JavaObject
   jo.InitializeStatic("java.lang.System")
   jo.RunMethod("setOut", Array(ps))
   jo.RunMethod("setErr", Array(ps))
#end if
End Sub
But it only creates a new file per jar startup: when the jar runs multiple days it keeps writing in the same file. If it could make a file per day, one could easily do some cleanup (e.g. after a week) of old logs.

How would the above redirect snippet have to look to archieve this?
 

Erel

Administrator
Staff member
Licensed User
B4X:
Sub Process_Globals
   Private LogsOutput As OutputStream
End Sub


Sub AppStart (Args() As String)
   HandleLogs
   StartMessageLoop
End Sub

Sub HandleLogs
   Dim CurrentDay As Long = 0
   Do While True
       Dim year As Int = DateTime.GetYear(DateTime.Now)
       Dim month As Int = DateTime.GetMonth(DateTime.Now)
       Dim day As Int = DateTime.GetDayOfMonth(DateTime.Now)
       Dim d As Long = DateUtils.SetDate(year, month, day)
       If d <> CurrentDay Then
           CurrentDay = d
           RedirectOutput(File.DirApp, $"Logs-$4{year}-$2{month}-$2{day}.txt"$)
       End If
       Sleep(60000)
   Loop
End Sub

Sub RedirectOutput (Dir As String, FileName As String)
#if RELEASE
   If LogsOutput.IsInitialized Then LogsOutput.Close
   LogsOutput = File.OpenOutput(Dir, FileName, False) 'Set to True to append the logs
   Log("Redirecting logs to: " & FileName)
   Dim ps As JavaObject
   ps.InitializeNewInstance("java.io.PrintStream", Array(LogsOutput, True, "utf8"))
   Dim jo As JavaObject
   jo.InitializeStatic("java.lang.System")
   jo.RunMethod("setOut", Array(ps))
   jo.RunMethod("setErr", Array(ps))
#end if
End Sub
 

alwaysbusy

Expert
Licensed User
@Erel I had a similar system, but was afraid that calling the "new" RedirectOutput wouldn't close the "old" one (which it didn't in my case, looking at your code).

I thought I would have somehow via JavaObject grab the old "out", close that and then re-set it. Your global LogsOutput and the 'If LogsOutput.IsInitialized Then LogsOutput.Close' solves that concern.

Thanks a bunch!
 
Top