Improvements in trace output:

- Scheduled calls are traced with ---> or +++> prefixes... This is handy to find where scheduled calls were actually called in the code. Line number and function is shown correctly now. ---> is for one schedule, and +++> for repeated schedules.
- Fsm output is now also organized better. All Fsm calls are shown with :::> prefix. The onafter, onbefore, onenter or onleave method names are also shown, and also the state transition including the function call place is shown now.
-- Now for each trace line, the class name has 30 characters space.
This commit is contained in:
FlightControl
2019-08-31 07:24:31 +02:00
parent c1b240857f
commit 14b35cb069
4 changed files with 90 additions and 30 deletions

View File

@@ -52,7 +52,7 @@ end
-- Nothing of this code should be modified without testing it thoroughly.
-- @param #SCHEDULEDISPATCHER self
-- @param Core.Scheduler#SCHEDULER Scheduler
function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel )
function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel, Fsm )
self:F2( { Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel } )
self.CallID = self.CallID + 1
@@ -85,13 +85,40 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
self.Schedule[Scheduler][CallID].Randomize = Randomize or 0
self.Schedule[Scheduler][CallID].Stop = Stop
local Source = ""
local Line = ""
-- This section handles the tracing of the scheduled calls.
-- Because these calls will be executed with a delay, we inspect the place where these scheduled calls are initiated.
-- The Info structure contains the output of the debug.getinfo() calls, which inspects the call stack for the function name, line number and source name.
-- The call stack has many levels, and the correct semantical function call depends on where in the code AddSchedule was "used".
-- - Using SCHEDULER:New()
-- - Using Schedule:AddSchedule()
-- - Using Fsm:__Func()
-- - Using Class:ScheduleOnce()
-- - Using Class:ScheduleRepeat()
-- - ...
-- So for each of these scheduled call variations, AddSchedule is the workhorse which will schedule the call.
-- But the correct level with the correct semantical function location will differ depending on the above scheduled call invocation forms.
-- That's where the field TraceLevel contains optionally the level in the call stack where the call information is obtained.
-- The TraceLevel field indicates the correct level where the semantical scheduled call was invoked within the source, ensuring that function name, line number and source name are correct.
-- There is one quick ...
-- The FSM class models scheduled calls using the __Func syntax. However, these functions are "tailed".
-- There aren't defined anywhere within the source code, but rather implemented as triggers within the FSM logic,
-- and using the onbefore, onafter, onenter, onleave prefixes. (See the FSM for details).
-- Therefore, in the call stack, at the TraceLevel these functions are mentioned as "tail calls", and the Info.name field will be nil as a result.
-- To obtain the correct function name for FSM object calls, the function is mentioned in the call stack at a higher stack level.
-- So when function name stored in Info.name is nil, then I inspect the function name within the call stack one level higher.
-- So this little piece of code does its magic wonderfully, preformance overhead is neglectible, as scheduled calls don't happen that often.
local Info = {}
if debug then
TraceLevel = TraceLevel or 2
Source = debug.getinfo( TraceLevel, "S" ).source
Line = debug.getinfo( TraceLevel, "nl" ).currentline
Info = debug.getinfo( TraceLevel, "nlS" )
local name_fsm = debug.getinfo( TraceLevel - 1, "n" ).name -- #string
if name_fsm then
Info.name = name_fsm
end
--env.info( debug.traceback() )
end
self:T3( self.Schedule[Scheduler][CallID] )
@@ -99,8 +126,10 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
self.Schedule[Scheduler][CallID].CallHandler = function( Params )
local CallID = Params.CallID
local Source = Params.Source
local Line = Params.Line
local Info = Params.Info
local Source = Info.source
local Line = Info.currentline
local Name = Info.name or "?"
local ErrorHandler = function( errmsg )
env.info( "Error in timer function: " .. errmsg )
@@ -134,19 +163,19 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
local Stop = Schedule.Stop or 0
local ScheduleID = Schedule.ScheduleID
local Prefix = ( Repeat == 0 ) and " ---> " or " +++> "
local Prefix = ( Repeat == 0 ) and "--->" or "+++>"
local Status, Result
--self:E( { SchedulerObject = SchedulerObject } )
if SchedulerObject then
local function Timer()
SchedulerObject:T( Prefix .. ( Source or "-" ) .. ": " .. ( Line or "-" ) )
SchedulerObject:T( Prefix .. Name .. ":" .. Line .. " (" .. Source .. ")" )
return ScheduleFunction( SchedulerObject, unpack( ScheduleArguments ) )
end
Status, Result = xpcall( Timer, ErrorHandler )
else
local function Timer()
self:T( Prefix .. ( Source or "-" ) .. ": " .. ( Line or "-" ) )
self:T( Prefix .. Name .. ":" .. Line .. " (" .. Source .. ")" )
return ScheduleFunction( unpack( ScheduleArguments ) )
end
Status, Result = xpcall( Timer, ErrorHandler )
@@ -177,13 +206,13 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
self:Stop( Scheduler, CallID )
end
else
self:I( " <<<> " .. ( Source or "-" ) .. ": " .. ( Line or "-" ) )
self:I( "<<<>" .. Name .. ":" .. Line .. " (" .. Source .. ")" )
end
return nil
end
self:Start( Scheduler, CallID, Source, Line )
self:Start( Scheduler, CallID, Info )
return CallID
end
@@ -197,7 +226,7 @@ function SCHEDULEDISPATCHER:RemoveSchedule( Scheduler, CallID )
end
end
function SCHEDULEDISPATCHER:Start( Scheduler, CallID, Source, Line )
function SCHEDULEDISPATCHER:Start( Scheduler, CallID, Info )
self:F2( { Start = CallID, Scheduler = Scheduler } )
if CallID then
@@ -208,13 +237,13 @@ function SCHEDULEDISPATCHER:Start( Scheduler, CallID, Source, Line )
Schedule[CallID].StartTime = timer.getTime() -- Set the StartTime field to indicate when the scheduler started.
Schedule[CallID].ScheduleID = timer.scheduleFunction(
Schedule[CallID].CallHandler,
{ CallID = CallID, Source = Source, Line = Line },
{ CallID = CallID, Info = Info },
timer.getTime() + Schedule[CallID].Start
)
end
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Start( Scheduler, CallID, Source, Line ) -- Recursive
self:Start( Scheduler, CallID, Info ) -- Recursive
end
end
end