[Class] LogClass - Logging and log file management class

Post your working scripts, libraries and tools
ahbi
Posts: 14
Joined: 15 Jun 2016, 17:11

[Class] LogClass - Logging and log file management class

15 Jun 2018, 23:14

This class makes working with a log file much easier. Once created, you can write to a log file with a single method call.
Each instance of the object supports a single log file (and its inactive older versions). To use multiple log files (with separate names) create multiple instances.
The log files will be tidied up and rotated automatically.
The current log will be titled with just the base filename (e.g., MyLogFile.log) with older, inactive log files being named with a trailing index (e.g., MyLogFile_1.log, MyLogFile_2.log). Newer files having a higher index.
Log files may be limited by size, and when the threshold is reached the file will be moved to an inactive filename and a new log started.

A brief usage example is as follows:

Code: [Select all] [Download] GeSHi © Codebox Plus

	global log := new LogClass(“MyLogFile”)
log.initalizeNewLogFile(false, “Header text to appear at the start of the new file”)
log.addLogEntry(“Your 1st message to put in the log file”)
log.addLogEntry(“Your next message to put in the log file”)
log.finalizeLog(“Footer text to appear at the very end of your log, which you are done with.)


This LogClass is inspired (very much so) by the pre-AHK built-in classes (circa 2009) file Log.ahk
by Ben McClure, and found at
From: https://autohotkey.com/board/topic/37953-class-log-logging-and-log-file-management-library/
Ben's Log.ahk required the Class.ahk, Vector.ahk, and String.ahk which are no longer available (and outdated), and hence was a dead piece of code.

Also a thank you to nnnik's excellent work at: https://autohotkey.com/boards/viewtopic.php?f=74&t=48740


The <name>String properties (e.g., preEntryString, HeaderString, etc.) may be set via initalizeNewLogFile() or individually.
They are strings that will be applied automatically when creating/ending a log file, or adding a new log message/entry. This allows you to apply a common format (or information) to every logfile or log entry.
The String properties all accept variables which may be expanded when written.
  • $time or %A_Now% expands to the time the log entry is written (as formatted according to this.logsTimeFormat).
  • $printStack expands to a list of the function calls which caused the log entry to be written.
  • %Var% expands to whatever value variable Var is, but Var must be a global/built-in variable.
These String property variables may be used in the log entries too (e.g., by this.addLogEntry(entry))

The class is as follows:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus




Several examples of how to use class are as follows:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus




Updates:

2018-06-19:
* Made all filename properties read-only (set via New())
* changed printStack().maxNumbCalls to 2000 which is pretty much ALL
Last edited by ahbi on 20 Jun 2018, 00:13, edited 2 times in total.
User avatar
nnnik
Posts: 2964
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [Class] LogClass - Logging and log file management class

16 Jun 2018, 01:38

This looks good. I'm probably going to use it. Glad you liked my discovery :)
Do you plan to host it on git?
Recommends AHK Studio
ahbi
Posts: 14
Joined: 15 Jun 2016, 17:11

Re: [Class] LogClass - Logging and log file management class

18 Jun 2018, 12:51

FYI:
I am thinking about pulling out the ability to set the log's filename through anything but New().

This would mean all the filename-related properties would be read-only (get(), but no set())

PS:
GitHub is an idea. I have never used it before.
User avatar
Chunjee
Posts: 49
Joined: 18 Apr 2014, 19:05
GitHub: Chunjee

Re: [Class] LogClass - Logging and log file management class

19 Jun 2018, 14:40

Wow I started needing a logging class today and I see this is less than a week old. Perfect timing. Thanks my dude.

I noticed that both .initalizeNewLogFile() and .finalizeLog() ignore pre/postEntryString, which seems a little inconsistant to me but I don't have any strong feeling about it.


In the future I'd like to see this go more async as FileAppend has the potential to significantly slow down an application. Might have to figure that one out on my own.
ahbi
Posts: 14
Joined: 15 Jun 2016, 17:11

Re: [Class] LogClass - Logging and log file management class

19 Jun 2018, 23:04

Chunjee wrote:Wow I started needing a logging class today and I see this is less than a week old. Perfect timing. Thanks my dude.


Thanks

Please let me know if I need to correct any errors.


Chunjee wrote:I noticed that both .initalizeNewLogFile() and .finalizeLog() ignore pre/postEntryString, which seems a little inconsistant to me but I don't have any strong feeling about it.


