This is what I do. You only need the first half.
Somewhere really early, i.e., in function Initialise:
- Code: Select all
logfile = io.open("Assets/AndiS/FPSignals/logs/logfile.txt", "w")
Anywhere you like:
- Code: Select all
logfile:write("some stuff for the log\n")
logfile:flush()
The second line makes sure the stuff from the first line really goes to the file right now. It would be more efficient to live without it and let the system do the writing whenever the buffer is full. But in practice, you cannot have that luxury for a series of reasons, one being that no one tells your script when to close the file.
The above would be fine, if you were sure that there will never be a second instance of your asset in the game. Of course you can't. In such a case, you read the log of the instance that opened the file last, what the others write is lost.
In that case, you use "a" instead of "w" in io.open. Now you always append.
This is another reason to flush after each and every message.
Now you need to delete the log after each test run or else you get messed up in old error messages that don't relate to your current script version.
What I do is this:
- Code: Select all
local tim = os.time()
local dat = os.date("*t", tim)
local datestring = string.format("%4d%02d%02d %02d%02d%02d",
dat.year, dat.month, dat.day, dat.hour, dat.min, dat.sec)
logfile = io.open("Assets/AndiS/FPSignals/logs/log " .. datestring .. ".txt", "a")
You can go without the seconds, but then you should be sure to never fix a bug in under 60 seconds, else you append to the old log after the super-fast fix.
You will find that often enough, some instance opens the file before the second boundary and the other after it. (e.g., at 10:00:02.995 and at 10:02:03.001). Then the log messages are split across two files.
You can try to open the log file for reading ("r") only to know if it exists and try the same for the second before now and write to the one that exists, but it starts to become childish here.
I ended up sending messages from signal to signal, originating at a dedicated invisible signal object to tell signals what to log, and added the time stamp to that message. Of course, it is quite an overkill in the normal case.
You will want to prefix our log file lines with some kind of ID of the sender. Signals have their plates, rail vehicles have their unique numbers, too. I found this in an old post, not sure I ever tested it myself:
- Code: Select all
number = Call("GetRVNumber")
If you are interested in the timing, you can either add up all the values of time in Update, assuming that you never call EndUpdate.
- Code: Select all
secondsSinceStart = Call("GetSimulationTime")
gives the seconds since the scenario started.
- Code: Select all
secondsAfterMidnight = SysCall("ScenarioManager:GetTimeOfDay")
gives the time in sync with what is defined in scenario editor. So in the case of signals, this is what I use to debug which train goes where and when.