Jump to content

_FileWriteLog question with multiple users


Recommended Posts

Hi,

I use the _FileWriteLog function in a script to write a small log.

All works fine, but when two different people run the script at the same time, the log is mixed with the entries from them.

Not so fine, cause it looks very weird.

Is there a way with _FileWriteLog to handle multiple users and write the text for each user in the log file and not mixed?

Link to post
Share on other sites
31 minutes ago, blumi said:

Is there a way with _FileWriteLog to handle multiple users and write the text for each user in the log file and not mixed?

I am not sure if I understand your problem correctly.

Should 1.) several users write to one log file (then the entries are mixed), or 2.) should each user get his own log file ?

-> 1.) You could place the macro @Username at the beginning of the log message ($sLogMsg).

-> 2.) You could put the macro @Username in the filename of the logfile.

If you want to use only one logfile, then you could include the following in the script :
-> lock the logfile for access from other instances of the script
-> write log entries
-> unlock the logfile
Check if the logfile is currently locked and wait until it is unlocked.

Take a look at : lockfile-lock-a-file-to-the-current-process-only

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to post
Share on other sites

My fault.

Yes, one log file for all.

It is like an installation script. Starting script, installing with or without errors, finish script...

I use @username in the script, that works all fine.

I only have the problem, wenn two different persons run the script an the same time, the lines in the log are written mixed by the users.

I will take a look at the lockfile UDF
 

Link to post
Share on other sites

You'd be better having a log file per user, it'll make it easier to read. I'd even go as far as filing them in Year and Month folders.

#include <Date.au3>
#include <File.au3>
#include <FileConstants.au3>

_AppendLog('Your User Name is: ' & @UserName)