That is because pre/post are for entries and init/final are for header/footers.

Which is to say, the init/final are for starting/stopping a log file and don't write "entries"

Whereas addLogEntry() is for the middle/body of the file and for writing an "entry"

Conceptually they are 2 different things. Header/Footer (init/final) are to be written once (or none) per file, and an entry (and per/post) are to be used over-and-over again, each time you want to write a note/message/entry/line to the log.

If it helps think of header/footer like the header/footer of a Word file that includes your letterhead, document title, page numbering (which doesn't work in the log context, but you know that in Word you put page numbers in the footer).
And an entry is the text in the main body of the Word document.
In the analogy, each log file (in the index chain MyLogFile_1.log) is a "page" in the Word document. As you go to a new "page" (or log file) a new copy of the header/footer gets written (well footer on the old "page" and header on the new). addLogEntry() writes in the body of each page.

Part of the idea is I expect preEntryString to (often) be a timestamp, and I don't want the header/footer muddied up with the timestamp at the front.

And I also admit init() is a slightly strange beast and it kind of acts like a 2nd half of the New() function by setting all those string properties.

Chunjee wrote:In the future I'd like to see this go more async as FileAppend has the potential to significantly slow down an application. Might have to figure that one out on my own.


It actually does use the File object.

I know it is easy to miss and it is in a wrapper function called appendFile() (vs. FileAppend, which is just the name flipped around; look down in the helper methods section).

I started off with FileAppend, but as you said it was too slow. You'll see a try/catch group in savePending() where I discovered that FileAppened couldn't keep up. So, I created the wrapper function appendFile() and started working on the File object (which is so much faster).
User avatar
nnnik
Posts: 2964
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [Class] LogClass - Logging and log file management class

19 Jun 2018, 23:41

Is the file object completely async?

A thing that would be nice to have is something like logObject which could handle objects. And let's the user define a function for Object logging beforehand.
Generally dealing with multiple types would by nice.
Recommends AHK Studio
ahbi
Posts: 14
Joined: 15 Jun 2016, 17:11

Re: [Class] LogClass - Logging and log file management class

20 Jun 2018, 00:11

nnnik wrote:Is the file object completely async?

A thing that would be nice to have is something like logObject which could handle objects. And let's the user define a function for Object logging beforehand.
Generally dealing with multiple types would by nice.


Explain to me more how to do that?

Or point me to some example.

The problem is, as a hobbyist, I don't fully understand the request.
User avatar
nnnik
Posts: 2964
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [Class] LogClass - Logging and log file management class

20 Jun 2018, 00:28

Well for every data type that would be loggeable add a code in this pattern:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus


There aren't many data types in AHK:
Number (turns into a string automatically)
Binary (might be neccessary to add a function for)
Object (I guess the most important case)

Edit:
This is my function for turning objects or rather anything into a string:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

Recommends AHK Studio
User avatar
Chunjee
Posts: 49
Joined: 18 Apr 2014, 19:05
GitHub: Chunjee

Re: [Class] LogClass - Logging and log file management class

10 Jul 2018, 09:59

My application usually just runs once a day, but occasionally more often. In those cases the original log file gets overwritten. Is there a built-in way to control this? I'd rather it just keep appending or rotate the logs and keep the original intact somehow.

EDIT: After looking at overwriteExistingFile, I'm thinking maxNumbOldLogs_Default needs to be set to -1 as the default 0 keeps only the current file.


Because I'm feeding logs up to Sumologic and want them a little more machine readable I wrote a custom method that just writes the entry as a stringified JSON object. I'm working to make it a little more useable by others and will post it eventually.
User avatar
Chunjee
Posts: 49
Joined: 18 Apr 2014, 19:05
GitHub: Chunjee

Re: [Class] LogClass - Logging and log file management class

Yesterday, 15:11

I tried changing isAutoWriteEntries_Default to false and it writes nothing beyond the initalize line. What gives?


I'm trying to figure it out. the library doesn't periodically call .savePendingEntriesToLog() by itself. I was expecting somekind of "Is the CPU idle enough to start writing?" timer.

.finalizeLog() should be calling it and my app does so, but some other error or setting is preventing it from hitting there. Still looking into it.
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
GitHub: KuroiLight

Re: [Class] LogClass - Logging and log file management class

Yesterday, 21:52

More extensive than mine, I may take some ideas from it :P, I like that its really customizable.

heres mine for reference:
Spoiler
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 19 guests