aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-05-10 20:08:01 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-05-10 20:10:02 +0200
commitc1f06ac28fef5498952994e0399312b1fc567f22 (patch)
treead71f80bb08bfe20ff33880509263d78f334409b /src/util
parentd1d18e6492708a0ce758ddd8c509f21b0ecbf6a0 (diff)
downloadgnunet-c1f06ac28fef5498952994e0399312b1fc567f22.tar.gz
gnunet-c1f06ac28fef5498952994e0399312b1fc567f22.zip
Implement asynchronous scope identifiers.
Without entering an asynchronous scope, logs are the same before. When entering an asynchronous scope (either thread-based of scheduler/task-based), all log lines within an asynchronous scope contain its ID. Currently this is only used in GNU Taler, for debugging requests across multiple services. This allows us to get all log lines pertaining to a particular request for a user or another service.
Diffstat (limited to 'src/util')
-rw-r--r--src/util/common_logging.c83
-rw-r--r--src/util/scheduler.c43
2 files changed, 125 insertions, 1 deletions
diff --git a/src/util/common_logging.c b/src/util/common_logging.c
index 77a595878..5052134f8 100644
--- a/src/util/common_logging.c
+++ b/src/util/common_logging.c
@@ -95,6 +95,13 @@ struct CustomLogger
95 void *logger_cls; 95 void *logger_cls;
96}; 96};
97 97
98
99/**
100 * Asynchronous scope of the current thread, or NULL if we have not
101 * entered an async scope yet.
102 */
103static __thread struct GNUNET_AsyncScopeSave current_async_scope;
104
98/** 105/**
99 * The last "bulk" error message that we have been logging. 106 * The last "bulk" error message that we have been logging.
100 * Note that this message maybe truncated to the first BULK_TRACK_SIZE 107 * Note that this message maybe truncated to the first BULK_TRACK_SIZE
@@ -838,6 +845,28 @@ output_message (enum GNUNET_ErrorType kind,
838 "* %s", 845 "* %s",
839 msg); 846 msg);
840 } 847 }
848 else if (GNUNET_YES == current_async_scope.have_scope)
849 {
850 static GNUNET_THREAD_LOCAL char id_buf[27];
851 char *end;
852
853 /* We're logging, so skip_log must be currently 0. */
854 skip_log = 100;
855 end = GNUNET_STRINGS_data_to_string (&current_async_scope.scope_id,
856 sizeof (struct GNUNET_AsyncScopeId),
857 id_buf,
858 sizeof (id_buf) - 1);
859 GNUNET_assert (NULL != end);
860 *end = '\0';
861 skip_log = 0;
862 FPRINTF (GNUNET_stderr,
863 "%s %s(%s) %s %s",
864 datestr,
865 comp,
866 id_buf,
867 GNUNET_error_type_to_string (kind),
868 msg);
869 }
841 else 870 else
842 { 871 {
843 FPRINTF (GNUNET_stderr, 872 FPRINTF (GNUNET_stderr,
@@ -1548,6 +1577,60 @@ GNUNET_log_config_invalid (enum GNUNET_ErrorType kind,
1548 1577
1549 1578
1550/** 1579/**
1580 * Set the async scope for the current thread.
1581 *
1582 * @param aid the async scope identifier
1583 * @param old_scope[out] location to save the old scope
1584 */
1585void
1586GNUNET_async_scope_enter (const struct GNUNET_AsyncScopeId *aid,
1587 struct GNUNET_AsyncScopeSave *old_scope)
1588{
1589 *old_scope = current_async_scope;
1590 current_async_scope.have_scope = GNUNET_YES;
1591 current_async_scope.scope_id = *aid;
1592}
1593
1594
1595/**
1596 * Clear the current thread's async scope.
1597 *
1598 * @param old_scope scope to restore
1599 */
1600void
1601GNUNET_async_scope_restore (struct GNUNET_AsyncScopeSave *old_scope)
1602{
1603 current_async_scope = *old_scope;
1604}
1605
1606
1607/**
1608 * Generate a fresh async scope identifier.
1609 *
1610 * @param[out] aid_ret pointer to where the result is stored
1611 */
1612void
1613GNUNET_async_scope_fresh (struct GNUNET_AsyncScopeId *aid_ret)
1614{
1615 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
1616 aid_ret,
1617 sizeof (struct GNUNET_AsyncScopeId));
1618}
1619
1620
1621/**
1622 * Get the current async scope.
1623 *
1624 * @param[out] scope_ret pointer to where the result is stored
1625 */
1626void
1627GNUNET_async_scope_get (struct GNUNET_AsyncScopeSave *scope_ret)
1628{
1629 *scope_ret = current_async_scope;
1630}
1631
1632
1633/**
1551 * Initializer 1634 * Initializer
1552 */ 1635 */
1553void __attribute__ ((constructor)) 1636void __attribute__ ((constructor))
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 2ddbb8c60..c818e91ee 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -241,6 +241,11 @@ struct GNUNET_SCHEDULER_Task
241 int num_backtrace_strings; 241 int num_backtrace_strings;
242#endif 242#endif
243 243
244 /**
245 * Asynchronous scope of the task that scheduled this scope,
246 */
247 struct GNUNET_AsyncScopeSave scope;
248
244}; 249};
245 250
246 251
@@ -1105,6 +1110,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
1105 GNUNET_assert (NULL != scheduler_driver); 1110 GNUNET_assert (NULL != scheduler_driver);
1106 GNUNET_assert (NULL != task); 1111 GNUNET_assert (NULL != task);
1107 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1112 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1113 GNUNET_async_scope_get (&t->scope);
1108 t->callback = task; 1114 t->callback = task;
1109 t->callback_cls = task_cls; 1115 t->callback_cls = task_cls;
1110 t->read_fd = -1; 1116 t->read_fd = -1;
@@ -1293,6 +1299,7 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task,
1293 GNUNET_assert (NULL != scheduler_driver); 1299 GNUNET_assert (NULL != scheduler_driver);
1294 GNUNET_assert (NULL != task); 1300 GNUNET_assert (NULL != task);
1295 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1301 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1302 GNUNET_async_scope_get (&t->scope);
1296 t->callback = task; 1303 t->callback = task;
1297 t->callback_cls = task_cls; 1304 t->callback_cls = task_cls;
1298 t->read_fd = -1; 1305 t->read_fd = -1;
@@ -1411,6 +1418,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1411 GNUNET_assert (NULL != scheduler_driver); 1418 GNUNET_assert (NULL != scheduler_driver);
1412 GNUNET_assert (NULL != task); 1419 GNUNET_assert (NULL != task);
1413 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1420 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1421 GNUNET_async_scope_get (&t->scope);
1414 init_fd_info (t, 1422 init_fd_info (t,
1415 &read_nh, 1423 &read_nh,
1416 read_nh ? 1 : 0, 1424 read_nh ? 1 : 0,
@@ -1882,6 +1890,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1882 task, 1890 task,
1883 task_cls); 1891 task_cls);
1884 t = GNUNET_new (struct GNUNET_SCHEDULER_Task); 1892 t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1893 GNUNET_async_scope_get (&t->scope);
1885 init_fd_info (t, 1894 init_fd_info (t,
1886 read_nhandles, 1895 read_nhandles,
1887 read_nhandles_len, 1896 read_nhandles_len,
@@ -2114,7 +2123,15 @@ GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh)
2114 "Running task %p\n", 2123 "Running task %p\n",
2115 pos); 2124 pos);
2116 GNUNET_assert (NULL != pos->callback); 2125 GNUNET_assert (NULL != pos->callback);
2117 pos->callback (pos->callback_cls); 2126 {
2127 struct GNUNET_AsyncScopeSave old_scope;
2128 if (pos->scope.have_scope)
2129 GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2130 else
2131 GNUNET_async_scope_get (&old_scope);
2132 pos->callback (pos->callback_cls);
2133 GNUNET_async_scope_restore (&old_scope);
2134 }
2118 if (NULL != pos->fds) 2135 if (NULL != pos->fds)
2119 { 2136 {
2120 int del_result = scheduler_driver->del (scheduler_driver->cls, pos); 2137 int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
@@ -2513,4 +2530,28 @@ GNUNET_SCHEDULER_driver_select ()
2513} 2530}
2514 2531
2515 2532
2533/**
2534 * Change the async scope for the currently executing task and (transitively)
2535 * for all tasks scheduled by the current task after calling this function.
2536 * Nested tasks can begin their own nested async scope.
2537 *
2538 * Once the current task is finished, the async scope ID is reset to
2539 * its previous value.
2540 *
2541 * Must only be called from a running task.
2542 *
2543 * @param aid the asynchronous scope id to enter
2544 */
2545void
2546GNUNET_SCHEDULER_begin_async_scope (struct GNUNET_AsyncScopeId *aid)
2547{
2548 struct GNUNET_AsyncScopeSave dummy_old_scope;
2549
2550 GNUNET_assert (NULL != active_task);
2551 /* Since we're in a task, the context will be automatically
2552 restored by the scheduler. */
2553 GNUNET_async_scope_enter (aid, &dummy_old_scope);
2554}
2555
2556
2516/* end of scheduler.c */ 2557/* end of scheduler.c */