B4J Question [Jserver4] display error and debug logs in an html page?

Waldemar Lima

Well-Known Member
Licensed User
Longtime User
How do I make b4jserver display the error and debug logs in an html page with b4j_ws.js instead of having to open the vps server every time to see the errors?

the idea is to make a panel to monitor the logs online
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
isplay the error and debug logs in an html page with b4j_ws.js
On the chat example. Erel shows how to store Websockets sessions in a map. Those being able to call them whenever an event happens.

The idea is simple.
Create a ThreadSafeMap
Add the session to this map
Every time an error occurs, call a function asynchronously triggering an updated on such websocket session
by Asynchronous i mean CallsubDelayed
 
Upvote 0

AHilton

Active Member
Licensed User
Longtime User
The basic idea that I deploy with all of my B4J servers is to ...

- Direct all log information to a file. It's a simple command.
- On the webpage (each server has its' own admin.htm page for this and other things), setup a simple text area that'll show the log.
- In the B4J websocket class for that page, read the log file and put that string into the text area.

There's lots of customization that you can employ, such as just showing the last x number of lines and make that configurable. If you're interested, I can pull some code snippets out of one of the servers tomorrow and post them here.

A more detailed way of going about it, and one that really helps with monitoring multiple servers at once, is to direct all logging to a database and then display these lines in an html datatables table. But, the first one is just fine for basic log monitoring.
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Direct all log information to a file.
Your idea is good but you are actually creating a bottleneck (assuming you create the file in the same thread as the websocket/handler) this is because a file can't be written by 2 different threads so most likely the OS is qeueing the writes and therefore there is a delay or you may get a corrupt file form time to time.

To prevent this Jserver allows you to create a same thread handlers, specifically for IO and burdensome operations.

direct all logging to a database
This is the correct answer, in Jserver we use database pooling effectively making the whole transaction asynchronous
 
Upvote 0

AHilton

Active Member
Licensed User
Longtime User
Here's how I do it...

In Main.AppStart, just before initializing the jServer, I call:

B4X:
Sub RedirectOutputToFile (Dir As String, FileName As String)
    #if RELEASE
        Dim out As OutputStream = File.OpenOutput(Dir, FileName, True) '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


In the admin.html page, I put:

B4X:
        <div id="divServerLog">
            <h2>Server Log ...</h2>
            <form id="formserverloglines">
                <label for="serverlognumberoflines">Showing # of lines:</label>
                <input type="text" id="serverlognumberoflines" name="serverlognumberoflines">
                <button id="serverloglinesenter" type="submit">Change</button>
            </form>
            <p>&nbsp;</p>
            <textarea id="serverlog" rows="20" cols="140"></textarea>
            <p>&nbsp;</p>
        </div>


In the B4J wsAdmin websocket class, within the WebSocket_Connected sub, I'll call...

B4X:
Sub ShowServerLog
    ' Server Log
    ServerLogNumberOfLines.SetVal(ShowServerLogLines)
    If File.Exists(File.DirApp & "logs", "logs.txt") = True Then
        Dim sb As StringBuilder : sb.initialize
        Dim List1 As List = File.ReadList(File.DirApp & "logs", "logs.txt")
        If List1.Size-1 > = ShowServerLogLines Then
            Dim start As Int = List1.Size - 1 - ShowServerLogLines
        Else
            Dim start As Int = 0
        End If
        Dim finish As Int = List1.Size - 1
        For i = start To finish
            sb.Append(List1.Get(i) & CRLF)
        Next
        ServerLog.SetVal(sb.ToString)
    End If
End Sub

In your code, you just use the same log() call that you use in normal debugging for the java system to automatically write to your log file. Errors, warnings, and crashes get sent there, too. You don't have to do anything special.

This is a very basic way of showing your log file on a webpage so that you might be able to see what's going on without having to logon to the (hardware) server.
 
Upvote 0

AHilton

Active Member
Licensed User
Longtime User

As you can see in my previous post, I'm letting the Java system do the logging automatically instead of what you were assuming I was doing: opening/writing a file from each websocket connection. Is there a delay anyway? Could be. Can't say that any of our admin staff (that monitors these) has ever complained about a delay. The customer-facing UI doesn't seem to be affected. I know that there's never been a corrupt file (5+ years, over 2 dozen B4J servers since the beginning, and thousands of daily constant users during that time), though.

In programming, there are very few absolute "correct answer"s. There are, however, a whole lot of "different answers", depending on the needs at the time. Is what I offered above a very flexible solution? No. Logging to a database is more flexible, yes. Especially if you're monitoring multiple servers from one location or running analysis on those logs, which is what our staff does now. But, that's no more "correct" than someone that simply wants to be able to see their logs on a webpage.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…