@@ -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,20 @@ static StackFrame *LastStackFrameByType(const EvalContext *ctx, StackFrameType t
349342 return NULL ;
350343}
351344
345+ static StackFrame * LastStackFrameByEvent (const EvalContext * ctx )
346+ {
347+ for (size_t i = 0 ; i < SeqLength (ctx -> stack ); i ++ )
348+ {
349+ StackFrame * frame = LastStackFrame (ctx , i );
350+ if (frame -> event != NULL )
351+ {
352+ return frame ;
353+ }
354+ }
355+
356+ return NULL ;
357+ }
358+
352359static LogLevel AdjustLogLevel (LogLevel base , LogLevel adjust )
353360{
354361 if (adjust == -1 )
@@ -1110,8 +1117,8 @@ EvalContext *EvalContextNew(void)
11101117
11111118 ctx -> dump_reports = false;
11121119
1113- ctx -> profiler . events = SeqNew (20 , EventFrameDestroy );
1114- ctx -> profiler . elapsed = 0 ;
1120+ ctx -> events = SeqNew (20 , EventFrameDestroy );
1121+ ctx -> elapsed = 0 ;
11151122
11161123 // evaluation order
11171124 ctx -> common_eval_order = EVAL_ORDER_UNDEFINED ;
@@ -1164,7 +1171,7 @@ void EvalContextDestroy(EvalContext *ctx)
11641171 ctx -> remote_var_promises = NULL ;
11651172 }
11661173
1167- SeqDestroy (ctx -> profiler . events );
1174+ SeqDestroy (ctx -> events );
11681175 free (ctx );
11691176 }
11701177}
@@ -1349,20 +1356,19 @@ static StackFrame *StackFrameNew(StackFrameType type, bool inherit_previous)
13491356 frame -> inherits_previous = inherit_previous ;
13501357 frame -> path = NULL ;
13511358 frame -> override_immutable = false;
1352- frame -> start = EvalContextEventStart ();
13531359 frame -> event = NULL ;
13541360
13551361 return frame ;
13561362}
13571363
1358- static StackFrame * StackFrameNewBundle (const Bundle * owner , bool inherit_previous , bool profiling )
1364+ static StackFrame * StackFrameNewBundle (const Bundle * owner , bool inherit_previous , bool profiling , EventFrame * prev_event )
13591365{
13601366 StackFrame * frame = StackFrameNew (STACK_FRAME_TYPE_BUNDLE , inherit_previous );
13611367
13621368 frame -> data .bundle .owner = owner ;
13631369 frame -> data .bundle .classes = ClassTableNew ();
13641370 frame -> data .bundle .vars = VariableTableNew ();
1365- frame -> event = (profiling ) ? BundleToEventFrame (owner ) : NULL ;
1371+ frame -> event = (profiling ) ? BundleToEventFrame (owner , prev_event ) : NULL ;
13661372
13671373 return frame ;
13681374}
@@ -1386,12 +1392,12 @@ static StackFrame *StackFrameNewBundleSection(const BundleSection *owner)
13861392 return frame ;
13871393}
13881394
1389- static StackFrame * StackFrameNewPromise (const Promise * owner , bool profiling )
1395+ static StackFrame * StackFrameNewPromise (const Promise * owner , bool profiling , EventFrame * prev_event )
13901396{
13911397 StackFrame * frame = StackFrameNew (STACK_FRAME_TYPE_PROMISE , true);
13921398
13931399 frame -> data .promise .owner = owner ;
1394- frame -> event = (profiling ) ? PromiseToEventFrame (owner ) : NULL ;
1400+ frame -> event = (profiling ) ? PromiseToEventFrame (owner , prev_event ) : NULL ;
13951401
13961402 return frame ;
13971403}
@@ -1443,7 +1449,8 @@ void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, cons
14431449 assert (ctx != NULL );
14441450 assert (!LastStackFrame (ctx , 0 ) || LastStackFrame (ctx , 0 )-> type == STACK_FRAME_TYPE_PROMISE_ITERATION );
14451451
1446- EvalContextStackPushFrame (ctx , StackFrameNewBundle (owner , inherits_previous , ctx -> profiling ));
1452+ StackFrame * frame = StackFrameNewBundle (owner , inherits_previous , ctx -> profiling , EvalContextGetLastEventFrame (ctx ));
1453+ EvalContextStackPushFrame (ctx , frame );
14471454
14481455 if (RlistLen (args ) > 0 )
14491456 {
@@ -1523,8 +1530,7 @@ void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner)
15231530
15241531 EvalContextVariableClearMatch (ctx );
15251532
1526- StackFrame * frame = StackFrameNewPromise (owner , ctx -> profiling );
1527-
1533+ StackFrame * frame = StackFrameNewPromise (owner , ctx -> profiling , EvalContextGetLastEventFrame (ctx ));
15281534 EvalContextStackPushFrame (ctx , frame );
15291535
15301536 // create an empty table
@@ -1615,15 +1621,11 @@ void EvalContextStackPopFrame(EvalContext *ctx)
16151621
16161622 StackFrame * last_frame = LastStackFrame (ctx , 0 );
16171623 StackFrameType last_frame_type = last_frame -> type ;
1618- int64_t start = last_frame -> start ;
1619- int64_t end = EvalContextEventStart ();
16201624
16211625 EventFrame * last_event = last_frame -> event ;
16221626 if (last_event != NULL )
16231627 {
1624- assert (end >= start ); /* sanity check */
1625- last_event -> elapsed = end - start ;
1626- SeqAppend (ctx -> profiler .events , last_event );
1628+ EvalContextAppendEventFrame (ctx , last_event );
16271629 }
16281630
16291631 switch (last_frame_type )
@@ -3892,22 +3894,40 @@ bool EvalContextOverrideImmutableGet(EvalContext *ctx)
38923894
38933895// ##############################################################
38943896
3895- void EvalContextSetProfiling ( EvalContext * ctx , bool profiling )
3897+ static int64_t EvalContextEventStart ( )
38963898{
3897- assert (ctx != NULL );
3898- ctx -> profiling = profiling ;
3899+ struct timespec ts ;
3900+ #ifdef CLOCK_MONOTONIC
3901+ clock_gettime (CLOCK_MONOTONIC , & ts );
3902+ #else
3903+ // As in libcfnet/net.c some OS-es don't have monotonic clock, realtime clock is best we can do.
3904+ clock_gettime (CLOCK_REALTIME , & ts );
3905+ #endif
3906+ return ts .tv_sec * 1000000000LL + ts .tv_nsec ;
38993907}
39003908
3901- static EventFrame * EventFrameCreate (char * type , const char * name , const char * source , SourceOffset offset )
3909+ static EventFrame * EventFrameCreate (const char * source ,
3910+ char * component ,
3911+ char * type ,
3912+ const char * ns ,
3913+ const char * name ,
3914+ SourceOffset offset ,
3915+ EventFrame * prev ,
3916+ char * id
3917+ )
39023918{
39033919 EventFrame * event = (EventFrame * ) xmalloc (sizeof (EventFrame ));
3920+ event -> elapsed = EvalContextEventStart ();
39043921
3922+ event -> source = GetAbsolutePath (source );
3923+ event -> component = component ;
39053924 event -> type = type ;
3925+ event -> ns = SafeStringDuplicate (ns );
39063926 event -> name = SafeStringDuplicate (name );
3907- event -> filename = GetAbsolutePath (source );
3908- event -> elapsed = 0 ;
39093927 event -> offset = offset ;
3910- event -> id = StringFormat ("%s_%s_%s_%ld_%ld" , type , name , source , offset .start , offset .line );
3928+
3929+ event -> id = id ;
3930+ event -> callstack = (prev != NULL ) ? StringFormat ("%s;%s" , prev -> callstack , event -> id ) : SafeStringDuplicate (event -> id );
39113931
39123932 return event ;
39133933}
@@ -3916,9 +3936,12 @@ static void EventFrameDestroy(EventFrame *event)
39163936{
39173937 if (event != NULL )
39183938 {
3919- free (event -> filename );
3920- free (event -> id );
3939+ free (event -> source );
3940+ free (event -> ns );
39213941 free (event -> name );
3942+
3943+ free (event -> id );
3944+ free (event -> callstack );
39223945 free (event );
39233946 }
39243947}
@@ -3928,11 +3951,14 @@ static JsonElement *EventToJson(EventFrame *event)
39283951 assert (event != NULL );
39293952 JsonElement * json_event = JsonObjectCreate (10 );
39303953
3954+ JsonObjectAppendString (json_event , "component" , event -> component );
39313955 JsonObjectAppendString (json_event , "type" , event -> type );
39323956 JsonObjectAppendString (json_event , "name" , event -> name );
3933- JsonObjectAppendString (json_event , "filename" , event -> filename );
3957+ JsonObjectAppendString (json_event , "namespace" , event -> ns );
3958+ JsonObjectAppendString (json_event , "source" , event -> source );
39343959 JsonObjectAppendString (json_event , "id" , event -> id );
39353960 JsonObjectAppendInteger64 (json_event , "elapsed" , event -> elapsed );
3961+ JsonObjectAppendString (json_event , "callstack" , event -> callstack );
39363962
39373963 JsonElement * offset = JsonObjectCreate (4 );
39383964 JsonObjectAppendInteger (offset , "start" , event -> offset .start );
@@ -3945,81 +3971,46 @@ static JsonElement *EventToJson(EventFrame *event)
39453971 return json_event ;
39463972}
39473973
3948- static EventFrame * BundleToEventFrame (const Bundle * bp )
3974+ EventFrame * BundleToEventFrame (const Bundle * bp , EventFrame * prev_frame )
39493975{
39503976 assert (bp != NULL );
3951- return EventFrameCreate ("bundle" , bp -> name , bp -> source_path , bp -> offset );
3977+ char * id = StringFormat ("%s:%ld/%s_%s_%s:%s" , GetAbsolutePath (bp -> source_path ), bp -> offset .line , "bundle" , bp -> type , bp -> ns , bp -> name );
3978+ return EventFrameCreate (bp -> source_path , "bundle" , bp -> type , bp -> ns , bp -> name , bp -> offset , prev_frame , id );
39523979}
39533980
3954- static EventFrame * PromiseToEventFrame (const Promise * pp )
3981+ EventFrame * PromiseToEventFrame (const Promise * pp , EventFrame * prev_frame )
39553982{
39563983 assert (pp != NULL );
3957- return EventFrameCreate ("promise" , PromiseGetPromiseType (pp ), PromiseGetBundle (pp )-> source_path , pp -> offset );
3984+ char * id = StringFormat ("%s:%ld/%s_%s" , PromiseGetBundle (pp )-> source_path , pp -> offset .line , "promise" , pp -> parent_section -> promise_type );
3985+ return EventFrameCreate (PromiseGetBundle (pp )-> source_path , "promise" , pp -> parent_section -> promise_type , "x" , "x" , pp -> offset , prev_frame , id );
39583986}
39593987
3960- static EventFrame * FunctionToEventFrame (const FnCall * fp )
3988+ EventFrame * FunctionToEventFrame (const FnCall * fp , EventFrame * prev_frame )
39613989{
39623990 assert (fp != NULL );
3963- return EventFrameCreate ("function" , fp -> name , PromiseGetBundle (fp -> caller )-> source_path , fp -> caller -> offset );
3991+ char * id = StringFormat ("%s:%ld/%s_%s" , PromiseGetBundle (fp -> caller )-> source_path , fp -> caller -> offset .line , "function" , fp -> name );
3992+ return EventFrameCreate (PromiseGetBundle (fp -> caller )-> source_path , "function" , "x" , "x" , fp -> name , fp -> caller -> offset , prev_frame , id );
39643993}
39653994
3966- void EvalContextAddFunctionEvent (EvalContext * ctx , const FnCall * fp , int64_t start )
3995+ void EvalContextSetProfiling (EvalContext * ctx , bool profiling )
39673996{
39683997 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- }
3998+ ctx -> profiling = profiling ;
39773999}
39784000
3979- int64_t EvalContextEventStart ( )
4001+ bool EvalContextGetProfiling ( EvalContext * ctx )
39804002{
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 ;
4003+ assert (ctx != NULL );
4004+ return ctx -> profiling ;
39894005}
39904006
39914007void EvalContextProfilingStart (EvalContext * ctx )
39924008{
39934009 assert (ctx != NULL );
3994- ctx -> profiler . elapsed = EvalContextEventStart ();
4010+ ctx -> elapsed = EvalContextEventStart ();
39954011}
39964012
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 ;
4020- }
4021-
4022- void EvalContextProfilingEnd (EvalContext * ctx , const Policy * policy )
4013+ void EvalContextProfilingEnd (EvalContext * ctx )
40234014{
40244015 assert (ctx != NULL );
40254016
@@ -4029,35 +4020,48 @@ void EvalContextProfilingEnd(EvalContext *ctx, const Policy *policy)
40294020 }
40304021
40314022 int64_t end = EvalContextEventStart ();
4032- int64_t start = ctx -> profiler . elapsed ;
4023+ int64_t start = ctx -> elapsed ;
40334024 assert (end >= start ); /* sanity check */
40344025
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 );
4026+ ctx -> elapsed = end - start ;
40424027
40434028 JsonElement * events = JsonArrayCreate (10 );
40444029 {
4045- HashMapIterator iter = HashMapIteratorInit (map );
4046- MapKeyValue * mkv ;
4047- while ((mkv = HashMapIteratorNext (& iter )) != NULL )
4030+ for (size_t i = 0 ; i < SeqLength (ctx -> events ); i ++ )
40484031 {
4049- EventFrame * event = mkv -> value ;
4032+ EventFrame * event = SeqAt ( ctx -> events , i ) ;
40504033 JsonArrayAppendObject (events , EventToJson (event ));
40514034 }
40524035 }
4053- JsonObjectAppendArray (profiling , "events" , events );
4054-
40554036 // write
40564037 Writer * writer = FileWriter (stdout );
4057- JsonWrite (writer , profiling , 2 );
4038+ JsonWrite (writer , events , 2 );
40584039 WriterClose (writer );
40594040
4060- JsonDestroy (profiling );
4041+ JsonDestroy (events );
4042+ }
4043+
4044+ EventFrame * EvalContextGetLastEventFrame (EvalContext * ctx )
4045+ {
4046+ StackFrame * frame = LastStackFrameByEvent (ctx );
4047+
4048+ if (frame == NULL )
4049+ {
4050+ return NULL ;
4051+ }
4052+
4053+ return frame -> event ;
4054+ }
4055+
4056+ void EvalContextAppendEventFrame (EvalContext * ctx , EventFrame * event )
4057+ {
4058+ int64_t start = event -> elapsed ;
4059+ int64_t end = EvalContextEventStart ();
4060+ assert (end >= start ); /* sanity check */
4061+
4062+ event -> elapsed = end - start ;
4063+
4064+ SeqAppend (ctx -> events , event );
40614065}
40624066
40634067// ##############################################################
@@ -4127,4 +4131,4 @@ bool EvalContextIsClassicOrder(EvalContext *ctx, const Bundle *bp)
41274131 // The fallback is to use what is defined in body common control,
41284132 // or if not defined there either, default to true (normal order)
41294133 return (ctx -> common_eval_order != EVAL_ORDER_TOP_DOWN );
4130- }
4134+ }
0 commit comments