Func _AppendLog($sString)
    If FileExists(@ScriptDir & '\Logs\' & @UserName & '\' & @YEAR & '\' & _DateToMonth(@MON, $DMW_SHORTNAME)) = 0 Then
        DirCreate(@ScriptDir & '\Logs\' & @UserName & '\' & @YEAR & '\' & _DateToMonth(@MON, $DMW_SHORTNAME))
    EndIf
    $hFile = FileOpen(@ScriptDir & '\Logs\' & @UserName & '\' & @YEAR & '\' & _DateToMonth(@MON, $DMW_SHORTNAME) & '\' & @MDAY & '.txt', $FO_APPEND)
    _FileWriteLog($hFile, $sString)
    FileClose($hFile)
EndFunc

If you're set on one log file however, like @Musashi said, definitely take a look at the LockFile UDF.

Link to post
Share on other sites
25 minutes ago, Nine said:

You could also use _Singleton to ensure only one process is running at a time ?

Does this work for expample in a network with 5 pcs and 5 users and one server where the script is saved and executed from the users?

Link to post
Share on other sites

I do not think so even if you create the mutex with the Global\ prefix.  As MSDN says :

Quote

The global namespace enables processes on multiple client sessions to communicate with a service application. For example, a client/server application might use a mutex object for synchronization. The server module can create the mutex object in the global namespace. Then a client session can use the "Global\" prefix to open the mutex object.

In your case, all clients create its own mutex (not the server).  So you are better with a CreateFile approach where you can create a specific temp file to serve as a mutex.

Link to post
Share on other sites
1 hour ago, Luke94 said:

You'd be better having a log file per user, it'll make it easier to read.

I would prefer this approach as well (in this particular case). A file lock would ensure, that the message sequences of the respective users appear as a coherent block and not as an erratic mix. However, the readability of the logfile would still be a PITA ;). One log file per user, in contrast, can be analyzed effectively.

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to post
Share on other sites

Yesterday, I had the idea, not to use _FileWriteLog.

Instead just create some text with date, time, user, message.

Line for line.

At the end of the script, just save the text to the log file. 

How about this idea?

 

Link to post
Share on other sites
10 minutes ago, blumi said:

Yesterday, I had the idea, not to use _FileWriteLog.

Instead just create some text with date, time, user, message.

Line for line.

At the end of the script, just save the text to the log file. 

How about this idea?

 

Isn't that just the same as doing:

_FileWriteLog(@UserName & ' - ' & $sString)

?

Link to post
Share on other sites
2 minutes ago, Luke94 said:

Isn't that just the same as doing:

_FileWriteLog(@UserName & ' - ' & $sString)

?

Not when I have the problem, that two people could use the script at the same time. 

For example the script takes 120s to run.

When I write all in an array and only open the log file to write all the text into it, it takes only a few seconds or faster.

The risk that a user does this at the same time is much smaller. 

That was my thought. 

Link to post
Share on other sites
19 minutes ago, blumi said:

Not when I have the problem, that two people could use the script at the same time. 

For example the script takes 120s to run.

When I write all in an array and only open the log file to write all the text into it, it takes only a few seconds or faster.

The risk that a user does this at the same time is much smaller. 

That was my thought. 

Like this?

#include <Array.au3>
#include <Date.au3>
#include <File.au3>
#include <MsgBoxConstants.au3>

Global $g_aLog[0]

For $i = 1 To 10 Step 1
    _LogWrite('Line ' & $i)
Next
MsgBox(($MB_OK + $MB_ICONINFORMATION), @ScriptName, "The log won't be written to the log file until you click OK.")
_LogWrite(NULL, 1)

Func _LogWrite($sString, $iFlush = 0)
    Local $hFile
    If $sString <> NULL Then
        _ArrayAdd($g_aLog, StringFormat('[%s %s] %s', _NowDate(), _NowTime(), $sString))
    EndIf
    If $iFlush = 1 Then
        If UBound($g_aLog) > 0 Then
            If FileExists(@ScriptDir & '\Logs\' & @YEAR & '\' & _DateToMonth(@MON, $DMW_SHORTNAME)) = 0 Then
                DirCreate(@ScriptDir & '\Logs\' & @YEAR & '\' & _DateToMonth(@MON, $DMW_SHORTNAME))
            EndIf
            $hFile = FileOpen(@ScriptDir & '\Logs\' & @YEAR & '\' & _DateToMonth(@MON, $DMW_SHORTNAME) & '\' & @MDAY & '.txt', $FO_APPEND)
            If $hFile <> -1 Then
                _FileWriteFromArray($hFile, $g_aLog)
                If @ERROR = 0 Then
                    Global $g_aLog[0]
                EndIf
            EndIf
            FileClose($hFile)
        EndIf
    EndIf
EndFunc

Edit: You'd obviously use @UserName etc in _LogWrite().

You could flush the log on exit.

I assume there's multiple programs? If so, you'd end up with the programs writing the array to the log file at different times and the log file could end up looking like this:

Quote

[17/06/2021 15:27:06] Line 1 <-- Program 1 log start
[17/06/2021 15:27:06] Line 2
[17/06/2021 15:27:06] Line 3
[17/06/2021 15:27:06] Line 4
[17/06/2021 15:27:06] Line 5
[17/06/2021 15:27:07] Line 6
[17/06/2021 15:27:07] Line 7
[17/06/2021 15:27:07] Line 8
[17/06/2021 15:27:07] Line 9
[17/06/2021 15:27:07] Line 10 <-- Program 1 log end
[17/06/2021 15:27:06] Line 1 <-- Program 2 log start
[17/06/2021 15:27:06] Line 2
[17/06/2021 15:27:06] Line 3
[17/06/2021 15:27:06] Line 4
[17/06/2021 15:27:06] Line 5
[17/06/2021 15:27:07] Line 6
[17/06/2021 15:27:07] Line 7
[17/06/2021 15:27:07] Line 8
[17/06/2021 15:27:07] Line 9
[17/06/2021 15:27:07] Line 10 <-- Program 2 log end

See how they're not in order.

Edited by Luke94
Link to post
Share on other sites
5 minutes ago, argumentum said:

..do a TCP to send to the server and the clients would all send to this "log collector server". That'll solve a bunch of future problems. :)

This is the best solution. Very easy to do over a network too.

Link to post
Share on other sites
3 minutes ago, argumentum said:

..do a TCP to send to the server and the clients would all send to this "log collector server". That'll solve a bunch of future problems. :)

Where can I find more info about this?

 

Link to post
Share on other sites
2 minutes ago, argumentum said:

the links on my signature have a bunch of stuff. You could use a web server. You can also find code in the help file.

Lots of stuff there, I will check later, thank you 

 

Link to post
Share on other sites
2 hours ago, blumi said:

Yesterday, I had the idea, not to use _FileWriteLog.

Instead just create some text with date, time, user, message.

Line for line.

At the end of the script, just save the text to the log file. 

How about this idea?

I think it is not a bad idea.  Only problem is that if a user hang or crash or exit the script, the whole log will be lost.  If this is not important, then I would agree to go with this solution.  If that causes a problem, one other solution is to create a single table in SQLite with the vars (user, date, time, message).  Everyone can write the RDBMS concurently, then you can print the table in the order of your choice (ex. user date time) at the end of the day.

Link to post
Share on other sites

I warmly second Nine's advice about SQLite. I think it's the only cheap & serious way to handle logs. Not only it supports all kind of nastinesses (power outage, concurrency) but it's also wastly superior when you have to trace things in any other order than chronological.

For instance, how frequent is error 117 for user group blah over the last 6 months? That's a one-line query using a (free) SQLite 3rd-party browser, no need to write code.

Of course if your log data won't never exceed 20 lines a year, you might consider taking the risk of flat text file(s).

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...