Generating logfiles

Hi everyone,

this question has been running through my head for quite some time now.

During writing my applications I use

log myVariable

a lot for debugging and displaying where I am in my code.
Now once you are done with a project and let it run you can still run into problems. This is one reason why I am looking for a nice/easy way to save my “logs” to get back to them later.

Anyone ever include writing logfiles in his applications?

Cheers,
Chris

Hi,

actually the clang debugger (LLBD) is so much better to log information but unfortunately it does not work with ASOC.

Try this handler, the parameter theMessage is a string, the log file “debugLog.txt” will be created at desktop


on writeToLog_(theMessage)
	set logMessage to current application's NSString's stringWithFormat_("%@\n", theMessage)
	set logMessageData to logMessage's dataUsingEncoding_(current application's NSUTF8StringEncoding)
	set logPath to POSIX path of (path to desktop) & "debugLog.txt"
	set fileManager to current application's NSFileManager's defaultManager()
	if not (fileManager's fileExistsAtPath_(logPath)) then
		set theResult to fileManager's createFileAtPath_contents_attributes_(logPath, logMessageData, missing value)
	else
		set logFileHandle to current application's NSFileHandle's fileHandleForWritingAtPath_(logPath)
		logFileHandle's seekToEndOfFile()
		logFileHandle's writeData_(logMessageData)
		logFileHandle's closeFile()
	end if
end writeToLog_

And again… thanks Stefan! Very cool! Works like a charm as expected!
I have modified it to add the actual date and time in the logfile created.
It works for me, even though I guess there is a cleaner way of doing it. :wink:


    on writeToLog_(theMessage)
        set timeStamp to current application's NSDate's |date|()
        set theMessage to ": " & theMessage as text
        set logMessage to current application's NSString's stringWithFormat_("%@\n", theMessage)
        set logMessageTime to current application's NSString's stringWithFormat_("%@", timeStamp)
        set logMessageData to logMessage's dataUsingEncoding_(current application's NSUTF8StringEncoding)
        set logMessageTimeData to logMessageTime's dataUsingEncoding_(current application's NSUTF8StringEncoding)
        set logPath to POSIX path of (path to desktop) & "CheckRun4Mac_Logs.txt"
        set fileManager to current application's NSFileManager's defaultManager()
        if not (fileManager's fileExistsAtPath_(logPath)) then
            set theResult to fileManager's createFileAtPath_contents_attributes_(logPath, logMessageTimeData , missing value)
            set logFileHandle to current application's NSFileHandle's fileHandleForWritingAtPath_(logPath)
            logFileHandle's seekToEndOfFile()
            logFileHandle's writeData_(logMessageData)
            logFileHandle's closeFile()
        else
            set logFileHandle to current application's NSFileHandle's fileHandleForWritingAtPath_(logPath)
            logFileHandle's seekToEndOfFile()
            logFileHandle's writeData_(logMessageTimeData)
            logFileHandle's writeData_(logMessageData)
            logFileHandle's closeFile()
        end if
    end writeToLog_

a bit cleaned up


on writeToLog_(theMessage)
	set timeStamp to current application's NSDate's |date|()
	set logMessage to current application's NSString's stringWithFormat_("%@: %@\n", timeStamp, theMessage)
	set logMessageData to logMessage's dataUsingEncoding_(current application's NSUTF8StringEncoding)
	set logPath to POSIX path of (path to desktop) & "CheckRun4Mac_Logs.txt"
	set fileManager to current application's NSFileManager's defaultManager()
	if not (fileManager's fileExistsAtPath_(logPath)) then
		fileManager's createFileAtPath_contents_attributes_(logPath, logMessageData, missing value)
	else
		set logFileHandle to current application's NSFileHandle's fileHandleForWritingAtPath_(logPath)
		logFileHandle's seekToEndOfFile()
		logFileHandle's writeData_(logMessageData)
		logFileHandle's closeFile()
	end if
end writeToLog_

:slight_smile: yepp… clean indeed.
This little snippet is pretty handy for a lot of applications.

Taking this even further, I have another question running through my head:
I would of cause, to not mess up the machines that this is running on, do some housekeeping.

The way I would try doing it (because for me that seems achiveable with my skills) try to write a new file every day and delete files older than X days.

The “cool” way of cause would be to do some sort of round-tripping: restrict the file size OR numer of lines OR after x days, start wrting at the top of the file again.
For the cool way I could think of a special line break / charakters to indicate "this is where I need to start writing other than

logFileHandle's seekToEndOfFile()

What would you say is the best way of doing this?

The easiest way is to write one file a day and delete older files.

Your “cool” way is possible but needs much more code to consider the cases.

The smartest way is probably to use the Apple System Log (ASL) API, but this requires also a portion of (Objective-)C-Code

Thats what I thought. :slight_smile:
I’ll give my first idea a try then…

Hi,

so I have played around a little and got something like this:
The Script will check if a folder for the logs has been created, otherwise it will create it.
It will name the logfile like yyyymmdd.log and create a new one the file with todays date doesnt exist.
It includes a part in the applicationWillFinischLaunching where it is supposed to delete files in that folder older than X days (7 in my example).
The only part I am missing is some sort of pathconversion I think, but I tried severeal way - none worked yet…

This is the code so far:


    on writeToLog_(theMessage)
        set {year:y, month:m, day:d, time string:t} to (current date)
        set todayDate to (y * 10000 + m * 100 + d) as string -- this was the only way I could figure out how to only get the date...
        set timeStamp to current application's NSDate's |date|()
        set logMessage to current application's NSString's stringWithFormat_("%@: %@\n", timeStamp, theMessage)
        set logMessageData to logMessage's dataUsingEncoding_(current application's NSUTF8StringEncoding)
        set logPath to POSIX path of (path to desktop) & "CJU_CheckRun4Mac_Logs/" & todayDate & ".log"
        set fileManager to current application's NSFileManager's defaultManager()
        if not (fileManager's fileExistsAtPath_(logPath)) then
            set theResult to fileManager's createFileAtPath_contents_attributes_(logPath, logMessageData , missing value)
        else
            set logFileHandle to current application's NSFileHandle's fileHandleForWritingAtPath_(logPath)
            logFileHandle's seekToEndOfFile()
            logFileHandle's writeData_(logMessageData)
            logFileHandle's closeFile()
        end if
    end writeToLog_

	on applicationWillFinishLaunching_(aNotification)
        set thePath to (path to desktop folder)
        set theFolderName to "CJU_CheckRun4Mac_Logs"
        set logFolder to POSIX path of (path to desktop) & "CJU_CheckRun4Mac_Logs/"
        tell application "Finder"
            -- check if folder for logfile exists / otherwise create it
            if not (exists folder theFolderName of thePath) then
                make new folder at thePath with properties {name:theFolderName}
            end if
            -- delete logfiles older than 7 days from the logfiles folder
            set deleteFiles to (files of entire contents of folder logFolder whose creation date is less than ((get current date)) - 7 * days)
            try
                repeat with deleteFile in deleteFiles
                    delete deleteFile
                end repeat
            end try
        end tell
        writeToLog_("Application started")
    end applicationWillFinishLaunching_

Hi,

the error message reveals that the error occurs in the Finder tell block while using a POSIX path which the Finder doesn’t understand

try


set deleteFiles to (files of entire contents of folder theFolderName of thePath whose creation date is less than ((get current date)) - 7 * days)

:o I am impressed.

That’s it! And I was thinking way more difficult things with pathconverstions… crazy.
Yes, so that’s it. Generating logfiles with some housekeeping.

Thanks again for your help… I learned a lot from this in the past days.