11#ifndef O2_FRAMEWORK_SIGNPOST_H_
12#define O2_FRAMEWORK_SIGNPOST_H_
23 char const*
name =
nullptr;
33 std::array<char, N>
res = {};
36 for (
int i = 0;
i < N; ++
i) {
37 if (
src[
i] ==
'%' &&
src[
i + 1] ==
'{') {
39 while (
src[
i] !=
'}' &&
src[
i] != 0) {
59#ifdef O2_SIGNPOST_IMPLEMENTATION
64 static std::atomic<o2_log_handle_t*>
first =
nullptr;
79 bool cont = callback(current->
name, current->
log, context);
84 current = current->
next;
92#include <os/signpost.h>
94#define O2_LOG_DEBUG_MAC(log, format, ...) os_log_debug(private_o2_log_##log, format __VA_OPT__(, ) __VA_ARGS__)
95#define O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ...) os_signpost_event_emit(private_o2_log_##log->os_log, (uint64_t)id.value, name, format __VA_OPT__(, ) __VA_ARGS__)
96#define O2_SIGNPOST_START_MAC(log, id, name, format, ...) os_signpost_interval_begin(private_o2_log_##log->os_log, (uint64_t)id.value, name, format __VA_OPT__(, ) __VA_ARGS__)
97#define O2_SIGNPOST_END_MAC(log, id, name, format, ...) os_signpost_interval_end(private_o2_log_##log->os_log, (uint64_t)id.value, name, format __VA_OPT__(, ) __VA_ARGS__)
98#define O2_SIGNPOST_ENABLED_MAC(log) os_signpost_enabled(private_o2_log_##log->os_log)
101#define O2_DECLARE_LOG_MAC(x, category)
102#define O2_LOG_DEBUG_MAC(log, ...)
103#define O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ...)
104#define O2_SIGNPOST_START_MAC(log, id, name, format, ...)
105#define O2_SIGNPOST_END_MAC(log, id, name, format, ...)
106#define O2_SIGNPOST_ENABLED_MAC(log) false
110#if defined(__APPLE__) || defined(O2_FORCE_SIGNPOSTS) || !defined(O2_NSIGNPOSTS)
111#define O2_LOG_ENABLED(log) private_o2_log_##log->stacktrace
113#define O2_LOG_ENABLED(log) false
116#if !defined(O2_LOG_MACRO_RAW) && __has_include("Framework/Logger.h")
118#define O2_LOG_MACRO_RAW(level, ...) LOGF(level, __VA_ARGS__)
119#elif !defined(O2_LOG_MACRO_RAW)
122#define O2_LOG_MACRO_RAW(level, format, ...) \
124 printf(#level ":" #format, __VA_ARGS__); \
128#define O2_LOG_MACRO_RAW(...)
131#if !defined(O2_LOG_MACRO) && __has_include("Framework/Logger.h")
133#define O2_LOG_MACRO(...) LOGF(info, __VA_ARGS__)
134#elif !defined(O2_LOG_MACRO)
137#define O2_LOG_MACRO(...) \
139 printf(__VA_ARGS__); \
143#define O2_LOG_MACRO(...)
155 static constexpr size_t N = 1024;
156 std::atomic<size_t>
top = 0;
178 os_log_t os_log =
nullptr;
183 std::array<_o2_signpost_id_t, 256>
ids = {};
243#ifdef O2_SIGNPOST_IMPLEMENTATION
257 size_t currentTop =
stack.top.load(std::memory_order_relaxed);
263#if defined(__x86_64__) || defined(__i386__)
264 __asm__ __volatile__(
"pause" ::
266#elif defined(__aarch64__)
267 __asm__ __volatile__(
"yield" ::
273 if (
stack.top.compare_exchange_weak(currentTop, currentTop + 1,
274 std::memory_order_release,
275 std::memory_order_relaxed)) {
284 size_t currentTop =
stack.top.load(std::memory_order_relaxed);
286 if (currentTop == 0 && spin ==
false) {
288 }
else if (currentTop == 0) {
290#if defined(__x86_64__) || defined(__i386__)
291 __asm__ __volatile__(
"pause" ::
293#elif defined(__aarch64__)
294 __asm__ __volatile__(
"yield" ::
300 if (
stack.top.compare_exchange_weak(currentTop, currentTop - 1,
301 std::memory_order_acquire,
302 std::memory_order_relaxed)) {
314 char const*
name = (
char const*)context;
315 if (strcmp(
name, currentName) == 0) {
331 for (
int i = 0;
i <
n;
i++) {
335 log->defaultStacktrace = defaultStacktrace;
337 newHandle->log = log;
341 if (defaultStacktrace > 1) {
342 log->os_log = os_log_create(
name, OS_LOG_CATEGORY_DYNAMIC_STACK_TRACING);
344 log->os_log = os_log_create(
name, OS_LOG_CATEGORY_DYNAMIC_TRACING);
347 newHandle->name = strdup(
name);
352 while (!
o2_get_logs_tail().compare_exchange_weak(newHandle->next, newHandle,
353 std::memory_order_release,
354 std::memory_order_relaxed)) {
371 for (
i = 0;
i < log->
ids.size(); ++
i) {
372 if (log->
ids[
i].value ==
id.value) {
378 if (
i != log->
ids.size()) {
385 char prebuffer[4096];
386 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16s*>%*c",
id.
value,
name, leading,
' ');
387 vsnprintf(prebuffer + s, 4096 - s,
format, args);
402 _o2_signpost_event_emit_v(log,
id,
name,
format, args);
416 log->
ids[signpost_index].value =
id.value;
417 auto* activity = &log->
activities[signpost_index];
419 activity->name =
name;
420 int leading = activity->indentation * 2;
421 char prebuffer[4096];
422 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16sS>%*c",
id.
value,
name, leading,
' ');
423 vsnprintf(prebuffer + s, 4096 - s,
format, args);
435 for (
i = 0;
i < log->
ids.size(); ++
i) {
436 if (log->
ids[
i].value ==
id.value) {
443 if (
i == log->
ids.size()) {
444 _o2_signpost_event_emit_v(log,
id,
name,
format, args);
450 char prebuffer[4096];
451 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16sE>%*c",
id.
value,
name, leading,
' ');
452 vsnprintf(prebuffer + s, 4096 - s,
format, args);
456 activity->
name =
nullptr;
457 log->
ids[
i].value = -1;
469 _o2_signpost_interval_end_v(log,
id,
name,
format, args);
480void o2_debug_log_set_stacktrace(
_o2_log_t* log,
int stacktrace)
487#if defined(__APPLE__) || defined(O2_FORCE_SIGNPOSTS) || !defined(O2_NSIGNPOSTS)
490#define O2_DECLARE_DYNAMIC_LOG(name) static _o2_log_t* private_o2_log_##name = (_o2_log_t*)_o2_log_create("ch.cern.aliceo2." #name, 1)
492#define O2_DECLARE_DYNAMIC_STACKTRACE_LOG(name) static _o2_log_t* private_o2_log_##name = (_o2_log_t*)_o2_log_create("ch.cern.aliceo2." #name, 64)
493#define O2_DECLARE_LOG(name, category) static _o2_log_t* private_o2_log_##name = (_o2_log_t*)_o2_log_create("ch.cern.aliceo2." #name, 1)
495#define O2_LOG_ENABLE(log) _o2_log_set_stacktrace(private_o2_log_##log, private_o2_log_##log->defaultStacktrace)
496#define O2_LOG_DISABLE(log) _o2_log_set_stacktrace(private_o2_log_##log, 0)
499#define O2_LOG_DEBUG(log, ...) __extension__({ \
500 if (O2_BUILTIN_UNLIKELY(O2_LOG_ENABLED(log))) { \
501 O2_LOG_MACRO(__VA_ARGS__); \
502 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
503 O2_LOG_MACRO(__VA_ARGS__); \
506#define O2_SIGNPOST_ID_FROM_POINTER(name, log, pointer) _o2_signpost_id_t name = _o2_signpost_id_make_with_pointer(private_o2_log_##log, pointer)
507#define O2_SIGNPOST_ID_GENERATE(name, log) _o2_signpost_id_t name = _o2_signpost_id_generate_local(private_o2_log_##log)
511#define O2_SIGNPOST_ACTION(log, callback) __extension__({ \
512 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
513 _o2_signpost_action(private_o2_log_##log, callback); \
514 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
515 _o2_signpost_action(private_o2_log_##log, callback); \
523#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format, ...) __extension__({ \
524 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
525 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
526 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
527 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
532#define O2_SIGNPOST_EVENT_EMIT_INFO(log, id, name, format, ...) __extension__({ \
533 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
534 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
535 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
536 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
538 O2_LOG_MACRO_RAW(info, remove_engineering_type(format).data(), ##__VA_ARGS__); \
543#define O2_SIGNPOST_EVENT_EMIT_DETAIL(log, id, name, format, ...) __extension__({ \
544 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
545 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
546 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
547 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
549 O2_LOG_MACRO_RAW(detail, remove_engineering_type(format).data(), ##__VA_ARGS__); \
554#define O2_SIGNPOST_EVENT_EMIT_ERROR(log, id, name, format, ...) __extension__({ \
555 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
556 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
557 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
558 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
560 O2_LOG_MACRO_RAW(error, remove_engineering_type(format).data(), ##__VA_ARGS__); \
564#define O2_SIGNPOST_EVENT_EMIT_WARN(log, id, name, format, ...) __extension__({ \
565 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
566 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
567 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
568 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
570 O2_LOG_MACRO_RAW(warn, remove_engineering_type(format).data(), ##__VA_ARGS__); \
574#define O2_SIGNPOST_EVENT_EMIT_CRITICAL(log, id, name, format, ...) __extension__({ \
575 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
576 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
577 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
578 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
580 O2_LOG_MACRO_RAW(critical, remove_engineering_type(format).data(), ##__VA_ARGS__); \
584#define O2_SIGNPOST_EVENT_EMIT_ALARM(log, id, name, format, ...) __extension__({ \
585 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
586 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
587 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
588 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
590 O2_LOG_MACRO_RAW(alarm, remove_engineering_type(format).data(), ##__VA_ARGS__); \
594#define O2_SIGNPOST_EVENT_EMIT_IMPORTANT(log, id, name, format, ...) __extension__({ \
595 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
596 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
597 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
598 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
600 O2_LOG_MACRO_RAW(important, remove_engineering_type(format).data(), ##__VA_ARGS__); \
603#define O2_SIGNPOST_START(log, id, name, format, ...) \
604 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
605 O2_SIGNPOST_START_MAC(log, id, name, format, ##__VA_ARGS__); \
606 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
607 _o2_signpost_interval_begin(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
609#define O2_SIGNPOST_END(log, id, name, format, ...) \
610 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
611 O2_SIGNPOST_END_MAC(log, id, name, format, ##__VA_ARGS__); \
612 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
613 _o2_signpost_interval_end(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
617#define O2_SIGNPOST_END_WITH_ERROR(log, id, name, format, ...) \
618 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
619 O2_SIGNPOST_END_MAC(log, id, name, format, ##__VA_ARGS__); \
620 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
621 _o2_signpost_interval_end(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
623 O2_LOG_MACRO_RAW(error, remove_engineering_type(format).data(), ##__VA_ARGS__); \
626#define O2_DECLARE_DYNAMIC_LOG(x)
627#define O2_DECLARE_DYNAMIC_STACKTRACE_LOG(x)
628#define O2_DECLARE_LOG(x, category)
629#define O2_LOG_ENABLE(log)
630#define O2_LOG_DISABLE(log)
631#define O2_LOG_DEBUG(log, ...)
632#define O2_SIGNPOST_ID_FROM_POINTER(name, log, pointer)
633#define O2_SIGNPOST_ID_GENERATE(name, log)
634#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format, ...)
635#define O2_SIGNPOST_START(log, id, name, format, ...)
636#define O2_SIGNPOST_END(log, id, name, format, ...)
o2_log_handle_t * o2_walk_logs(bool(*callback)(char const *name, void *log, void *context), void *context=nullptr)
bool _o2_lock_free_stack_push(_o2_lock_free_stack &stack, const int &value, bool spin=false)
void _o2_signpost_interval_end(_o2_log_t *log, _o2_signpost_id_t id, char const *name, char const *const format,...)
void _o2_singpost_action(_o2_log_t *log, void(*callback)(void *))
void _o2_log_set_stacktrace(_o2_log_t *log, int stacktrace)
void _o2_signpost_event_emit(_o2_log_t *log, _o2_signpost_id_t id, char const *name, char const *const format,...)
bool _o2_lock_free_stack_pop(_o2_lock_free_stack &stack, int &value, bool spin=false)
_o2_signpost_id_t _o2_signpost_id_generate_local(_o2_log_t *log)
std::atomic< o2_log_handle_t * > & o2_get_logs_tail()
consteval auto remove_engineering_type(char const (&src)[N])
#define O2_LOG_MACRO(...)
void _o2_signpost_action(_o2_log_t *log, void(*callback)(void *))
_o2_signpost_id_t _o2_signpost_id_make_with_pointer(_o2_log_t *log, void const *pointer)
void _o2_signpost_interval_begin(_o2_log_t *log, _o2_signpost_id_t id, char const *name, char const *const format,...)
void * _o2_log_create(char const *name, int stacktrace)
GLdouble GLdouble GLdouble GLdouble top
GLuint const GLchar * name
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum format
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
unsigned char indentation
static constexpr size_t N
std::atomic< int64_t > current_indentation
_o2_lock_free_stack slots
std::array< _o2_signpost_id_t, 256 > ids
std::array< _o2_activity_t, 256 > activities
std::atomic< int64_t > unique_signpost
static void demangled_backtrace_symbols(void **backtrace, unsigned int total, int fd)
static constexpr unsigned int MAX_BACKTRACE_SIZE