aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2017-08-29 17:58:08 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2017-08-29 18:02:15 +0200
commit170aef20bc3a59d5139c2eff8794d9ba4c83a2e5 (patch)
tree8354a7496e390e03e6fbdd0e6e663c4228326cb7
parent6d8d9dc5aad148a74bcdf8965bee9f7058a08166 (diff)
hooking: Add hook at global scope
Actually the global scope only allows to trace log messages. Change-Id: Ib73edf2e3168311b2ad694d857e6647e34884313 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/afb-hook.c157
-rw-r--r--src/afb-hook.h24
-rw-r--r--src/afb-trace.c81
-rw-r--r--src/verbose.c10
-rw-r--r--test/monitoring/monitor-base.css3
-rw-r--r--test/monitoring/monitor-demo.css1
-rw-r--r--test/monitoring/monitor-pastel.css1
-rw-r--r--test/monitoring/monitor.html5
-rw-r--r--test/monitoring/monitor.js1
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 */
};
@@ -821,6 +822,60 @@ static struct afb_hook_evt_itf hook_evt_itf = {
};
/*******************************************************************************/
+/***** 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 @@
<div class="trace-item"><input type="radio" value="extra">extra</input></div>
<div class="trace-item"><input type="radio" value="all">all</input></div>
</div>
+ <div class="trace-box global" data-trace="global">
+ <div class="trace-title">trace globals:</div>
+ <div class="trace-item"><input type="radio" value="no" checked>no</input></div>
+ <div class="trace-item"><input type="radio" value="all">all</input></div>
+ </div>
</div>
</template>
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)