@@ -127,11 +127,7 @@ static bool EvalContextClassPut(EvalContext *ctx, const char *ns, const char *na
127127static const char * EvalContextCurrentNamespace (const EvalContext * ctx );
128128static ClassRef IDRefQualify (const EvalContext * ctx , const char * id );
129129
130- static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset );
131130static void EventFrameDestroy (EventFrame * event );
132- static EventFrame * BundleToEventFrame (const Bundle * bp );
133- static EventFrame * PromiseToEventFrame (const Promise * pp );
134- static EventFrame * FunctionToEventFrame (const FnCall * fp );
135131
136132/**
137133 * Every agent has only one EvalContext from process start to finish.
@@ -201,11 +197,8 @@ struct EvalContext_
201197
202198 /* These are needed for policy profiling */
203199 bool profiling ;
204-
205- struct {
206- int64_t elapsed ;
207- Seq * events ;
208- } profiler ;
200+ int64_t elapsed ;
201+ Seq * events ;
209202
210203 EvalOrder common_eval_order ;
211204 EvalOrder agent_eval_order ;
@@ -349,6 +342,21 @@ static StackFrame *LastStackFrameByType(const EvalContext *ctx, StackFrameType t
349342 return NULL ;
350343}
351344
345+ static StackFrame * LastStackFrameByEvent (const EvalContext * ctx )
346+ {
347+ assert (ctx != NULL );
348+ for (size_t i = 0 ; i < SeqLength (ctx -> stack ); i ++ )
349+ {
350+ StackFrame * frame = LastStackFrame (ctx , i );
351+ if (frame -> event != NULL )
352+ {
353+ return frame ;
354+ }
355+ }
356+
357+ return NULL ;
358+ }
359+
352360static LogLevel AdjustLogLevel (LogLevel base , LogLevel adjust )
353361{
354362 if (adjust == -1 )
@@ -1110,8 +1118,8 @@ EvalContext *EvalContextNew(void)
11101118
11111119 ctx -> dump_reports = false;
11121120
1113- ctx -> profiler . events = SeqNew (20 , EventFrameDestroy );
1114- ctx -> profiler . elapsed = 0 ;
1121+ ctx -> events = SeqNew (20 , EventFrameDestroy );
1122+ ctx -> elapsed = 0 ;
11151123
11161124 // evaluation order
11171125 ctx -> common_eval_order = EVAL_ORDER_UNDEFINED ;
@@ -1164,7 +1172,7 @@ void EvalContextDestroy(EvalContext *ctx)
11641172 ctx -> remote_var_promises = NULL ;
11651173 }
11661174
1167- SeqDestroy (ctx -> profiler . events );
1175+ SeqDestroy (ctx -> events );
11681176 free (ctx );
11691177 }
11701178}
@@ -1349,20 +1357,19 @@ static StackFrame *StackFrameNew(StackFrameType type, bool inherit_previous)
13491357 frame -> inherits_previous = inherit_previous ;
13501358 frame -> path = NULL ;
13511359 frame -> override_immutable = false;
1352- frame -> start = EvalContextEventStart ();
13531360 frame -> event = NULL ;
13541361
13551362 return frame ;
13561363}
13571364
1358- static StackFrame * StackFrameNewBundle (const Bundle * owner , bool inherit_previous , bool profiling )
1365+ static StackFrame * StackFrameNewBundle (const Bundle * owner , bool inherit_previous , bool profiling , EventFrame * prev_event )
13591366{
13601367 StackFrame * frame = StackFrameNew (STACK_FRAME_TYPE_BUNDLE , inherit_previous );
13611368
13621369 frame -> data .bundle .owner = owner ;
13631370 frame -> data .bundle .classes = ClassTableNew ();
13641371 frame -> data .bundle .vars = VariableTableNew ();
1365- frame -> event = (profiling ) ? BundleToEventFrame (owner ) : NULL ;
1372+ frame -> event = (profiling ) ? BundleToEventFrame (owner , prev_event ) : NULL ;
13661373
13671374 return frame ;
13681375}
@@ -1386,12 +1393,12 @@ static StackFrame *StackFrameNewBundleSection(const BundleSection *owner)
13861393 return frame ;
13871394}
13881395
1389- static StackFrame * StackFrameNewPromise (const Promise * owner , bool profiling )
1396+ static StackFrame * StackFrameNewPromise (const Promise * owner , bool profiling , EventFrame * prev_event )
13901397{
13911398 StackFrame * frame = StackFrameNew (STACK_FRAME_TYPE_PROMISE , true);
13921399
13931400 frame -> data .promise .owner = owner ;
1394- frame -> event = (profiling ) ? PromiseToEventFrame (owner ) : NULL ;
1401+ frame -> event = (profiling ) ? PromiseToEventFrame (owner , prev_event ) : NULL ;
13951402
13961403 return frame ;
13971404}
@@ -1443,7 +1450,8 @@ void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, cons
14431450 assert (ctx != NULL );
14441451 assert (!LastStackFrame (ctx , 0 ) || LastStackFrame (ctx , 0 )-> type == STACK_FRAME_TYPE_PROMISE_ITERATION );
14451452
1446- EvalContextStackPushFrame (ctx , StackFrameNewBundle (owner , inherits_previous , ctx -> profiling ));
1453+ StackFrame * frame = StackFrameNewBundle (owner , inherits_previous , ctx -> profiling , EvalContextGetLastEventFrame (ctx ));
1454+ EvalContextStackPushFrame (ctx , frame );
14471455
14481456 if (RlistLen (args ) > 0 )
14491457 {
@@ -1523,8 +1531,7 @@ void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner)
15231531
15241532 EvalContextVariableClearMatch (ctx );
15251533
1526- StackFrame * frame = StackFrameNewPromise (owner , ctx -> profiling );
1527-
1534+ StackFrame * frame = StackFrameNewPromise (owner , ctx -> profiling , EvalContextGetLastEventFrame (ctx ));
15281535 EvalContextStackPushFrame (ctx , frame );
15291536
15301537 // create an empty table
@@ -1615,15 +1622,11 @@ void EvalContextStackPopFrame(EvalContext *ctx)
16151622
16161623 StackFrame * last_frame = LastStackFrame (ctx , 0 );
16171624 StackFrameType last_frame_type = last_frame -> type ;
1618- int64_t start = last_frame -> start ;
1619- int64_t end = EvalContextEventStart ();
16201625
16211626 EventFrame * last_event = last_frame -> event ;
16221627 if (last_event != NULL )
16231628 {
1624- assert (end >= start ); /* sanity check */
1625- last_event -> elapsed = end - start ;
1626- SeqAppend (ctx -> profiler .events , last_event );
1629+ EvalContextAppendEventFrame (ctx , last_event );
16271630 }
16281631
16291632 switch (last_frame_type )
@@ -3892,22 +3895,33 @@ bool EvalContextOverrideImmutableGet(EvalContext *ctx)
38923895
38933896// ##############################################################
38943897
3895- void EvalContextSetProfiling ( EvalContext * ctx , bool profiling )
3898+ static int64_t EvalContextEventStart ( )
38963899{
3897- assert (ctx != NULL );
3898- ctx -> profiling = profiling ;
3900+ struct timespec ts ;
3901+ #ifdef CLOCK_MONOTONIC
3902+ clock_gettime (CLOCK_MONOTONIC , & ts );
3903+ #else
3904+ // As in libcfnet/net.c some OS-es don't have monotonic clock, realtime clock is best we can do.
3905+ clock_gettime (CLOCK_REALTIME , & ts );
3906+ #endif
3907+ return ts .tv_sec * 1000000000LL + ts .tv_nsec ;
38993908}
39003909
3901- static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset )
3910+ static EventFrame * EventFrameCreate (const char * source , char * component , char * type , const char * ns , const char * name ,
3911+ SourceOffset offset , EventFrame * prev , char * id )
39023912{
39033913 EventFrame * event = (EventFrame * ) xmalloc (sizeof (EventFrame ));
3914+ event -> elapsed = EvalContextEventStart ();
39043915
3916+ event -> source = GetAbsolutePath (source );
3917+ event -> component = component ;
39053918 event -> type = type ;
3919+ event -> ns = SafeStringDuplicate (ns );
39063920 event -> name = SafeStringDuplicate (name );
3907- event -> filename = GetAbsolutePath (source );
3908- event -> elapsed = 0 ;
39093921 event -> offset = offset ;
3910- event -> id = StringFormat ("%s_%s_%s_%ld_%ld" , type , name , source , offset .start , offset .line );
3922+
3923+ event -> id = id ;
3924+ event -> callstack = (prev != NULL ) ? StringFormat ("%s;%s" , prev -> callstack , event -> id ) : SafeStringDuplicate (event -> id );
39113925
39123926 return event ;
39133927}
@@ -3916,9 +3930,12 @@ static void EventFrameDestroy(EventFrame *event)
39163930{
39173931 if (event != NULL )
39183932 {
3919- free (event -> filename );
3920- free (event -> id );
3933+ free (event -> source );
3934+ free (event -> ns );
39213935 free (event -> name );
3936+
3937+ free (event -> id );
3938+ free (event -> callstack );
39223939 free (event );
39233940 }
39243941}
@@ -3928,11 +3945,14 @@ static JsonElement *EventToJson(EventFrame *event)
39283945 assert (event != NULL );
39293946 JsonElement * json_event = JsonObjectCreate (10 );
39303947
3948+ JsonObjectAppendString (json_event , "component" , event -> component );
39313949 JsonObjectAppendString (json_event , "type" , event -> type );
39323950 JsonObjectAppendString (json_event , "name" , event -> name );
3933- JsonObjectAppendString (json_event , "filename" , event -> filename );
3951+ JsonObjectAppendString (json_event , "namespace" , event -> ns );
3952+ JsonObjectAppendString (json_event , "source" , event -> source );
39343953 JsonObjectAppendString (json_event , "id" , event -> id );
39353954 JsonObjectAppendInteger64 (json_event , "elapsed" , event -> elapsed );
3955+ JsonObjectAppendString (json_event , "callstack" , event -> callstack );
39363956
39373957 JsonElement * offset = JsonObjectCreate (4 );
39383958 JsonObjectAppendInteger (offset , "start" , event -> offset .start );
@@ -3945,81 +3965,46 @@ static JsonElement *EventToJson(EventFrame *event)
39453965 return json_event ;
39463966}
39473967
3948- static EventFrame * BundleToEventFrame (const Bundle * bp )
3968+ EventFrame * BundleToEventFrame (const Bundle * bp , EventFrame * prev_frame )
39493969{
39503970 assert (bp != NULL );
3951- return EventFrameCreate ("bundle" , bp -> name , bp -> source_path , bp -> offset );
3971+ char * id = StringFormat ("%s:%ld/%s_%s_%s:%s" , GetAbsolutePath (bp -> source_path ), bp -> offset .line , "bundle" , bp -> type , bp -> ns , bp -> name );
3972+ return EventFrameCreate (bp -> source_path , "bundle" , bp -> type , bp -> ns , bp -> name , bp -> offset , prev_frame , id );
39523973}
39533974
3954- static EventFrame * PromiseToEventFrame (const Promise * pp )
3975+ EventFrame * PromiseToEventFrame (const Promise * pp , EventFrame * prev_frame )
39553976{
39563977 assert (pp != NULL );
3957- return EventFrameCreate ("promise" , PromiseGetPromiseType (pp ), PromiseGetBundle (pp )-> source_path , pp -> offset );
3978+ char * id = StringFormat ("%s:%ld/%s_%s" , PromiseGetBundle (pp )-> source_path , pp -> offset .line , "promise" , pp -> parent_section -> promise_type );
3979+ return EventFrameCreate (PromiseGetBundle (pp )-> source_path , "promise" , pp -> parent_section -> promise_type , "x" , "x" , pp -> offset , prev_frame , id );
39583980}
39593981
3960- static EventFrame * FunctionToEventFrame (const FnCall * fp )
3982+ EventFrame * FunctionToEventFrame (const FnCall * fp , EventFrame * prev_frame )
39613983{
39623984 assert (fp != NULL );
3963- return EventFrameCreate ("function" , fp -> name , PromiseGetBundle (fp -> caller )-> source_path , fp -> caller -> offset );
3985+ char * id = StringFormat ("%s:%ld/%s_%s" , PromiseGetBundle (fp -> caller )-> source_path , fp -> caller -> offset .line , "function" , fp -> name );
3986+ return EventFrameCreate (PromiseGetBundle (fp -> caller )-> source_path , "function" , "x" , "x" , fp -> name , fp -> caller -> offset , prev_frame , id );
39643987}
39653988
3966- void EvalContextAddFunctionEvent (EvalContext * ctx , const FnCall * fp , int64_t start )
3989+ void EvalContextSetProfiling (EvalContext * ctx , bool profiling )
39673990{
39683991 assert (ctx != NULL );
3969- if (ctx -> profiling )
3970- {
3971- EventFrame * event = FunctionToEventFrame (fp );
3972- int64_t end = EvalContextEventStart ();
3973- assert (end >= start ); /* sanity check */
3974- event -> elapsed = end - start ;
3975- SeqAppend (ctx -> profiler .events , event );
3976- }
3992+ ctx -> profiling = profiling ;
39773993}
39783994
3979- int64_t EvalContextEventStart ( )
3995+ bool EvalContextGetProfiling ( EvalContext * ctx )
39803996{
3981- struct timespec ts ;
3982- #ifdef CLOCK_MONOTONIC
3983- clock_gettime (CLOCK_MONOTONIC , & ts );
3984- #else
3985- // As in libcfnet/net.c some OS-es don't have monotonic clock, realtime clock is best we can do.
3986- clock_gettime (CLOCK_REALTIME , & ts );
3987- #endif
3988- return ts .tv_sec * 1000000000LL + ts .tv_nsec ;
3997+ assert (ctx != NULL );
3998+ return ctx -> profiling ;
39893999}
39904000
39914001void EvalContextProfilingStart (EvalContext * ctx )
39924002{
39934003 assert (ctx != NULL );
3994- ctx -> profiler .elapsed = EvalContextEventStart ();
3995- }
3996-
3997- static HashMap * SumEventFrames (Seq * events )
3998- {
3999- HashMap * map = HashMapNew ((MapHashFn ) StringHash , (MapKeyEqualFn ) StringEqual , NULL , NULL , 10 );
4000-
4001- size_t length = SeqLength (events );
4002- EventFrame * curr ;
4003- EventFrame * prev ;
4004- MapKeyValue * mkv ;
4005- for (int i = 0 ; i < length ; i ++ )
4006- {
4007- curr = SeqAt (events , i );
4008- mkv = HashMapGet (map , curr -> id );
4009-
4010- if (mkv == NULL )
4011- {
4012- HashMapInsert (map , curr -> id , curr );
4013- continue ;
4014- }
4015- prev = mkv -> value ;
4016- prev -> elapsed += curr -> elapsed ;
4017- }
4018-
4019- return map ;
4004+ ctx -> elapsed = EvalContextEventStart ();
40204005}
40214006
4022- void EvalContextProfilingEnd (EvalContext * ctx , const Policy * policy )
4007+ void EvalContextProfilingEnd (EvalContext * ctx )
40234008{
40244009 assert (ctx != NULL );
40254010
@@ -4029,35 +4014,46 @@ void EvalContextProfilingEnd(EvalContext *ctx, const Policy *policy)
40294014 }
40304015
40314016 int64_t end = EvalContextEventStart ();
4032- int64_t start = ctx -> profiler . elapsed ;
4017+ int64_t start = ctx -> elapsed ;
40334018 assert (end >= start ); /* sanity check */
40344019
4035- ctx -> profiler .elapsed = end - start ;
4036-
4037- HashMap * map = SumEventFrames (ctx -> profiler .events );
4038- JsonElement * profiling = JsonObjectCreate (2 );
4039-
4040- JsonElement * json_policy = PolicyToJson (policy );
4041- JsonObjectAppendObject (profiling , "policy" , json_policy );
4020+ ctx -> elapsed = end - start ;
40424021
40434022 JsonElement * events = JsonArrayCreate (10 );
40444023 {
4045- HashMapIterator iter = HashMapIteratorInit (map );
4046- MapKeyValue * mkv ;
4047- while ((mkv = HashMapIteratorNext (& iter )) != NULL )
4024+ for (size_t i = 0 ; i < SeqLength (ctx -> events ); i ++ )
40484025 {
4049- EventFrame * event = mkv -> value ;
4026+ EventFrame * event = SeqAt ( ctx -> events , i ) ;
40504027 JsonArrayAppendObject (events , EventToJson (event ));
40514028 }
40524029 }
4053- JsonObjectAppendArray (profiling , "events" , events );
4054-
40554030 // write
40564031 Writer * writer = FileWriter (stdout );
4057- JsonWrite (writer , profiling , 2 );
4032+ JsonWrite (writer , events , 2 );
40584033 WriterClose (writer );
40594034
4060- JsonDestroy (profiling );
4035+ JsonDestroy (events );
4036+ }
4037+
4038+ EventFrame * EvalContextGetLastEventFrame (EvalContext * ctx )
4039+ {
4040+ StackFrame * frame = LastStackFrameByEvent (ctx );
4041+
4042+ return (frame == NULL ) ? NULL : frame -> event ;
4043+ }
4044+
4045+ void EvalContextAppendEventFrame (EvalContext * ctx , EventFrame * event )
4046+ {
4047+ assert (ctx != NULL );
4048+ assert (event != NULL );
4049+
4050+ int64_t start = event -> elapsed ;
4051+ int64_t end = EvalContextEventStart ();
4052+ assert (end >= start ); /* sanity check */
4053+
4054+ event -> elapsed = end - start ;
4055+
4056+ SeqAppend (ctx -> events , event );
40614057}
40624058
40634059// ##############################################################
@@ -4127,4 +4123,4 @@ bool EvalContextIsClassicOrder(EvalContext *ctx, const Bundle *bp)
41274123 // The fallback is to use what is defined in body common control,
41284124 // or if not defined there either, default to true (normal order)
41294125 return (ctx -> common_eval_order != EVAL_ORDER_TOP_DOWN );
4130- }
4126+ }
0 commit comments