From 170aef20bc3a59d5139c2eff8794d9ba4c83a2e5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Tue, 29 Aug 2017 17:58:08 +0200 Subject: [PATCH] hooking: Add hook at global scope MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Actually the global scope only allows to trace log messages. Change-Id: Ib73edf2e3168311b2ad694d857e6647e34884313 Signed-off-by: José Bollo --- src/afb-hook.c | 157 ++++++++++++++++++++++++++++++++++++- src/afb-hook.h | 24 +++++- src/afb-trace.c | 81 ++++++++++++++++++- src/verbose.c | 10 ++- test/monitoring/monitor-base.css | 3 +- test/monitoring/monitor-demo.css | 1 + test/monitoring/monitor-pastel.css | 1 + test/monitoring/monitor.html | 5 ++ test/monitoring/monitor.js | 1 + 9 files changed, 271 insertions(+), 12 deletions(-) diff --git a/src/afb-hook.c b/src/afb-hook.c index a07d8426..14076281 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -90,6 +90,17 @@ struct afb_hook_evt { void *closure; /**< closure for callbacks */ }; +/** + * Definition of a hook for global + */ +struct afb_hook_global { + struct afb_hook_global *next; /**< next hook */ + unsigned refcount; /**< reference count */ + unsigned flags; /**< hook flags */ + struct afb_hook_global_itf *itf; /**< interface of hook */ + void *closure; /**< closure for callbacks */ +}; + /* synchronisation across threads */ static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; @@ -105,6 +116,9 @@ static struct afb_hook_svc *list_of_svc_hooks = NULL; /* list of hooks for evt */ static struct afb_hook_evt *list_of_evt_hooks = NULL; +/* list of hooks for global */ +static struct afb_hook_global *list_of_global_hooks = NULL; + /* hook id */ static unsigned next_hookid = 0; @@ -1159,7 +1173,7 @@ static struct afb_hook_evt_itf hook_evt_default_itf = { }; /****************************************************************************** - * section: hooks for tracing service interface (evt) + * section: hooks for tracing events interface (evt) *****************************************************************************/ #define _HOOK_EVT_(what,...) \ @@ -1300,3 +1314,144 @@ void afb_hook_unref_evt(struct afb_hook_evt *hook) } } } + +/****************************************************************************** + * section: default callbacks for globals (global) + *****************************************************************************/ + +static void _hook_global_(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + _hook_("global", format, ap); + va_end(ap); +} + +static void hook_global_vverbose_default_cb(void *closure, const struct afb_hookid *hookid, int level, const char *file, int line, const char *func, const char *fmt, va_list args) +{ + int len; + char *msg; + va_list ap; + + va_copy(ap, args); + len = vasprintf(&msg, fmt, ap); + va_end(ap); + + if (len < 0) + _hook_global_("vverbose(%d, %s, %d, %s) -> %s ? ? ?", level, file, line, func, fmt); + else { + _hook_global_("vverbose(%d, %s, %d, %s) -> %s", level, file, line, func, msg); + free(msg); + } +} + +static struct afb_hook_global_itf hook_global_default_itf = { + .hook_global_vverbose = hook_global_vverbose_default_cb +}; + +/****************************************************************************** + * section: hooks for tracing globals (global) + *****************************************************************************/ + +#define _HOOK_GLOBAL_(what,...) \ + struct afb_hook_global *hook; \ + struct afb_hookid hookid; \ + pthread_rwlock_rdlock(&rwlock); \ + init_hookid(&hookid); \ + hook = list_of_global_hooks; \ + while (hook) { \ + if (hook->itf->hook_global_##what \ + && (hook->flags & afb_hook_flag_global_##what) != 0) { \ + hook->itf->hook_global_##what(hook->closure, &hookid, __VA_ARGS__); \ + } \ + hook = hook->next; \ + } \ + pthread_rwlock_unlock(&rwlock); + +static void afb_hook_global_vverbose(int level, const char *file, int line, const char *func, const char *fmt, va_list args) +{ + _HOOK_GLOBAL_(vverbose, level, file ?: "?", line, func ?: "?", fmt, args); +} + +/****************************************************************************** + * section: hooking globals (global) + *****************************************************************************/ + +static void update_global() +{ + struct afb_hook_global *hook; + int flags = 0; + + pthread_rwlock_rdlock(&rwlock); + hook = list_of_global_hooks; + while (hook) { + flags = hook->flags; + hook = hook->next; + } + verbose_observer = (flags & afb_hook_flag_global_vverbose) ? afb_hook_global_vverbose : NULL; + pthread_rwlock_unlock(&rwlock); +} + +struct afb_hook_global *afb_hook_create_global(int flags, struct afb_hook_global_itf *itf, void *closure) +{ + struct afb_hook_global *hook; + + /* alloc the result */ + hook = calloc(1, sizeof *hook); + if (hook == NULL) + return NULL; + + /* initialise the rest */ + hook->refcount = 1; + hook->flags = flags; + hook->itf = itf ? itf : &hook_global_default_itf; + hook->closure = closure; + + /* record the hook */ + pthread_rwlock_wrlock(&rwlock); + hook->next = list_of_global_hooks; + list_of_global_hooks = hook; + pthread_rwlock_unlock(&rwlock); + + /* update hooking */ + update_global(); + + /* returns it */ + return hook; +} + +struct afb_hook_global *afb_hook_addref_global(struct afb_hook_global *hook) +{ + pthread_rwlock_wrlock(&rwlock); + hook->refcount++; + pthread_rwlock_unlock(&rwlock); + return hook; +} + +void afb_hook_unref_global(struct afb_hook_global *hook) +{ + struct afb_hook_global **prv; + + if (hook) { + pthread_rwlock_wrlock(&rwlock); + if (--hook->refcount) + hook = NULL; + else { + /* unlink */ + prv = &list_of_global_hooks; + while (*prv && *prv != hook) + prv = &(*prv)->next; + if(*prv) + *prv = hook->next; + } + pthread_rwlock_unlock(&rwlock); + if (hook) { + /* free */ + free(hook); + + /* update hooking */ + update_global(); + } + } +} + diff --git a/src/afb-hook.h b/src/afb-hook.h index 8f7f61d1..43341242 100644 --- a/src/afb-hook.h +++ b/src/afb-hook.h @@ -32,6 +32,11 @@ struct afb_svc; struct afb_stored_req; struct sd_bus; struct sd_event; +struct afb_hook_xreq; +struct afb_hook_ditf; +struct afb_hook_svc; +struct afb_hook_evt; +struct afb_hook_global; /********************************************************* * section hookid @@ -45,7 +50,6 @@ struct afb_hookid /********************************************************* * section hooking xreq *********************************************************/ -struct afb_hook_xreq; /* individual flags */ #define afb_hook_flag_req_begin 0x000001 @@ -301,7 +305,23 @@ extern void afb_hook_evt_name(const char *evt, int id); extern void afb_hook_evt_drop(const char *evt, int id); extern int afb_hook_flags_evt(const char *name); -extern struct afb_hook_evt *afb_hook_create_evt(const char *name, int flags, struct afb_hook_evt_itf *itf, void *closure); +extern struct afb_hook_evt *afb_hook_create_evt(const char *pattern, int flags, struct afb_hook_evt_itf *itf, void *closure); extern struct afb_hook_evt *afb_hook_addref_evt(struct afb_hook_evt *hook); extern void afb_hook_unref_evt(struct afb_hook_evt *hook); +/********************************************************* +* section hooking global (global interface) +*********************************************************/ + +#define afb_hook_flag_global_vverbose 0x000001 + +#define afb_hook_flags_global_all (afb_hook_flag_global_vverbose) + +struct afb_hook_global_itf { + void (*hook_global_vverbose)(void *closure, const struct afb_hookid *hookid, int level, const char *file, int line, const char *function, const char *fmt, va_list args); +}; + +extern struct afb_hook_global *afb_hook_create_global(int flags, struct afb_hook_global_itf *itf, void *closure); +extern struct afb_hook_global *afb_hook_addref_global(struct afb_hook_global *hook); +extern void afb_hook_unref_global(struct afb_hook_global *hook); + diff --git a/src/afb-trace.c b/src/afb-trace.c index bc2de6d2..2d098407 100644 --- a/src/afb-trace.c +++ b/src/afb-trace.c @@ -98,6 +98,7 @@ enum trace_type Trace_Type_Ditf, /* ditf hooks */ Trace_Type_Svc, /* svc hooks */ Trace_Type_Evt, /* evt hooks */ + Trace_Type_Global, /* global hooks */ Trace_Type_Count /* count of types of hooks */ }; @@ -820,6 +821,60 @@ static struct afb_hook_evt_itf hook_evt_itf = { .hook_evt_drop = hook_evt_drop }; +/*******************************************************************************/ +/***** trace the globals *****/ +/*******************************************************************************/ + +static struct flag global_flags[] = { /* must be sorted by names */ + { "all", afb_hook_flags_global_all }, + { "vverbose", afb_hook_flag_global_vverbose }, +}; + +/* get the global value for flag of 'name' */ +static int get_global_flag(const char *name) +{ + return get_flag(name, global_flags, (int)(sizeof global_flags / sizeof *global_flags)); +} + +static void hook_global(void *closure, const struct afb_hookid *hookid, const char *action, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + emit(closure, hookid, "global", "{ss}", format, ap, "action", action); + va_end(ap); +} + +static void hook_global_vverbose(void *closure, const struct afb_hookid *hookid, int level, const char *file, int line, const char *function, const char *fmt, va_list args) +{ + struct json_object *pos; + int len; + char *msg; + va_list ap; + + pos = NULL; + msg = NULL; + + va_copy(ap, args); + len = vasprintf(&msg, fmt, ap); + va_end(ap); + + if (file) + wrap_json_pack(&pos, "{ss si ss*}", "file", file, "line", line, "function", function); + + hook_global(closure, hookid, "vverbose", "{si ss* ss? so*}", + "level", level, + "type", verbosity_level_name(level), + len < 0 ? "format" : "message", len < 0 ? fmt : msg, + "position", pos); + + free(msg); +} + +static struct afb_hook_global_itf hook_global_itf = { + .hook_global_vverbose = hook_global_vverbose, +}; + /*******************************************************************************/ /***** abstract types *****/ /*******************************************************************************/ @@ -856,7 +911,13 @@ abstracting[Trace_Type_Count] = .name = "event", .unref = (void(*)(void*))afb_hook_unref_evt, .get_flag = get_evt_flag - } + }, + [Trace_Type_Global] = + { + .name = "global", + .unref = (void(*)(void*))afb_hook_unref_global, + .get_flag = get_global_flag + }, }; /*******************************************************************************/ @@ -1149,6 +1210,9 @@ static void addhook(struct desc *desc, enum trace_type type) case Trace_Type_Evt: hook->handler = afb_hook_create_evt(desc->pattern, desc->flags[type], &hook_evt_itf, hook); break; + case Trace_Type_Global: + hook->handler = afb_hook_create_global(desc->flags[type], &hook_global_itf, hook); + break; default: break; } @@ -1214,17 +1278,22 @@ static void add_evt_flags(void *closure, struct json_object *object) add_flags(closure, object, Trace_Type_Evt); } +static void add_global_flags(void *closure, struct json_object *object) +{ + add_flags(closure, object, Trace_Type_Global); +} + /* add hooks */ static void add(void *closure, struct json_object *object) { int rc; struct desc desc; - struct json_object *request, *event, *daemon, *service, *sub; + struct json_object *request, *event, *daemon, *service, *sub, *global; memcpy (&desc, closure, sizeof desc); - request = event = daemon = service = sub = NULL; + request = event = daemon = service = sub = global = NULL; - rc = wrap_json_unpack(object, "{s?s s?s s?s s?s s?s s?s s?o s?o s?o s?o s?o}", + rc = wrap_json_unpack(object, "{s?s s?s s?s s?s s?s s?s s?o s?o s?o s?o s?o s?o}", "name", &desc.name, "tag", &desc.tag, "api", &desc.api, @@ -1235,6 +1304,7 @@ static void add(void *closure, struct json_object *object) "daemon", &daemon, "service", &service, "event", &event, + "global", &global, "for", &sub); if (!rc) { @@ -1261,6 +1331,9 @@ static void add(void *closure, struct json_object *object) if (event) wrap_json_optarray_for_all(event, add_evt_flags, &desc); + if (global) + wrap_json_optarray_for_all(global, add_global_flags, &desc); + /* apply */ if (sub) wrap_json_optarray_for_all(sub, add, &desc); diff --git a/src/verbose.c b/src/verbose.c index 2d60dfca..e0e38248 100644 --- a/src/verbose.c +++ b/src/verbose.c @@ -132,12 +132,16 @@ void verbose(int loglevel, const char *file, int line, const char *function, con void vverbose(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args) { - if (verbose_observer) { + void (*observer)(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args) = verbose_observer; + + if (!observer) + _vverbose_(loglevel, file, line, function, fmt, args); + else { va_list ap; va_copy(ap, args); - verbose_observer(loglevel, file, line, function, fmt, ap); + _vverbose_(loglevel, file, line, function, fmt, args); + observer(loglevel, file, line, function, fmt, ap); va_end(ap); } - _vverbose_(loglevel, file, line, function, fmt, args); } diff --git a/test/monitoring/monitor-base.css b/test/monitoring/monitor-base.css index f2de1d92..ff761ae7 100644 --- a/test/monitoring/monitor-base.css +++ b/test/monitoring/monitor-base.css @@ -88,8 +88,7 @@ body.on #params, body.on #connect, body.off #disconnect { display: none; } /*******************************************************************/ /* setting for traces */ -#apis .trace-evt { - visibility: hidden; +#apis .event, #apis .global { display: none; } diff --git a/test/monitoring/monitor-demo.css b/test/monitoring/monitor-demo.css index 87cf0a0e..1025b120 100644 --- a/test/monitoring/monitor-demo.css +++ b/test/monitoring/monitor-demo.css @@ -244,6 +244,7 @@ html { .traceevent.daemon, .trace-box.daemon { color: #5af; } .traceevent.service, .trace-box.service { color: #0f0; } .traceevent.event, .trace-box.event { color: #f52; } +.traceevent.global, .trace-box.global { color: white; } .traceevent.closed { max-height: 16px; diff --git a/test/monitoring/monitor-pastel.css b/test/monitoring/monitor-pastel.css index 0264bf52..d5cf3f6f 100644 --- a/test/monitoring/monitor-pastel.css +++ b/test/monitoring/monitor-pastel.css @@ -224,6 +224,7 @@ body { .traceevent.daemon, .trace-box.daemon { background: #fdf; } .traceevent.service, .trace-box.service { background: #ddf; } .traceevent.event, .trace-box.event { background: #dfd; } +.traceevent.global, .trace-box.global { background: #eee; } .traceevent.closed { max-height: 16px; diff --git a/test/monitoring/monitor.html b/test/monitoring/monitor.html index f22a62b2..e9572ba8 100644 --- a/test/monitoring/monitor.html +++ b/test/monitoring/monitor.html @@ -171,6 +171,11 @@
extra
all
+
+
trace globals:
+
no
+
all
+
diff --git a/test/monitoring/monitor.js b/test/monitoring/monitor.js index e1d4be5b..bee87e4b 100644 --- a/test/monitoring/monitor.js +++ b/test/monitoring/monitor.js @@ -445,6 +445,7 @@ function gottraceevent(obj) { service: function(r) { return r.api + "@" + r.action; }, daemon: function(r) { return r.api + ":" + r.action; }, event: function(r) { return r.name + "!" + r.action; }, + global: function(r) { return "$" + r.action; }, })[type](desc); var tab = makeobj(desc, 4); if ("data" in data) -- 2.16.6