summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--changes/bug212935
-rw-r--r--changes/ticket138027
-rw-r--r--configure.ac10
-rw-r--r--doc/HACKING/Tracing.md91
-rw-r--r--src/common/compat_threads.c45
-rw-r--r--src/common/compat_threads.h14
-rw-r--r--src/common/compress.c8
-rw-r--r--src/common/compress.h2
-rw-r--r--src/common/compress_lzma.c13
-rw-r--r--src/common/compress_lzma.h2
-rw-r--r--src/common/compress_zlib.c14
-rw-r--r--src/common/compress_zlib.h2
-rw-r--r--src/common/compress_zstd.c13
-rw-r--r--src/common/compress_zstd.h2
-rw-r--r--src/include.am1
-rw-r--r--src/or/include.am1
-rw-r--r--src/or/main.c1
-rw-r--r--src/or/relay.c3
-rw-r--r--src/test/bench.c1
-rw-r--r--src/test/fuzz/fuzzing_common.c1
-rw-r--r--src/test/include.am5
-rw-r--r--src/test/testing_common.c1
-rw-r--r--src/trace/debug.h25
-rw-r--r--src/trace/events.h45
-rw-r--r--src/trace/include.am20
26 files changed, 324 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore
index f8d6e13da7..68bad5f113 100644
--- a/.gitignore
+++ b/.gitignore
@@ -125,6 +125,9 @@ uptime-*.json
/src/Makefile
/src/Makefile.in
+# /src/trace
+/src/trace/libor-trace.a
+
# /src/common/
/src/common/Makefile
/src/common/Makefile.in
diff --git a/changes/bug21293 b/changes/bug21293
new file mode 100644
index 0000000000..23a7547951
--- /dev/null
+++ b/changes/bug21293
@@ -0,0 +1,5 @@
+ o Minor bugfixes (cell, logging):
+ - Downgrade a log statement from bug to protocol warning because there is
+ at least one use case where it can be triggered by a buggy tor
+ implementation on the Internet for instance. Fixes bug 21293; bugfix on
+ tor-0.1.1.14-alpha.
diff --git a/changes/ticket13802 b/changes/ticket13802
new file mode 100644
index 0000000000..35cd2b5b68
--- /dev/null
+++ b/changes/ticket13802
@@ -0,0 +1,7 @@
+ o Minor features (testing):
+ - Add a general event-tracing instrumentation support to Tor. This
+ subsystem will enable developers and researchers to add fine-grained
+ instrumentation to their Tor instances, for use when examining Tor
+ network performance issues. There are no trace events yet, and
+ event-tracing is off by default unless enabled at compile time.
+ Implements ticket 13802.
diff --git a/configure.ac b/configure.ac
index c7960fa4ed..ff917354a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,6 +189,16 @@ AC_ARG_ENABLE(seccomp,
AC_ARG_ENABLE(libscrypt,
AS_HELP_STRING(--disable-libscrypt, [do not attempt to use libscrypt]))
+dnl Enable event tracing which are transformed to debug log statement.
+AC_ARG_ENABLE(event-tracing-debug,
+ AS_HELP_STRING(--enable-event-tracing-debug, [build with event tracing to debug log]))
+AM_CONDITIONAL([USE_EVENT_TRACING_DEBUG], [test "x$enable_event_tracing_debug" = "xyes"])
+
+if test x$enable_event_tracing_debug = xyes; then
+ AC_DEFINE([USE_EVENT_TRACING_DEBUG], [1], [Tracing framework to log debug])
+ AC_DEFINE([TOR_EVENT_TRACING_ENABLED], [1], [Compile the event tracing instrumentation])
+fi
+
dnl check for the correct "ar" when cross-compiling.
dnl (AM_PROG_AR was new in automake 1.11.2, which we do not yet require,
dnl so kludge up a replacement for the case where it isn't there yet.)
diff --git a/doc/HACKING/Tracing.md b/doc/HACKING/Tracing.md
new file mode 100644
index 0000000000..a5fb5165e2
--- /dev/null
+++ b/doc/HACKING/Tracing.md
@@ -0,0 +1,91 @@
+# Tracing #
+
+This document describes how the event tracing subsystem works in tor so
+developers can add events to the code base but also hook them to an event
+tracing framework.
+
+## Basics ###
+
+Event tracing is seperated in two concepts, trace events and a tracer. The
+tracing subsystem can be found in `src/trace`. The `events.h` header file is
+the main file that maps the different tracers to trace events.
+
+### Events ###
+
+A trace event is basically a function from which we can pass any data that
+we want to collect. In addition, we specify a context for the event such as
+a subsystem and an event name.
+
+A trace event in tor has the following standard format:
+
+ tor_trace(subsystem, event\_name, args...)
+
+The `subsystem` parameter is the name of the subsytem the trace event is in.
+For example that could be "scheduler" or "vote" or "hs". The idea is to add
+some context to the event so when we collect them we know where it's coming
+from. The `event_name` is the name of the event which helps a lot with
+adding some semantic to the event. Finally, `args` is any number of
+arguments we want to collect.
+
+Here is an example of a possible tracepoint in main():
+
+ tor_trace(main, init_phase, argc)
+
+The above is a tracepoint in the `main` subsystem with `init_phase` as the
+event name and the `int argc` is passed to the event as well.
+
+How `argc` is collected or used has nothing to do with the instrumentation
+(adding trace events to the code). It is the work of the tracer so this is why
+the trace events and collection framework (tracer) are decoupled. You _can_
+have trace events without a tracer.
+
+### Tracer ###
+
+In `src/trace/events.h`, we map the `tor_trace()` function to the right
+tracer. A tracer support is only enabled at compile time. For instance, the
+file `src/trace/debug.h` contains the mapping of the generic tracing function
+`tor_trace()` to the `log_debug()` function. More specialized function can be
+mapped depending on the tracepoint.
+
+## Build System ##
+
+This section describes how it is integrated into the build system of tor.
+
+By default, every tracing events are disabled in tor that is `tor_trace()`
+is a NOP.
+
+To enable a tracer, there is a configure option on the form of:
+
+ --enable-tracing-<tracer>
+
+We have an option that will send every trace events to a `log_debug()` (as
+mentionned above) which will print you the subsystem and name of the event but
+not the arguments for technical reasons. This is useful if you want to quickly
+see if your trace event is being hit or well written. To do so, use this
+configure option:
+
+ --enable-tracing-debug
+
+## Instrument Tor ##
+
+This is pretty easy. Let's say you want to add a trace event in
+`src/or/rendcache.c`, you only have to add this include statement:
+
+ #include "trace/events.h"
+
+Once done, you can add as many as you want `tor_trace()` that you need.
+Please use the right subsystem (here it would be `hs`) and a unique name that
+tells what the event is for. For example:
+
+ tor_trace(hs, store_desc_as_client, desc, desc_id);
+
+If you look in `src/trace/events.h`, you'll see that if tracing is enabled it
+will be mapped to a function called:
+
+ tor_trace_hs_store_desc_as_client(desc, desc_id)
+
+And the point of all this is for that function to be defined in a new file
+that you might want to add named `src/trace/hs.{c|h}` which would defined how
+to collect the data for the `tor_trace_hs_store_desc_as_client()` function
+like for instance sending it to a `log_debug()` or do more complex operations
+or use a userspace tracer like LTTng (https://lttng.org).
diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c
index 7b28a9494a..8d026dd5a7 100644
--- a/src/common/compat_threads.c
+++ b/src/common/compat_threads.c
@@ -352,3 +352,48 @@ alert_sockets_close(alert_sockets_t *socks)
socks->read_fd = socks->write_fd = -1;
}
+/*
+ * XXXX We might be smart to move to compiler intrinsics or real atomic
+ * XXXX operations at some point. But not yet.
+ *
+ */
+
+/** Initialize a new atomic counter with the value 0 */
+void
+atomic_counter_init(atomic_counter_t *counter)
+{
+ tor_mutex_init_nonrecursive(&counter->mutex);
+ counter->val = 0;
+}
+/** Clean up all resources held by an atomic counter. */
+void
+atomic_counter_destroy(atomic_counter_t *counter)
+{
+ tor_mutex_uninit(&counter->mutex);
+ memset(counter, 0, sizeof(*counter));
+}
+/** Add a value to an atomic counter. */
+void
+atomic_counter_add(atomic_counter_t *counter, size_t add)
+{
+ tor_mutex_acquire(&counter->mutex);
+ counter->val += add;
+ tor_mutex_release(&counter->mutex);
+}
+/** Subtract a value from an atomic counter. */
+void
+atomic_counter_sub(atomic_counter_t *counter, size_t sub)
+{
+ // this relies on unsigned overflow, but that's fine.
+ atomic_counter_add(counter, -sub);
+}
+/** Return the current value of an atomic counter */
+size_t
+atomic_counter_get(atomic_counter_t *counter)
+{
+ size_t val;
+ tor_mutex_acquire(&counter->mutex);
+ val = counter->val;
+ tor_mutex_release(&counter->mutex);
+ return val;
+}
diff --git a/src/common/compat_threads.h b/src/common/compat_threads.h
index 2943573b23..9fa3d0d0b7 100644
--- a/src/common/compat_threads.h
+++ b/src/common/compat_threads.h
@@ -147,5 +147,19 @@ void *tor_threadlocal_get(tor_threadlocal_t *threadlocal);
*/
void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
+/**
+ * Atomic counter type; holds a size_t value.
+ */
+typedef struct atomic_counter_t {
+ tor_mutex_t mutex;
+ size_t val;
+} atomic_counter_t;
+
+void atomic_counter_init(atomic_counter_t *counter);
+void atomic_counter_destroy(atomic_counter_t *counter);
+void atomic_counter_add(atomic_counter_t *counter, size_t add);
+void atomic_counter_sub(atomic_counter_t *counter, size_t sub);
+size_t atomic_counter_get(atomic_counter_t *counter);
+
#endif
diff --git a/src/common/compress.c b/src/common/compress.c
index e8d11b9715..fd2cb06404 100644
--- a/src/common/compress.c
+++ b/src/common/compress.c
@@ -487,3 +487,11 @@ tor_compress_state_size(const tor_compress_state_t *state)
return 0;
}
+/** Initialize all compression modules. */
+void
+tor_compress_init(void)
+{
+ tor_zlib_init();
+ tor_lzma_init();
+ tor_zstd_init();
+}
diff --git a/src/common/compress.h b/src/common/compress.h
index 8be67df3a6..cb5caeaf07 100644
--- a/src/common/compress.h
+++ b/src/common/compress.h
@@ -79,5 +79,7 @@ void tor_compress_free(tor_compress_state_t *state);
size_t tor_compress_state_size(const tor_compress_state_t *state);
+void tor_compress_init(void);
+
#endif // TOR_COMPRESS_H.
diff --git a/src/common/compress_lzma.c b/src/common/compress_lzma.c
index 59b7df6e0c..906a4067bd 100644
--- a/src/common/compress_lzma.c
+++ b/src/common/compress_lzma.c
@@ -23,7 +23,7 @@
#endif
/** Total number of bytes allocated for LZMA state. */
-static size_t total_lzma_allocation = 0;
+static atomic_counter_t total_lzma_allocation;
#ifdef HAVE_LZMA
/** Given <b>level</b> return the memory level. */
@@ -176,6 +176,7 @@ tor_lzma_compress_new(int compress,
}
}
+ atomic_counter_add(&total_lzma_allocation, result->allocation);
return result;
err:
@@ -290,7 +291,7 @@ tor_lzma_compress_free(tor_lzma_compress_state_t *state)
if (state == NULL)
return;
- total_lzma_allocation -= state->allocation;
+ atomic_counter_sub(&total_lzma_allocation, state->allocation);
#ifdef HAVE_LZMA
lzma_end(&state->stream);
@@ -311,6 +312,12 @@ tor_lzma_compress_state_size(const tor_lzma_compress_state_t *state)
size_t
tor_lzma_get_total_allocation(void)
{
- return total_lzma_allocation;
+ return atomic_counter_get(&total_lzma_allocation);
}
+/** Initialize the lzma module */
+void
+tor_lzma_init(void)
+{
+ atomic_counter_init(&total_lzma_allocation);
+}
diff --git a/src/common/compress_lzma.h b/src/common/compress_lzma.h
index 79cf9dc652..1433c89f88 100644
--- a/src/common/compress_lzma.h
+++ b/src/common/compress_lzma.h
@@ -37,5 +37,7 @@ size_t tor_lzma_compress_state_size(const tor_lzma_compress_state_t *state);
size_t tor_lzma_get_total_allocation(void);
+void tor_lzma_init(void);
+
#endif // TOR_COMPRESS_LZMA_H.
diff --git a/src/common/compress_zlib.c b/src/common/compress_zlib.c
index 7e848d5192..3fc574ce9a 100644
--- a/src/common/compress_zlib.c
+++ b/src/common/compress_zlib.c
@@ -48,7 +48,7 @@ static size_t tor_zlib_state_size_precalc(int inflate,
int windowbits, int memlevel);
/** Total number of bytes allocated for zlib state */
-static size_t total_zlib_allocation = 0;
+static atomic_counter_t total_zlib_allocation;
/** Given <b>level</b> return the memory level. */
static int
@@ -185,7 +185,7 @@ tor_zlib_compress_new(int compress_,
}
out->allocation = tor_zlib_state_size_precalc(!compress_, bits, memlevel);
- total_zlib_allocation += out->allocation;
+ atomic_counter_add(&total_zlib_allocation, out->allocation);
return out;
@@ -270,7 +270,7 @@ tor_zlib_compress_free(tor_zlib_compress_state_t *state)
if (state == NULL)
return;
- total_zlib_allocation -= state->allocation;
+ atomic_counter_sub(&total_zlib_allocation, state->allocation);
if (state->compress)
deflateEnd(&state->stream);
@@ -292,6 +292,12 @@ tor_zlib_compress_state_size(const tor_zlib_compress_state_t *state)
size_t
tor_zlib_get_total_allocation(void)
{
- return total_zlib_allocation;
+ return atomic_counter_get(&total_zlib_allocation);
}
+/** Set up global state for the zlib module */
+void
+tor_zlib_init(void)
+{
+ atomic_counter_init(&total_zlib_allocation);
+}
diff --git a/src/common/compress_zlib.h b/src/common/compress_zlib.h
index 2dd1254acb..df5c196ac7 100644
--- a/src/common/compress_zlib.h
+++ b/src/common/compress_zlib.h
@@ -37,5 +37,7 @@ size_t tor_zlib_compress_state_size(const tor_zlib_compress_state_t *state);
size_t tor_zlib_get_total_allocation(void);
+void tor_zlib_init(void);
+
#endif // TOR_COMPRESS_ZLIB_H.
diff --git a/src/common/compress_zstd.c b/src/common/compress_zstd.c
index 58fa327571..8b8aea1d01 100644
--- a/src/common/compress_zstd.c
+++ b/src/common/compress_zstd.c
@@ -24,7 +24,7 @@
#endif
/** Total number of bytes allocated for Zstandard state. */
-static size_t total_zstd_allocation = 0;
+static atomic_counter_t total_zstd_allocation;
#ifdef HAVE_ZSTD
/** Given <b>level</b> return the memory level. */
@@ -164,6 +164,7 @@ tor_zstd_compress_new(int compress,
}
}
+ atomic_counter_add(&total_zstd_allocation, result->allocation);
return result;
err:
@@ -296,7 +297,7 @@ tor_zstd_compress_free(tor_zstd_compress_state_t *state)
if (state == NULL)
return;
- total_zstd_allocation -= state->allocation;
+ atomic_counter_sub(&total_zstd_allocation, state->allocation);
#ifdef HAVE_ZSTD
if (state->compress) {
@@ -322,6 +323,12 @@ tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state)
size_t
tor_zstd_get_total_allocation(void)
{
- return total_zstd_allocation;
+ return atomic_counter_get(&total_zstd_allocation);
}
+/** Initialize the zstd module */
+void
+tor_zstd_init(void)
+{
+ atomic_counter_init(&total_zstd_allocation);
+}
diff --git a/src/common/compress_zstd.h b/src/common/compress_zstd.h
index 24e287c55c..d3e65c2f16 100644
--- a/src/common/compress_zstd.h
+++ b/src/common/compress_zstd.h
@@ -37,5 +37,7 @@ size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state);
size_t tor_zstd_get_total_allocation(void);
+void tor_zstd_init(void);
+
#endif // TOR_COMPRESS_ZSTD_H.
diff --git a/src/include.am b/src/include.am
index d12684e187..f78853f50f 100644
--- a/src/include.am
+++ b/src/include.am
@@ -7,3 +7,4 @@ include src/tools/include.am
include src/win32/include.am
include src/config/include.am
include src/test/fuzz/include.am
+include src/trace/include.am
diff --git a/src/or/include.am b/src/or/include.am
index 483ea2f2aa..4c24dd23b3 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -120,6 +120,7 @@ src_or_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libev
src_or_tor_LDADD = src/or/libtor.a src/common/libor.a src/common/libor-ctime.a \
src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
src/common/libor-event.a src/trunnel/libor-trunnel.a \
+ src/trace/libor-trace.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
diff --git a/src/or/main.c b/src/or/main.c
index 1ba6554d3e..5fec7e4a5d 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -3616,6 +3616,7 @@ tor_main(int argc, char *argv[])
update_approx_time(time(NULL));
tor_threads_init();
+ tor_compress_init();
init_logging(0);
monotime_init();
#ifdef USE_DMALLOC
diff --git a/src/or/relay.c b/src/or/relay.c
index 8524080939..1842012ed7 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -226,7 +226,8 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
return 0;
if (relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) {
- log_warn(LD_BUG,"relay crypt failed. Dropping connection.");
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "relay crypt failed. Dropping connection.");
return -END_CIRC_REASON_INTERNAL;
}
diff --git a/src/test/bench.c b/src/test/bench.c
index 5da9168cdc..a44dc94a61 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -674,6 +674,7 @@ main(int argc, const char **argv)
or_options_t *options;
tor_threads_init();
+ tor_compress_init();
if (argc == 4 && !strcmp(argv[1], "diff")) {
init_logging(1);
diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c
index f540176204..7aee92df63 100644
--- a/src/test/fuzz/fuzzing_common.c
+++ b/src/test/fuzz/fuzzing_common.c
@@ -96,6 +96,7 @@ static void
global_init(void)
{
tor_threads_init();
+ tor_compress_init();
{
struct sipkey sipkey = { 1337, 7331 };
siphash_set_global_key(&sipkey);
diff --git a/src/test/include.am b/src/test/include.am
index 653adad300..230a6c8bad 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -193,6 +193,7 @@ src_test_test_LDADD = src/or/libtor-testing.a \
src/common/libor-ctime-testing.a \
src/common/libor-event-testing.a \
src/trunnel/libor-trunnel-testing.a \
+ src/trace/libor-trace.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
@@ -216,6 +217,7 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
src/common/libor-ctime.a \
src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
src/common/libor-event.a src/trunnel/libor-trunnel.a \
+ src/trace/libor-trace.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \
@TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
@@ -227,6 +229,7 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \
src/common/libor-ctime-testing.a \
src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \
src/common/libor-event-testing.a \
+ src/trace/libor-trace.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \
@TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@
@@ -264,6 +267,7 @@ src_test_test_ntor_cl_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \
src/common/libor-ctime.a \
src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \
+ src/trace/libor-trace.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \
@TOR_LZMA_LIBS@
@@ -285,6 +289,7 @@ noinst_PROGRAMS += src/test/test-bt-cl
src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c
src_test_test_bt_cl_LDADD = src/common/libor-testing.a \
src/common/libor-ctime-testing.a \
+ src/trace/libor-trace.a \
@TOR_LIB_MATH@ \
@TOR_LIB_WS32@ @TOR_LIB_GDI@
src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index 0e37e0d154..d3dc761c77 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -245,6 +245,7 @@ main(int c, const char **v)
update_approx_time(time(NULL));
options = options_new();
tor_threads_init();
+ tor_compress_init();
network_init();
diff --git a/src/trace/debug.h b/src/trace/debug.h
new file mode 100644
index 0000000000..3a1652543a
--- /dev/null
+++ b/src/trace/debug.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_TRACE_LOG_DEBUG_H
+#define TOR_TRACE_LOG_DEBUG_H
+
+#include "torlog.h"
+
+/* Stringify pre-processor trick. */
+#define XSTR(d) STR(d)
+#define STR(s) #s
+
+/* Send every event to a debug log level. This is useful to debug new trace
+ * events without implementing them for a specific event tracing framework.
+ * Note that the arguments are ignored since at this step we do not know the
+ * types and amount there is. */
+
+/* Example on how to map a tracepoint to log_debug(). */
+#undef tor_trace
+#define tor_trace(subsystem, name, args...) \
+ log_debug(LD_GENERAL, "Trace event \"" XSTR(name) "\" from " \
+ "\"" XSTR(subsystem) "\" hit. " \
+ "(line "XSTR(__LINE__) ")")
+
+#endif /* TOR_TRACE_LOG_DEBUG_H */
diff --git a/src/trace/events.h b/src/trace/events.h
new file mode 100644
index 0000000000..1be1fd596e
--- /dev/null
+++ b/src/trace/events.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file events.h
+ * \brief Header file for Tor event tracing.
+ **/
+
+#ifndef TOR_TRACE_EVENTS_H
+#define TOR_TRACE_EVENTS_H
+
+/*
+ * The following defines a generic event tracing function name that has to be
+ * used to trace events in the code base.
+ *
+ * That generic function is then defined by a event tracing framework. For
+ * instance, the "log debug" framework sends all trace events to log_debug()
+ * which is defined in src/trace/debug.h which can only be enabled at compile
+ * time (--enable-event-tracing-debug).
+ *
+ * By default, every trace events in the code base are replaced by a NOP. See
+ * doc/HACKING/Tracing.md for more information on how to use event tracing or
+ * add events.
+ */
+
+#ifdef TOR_EVENT_TRACING_ENABLED
+/* Map every trace event to a per subsystem macro. */
+#define tor_trace(subsystem, name, ...) \
+ tor_trace_##subsystem(name, __VA_ARGS__)
+
+/* Enable event tracing for the debug framework where all trace events are
+ * mapped to a log_debug(). */
+#ifdef USE_EVENT_TRACING_DEBUG
+#include "trace/debug.h"
+#endif
+
+#else /* TOR_EVENT_TRACING_ENABLED */
+
+/* Reaching this point, we NOP every event declaration because event tracing
+ * is not been enabled at compile time. */
+#define tor_trace(subsystem, name, args...)
+
+#endif /* TOR_EVENT_TRACING_ENABLED */
+
+#endif /* TOR_TRACE_EVENTS_H */
diff --git a/src/trace/include.am b/src/trace/include.am
new file mode 100644
index 0000000000..f7de1fb111
--- /dev/null
+++ b/src/trace/include.am
@@ -0,0 +1,20 @@
+# Include the src/ so we can use the trace/events.h statement when including
+# any file in that directory.
+AM_CPPFLAGS += -I$(srcdir)/src
+
+noinst_LIBRARIES += \
+ src/trace/libor-trace.a
+LIBOR_TRACE_A_SOURCES =
+
+TRACEHEADERS = \
+ src/trace/events.h
+
+if USE_EVENT_TRACING_DEBUG
+TRACEHEADERS += \
+ src/trace/debug.h
+endif
+
+# Library source files.
+src_trace_libor_trace_a_SOURCES = $(LIBOR_TRACE_A_SOURCES)
+
+noinst_HEADERS+= $(TRACEHEADERS)