11#ifndef O2_FRAMEWORK_SIGNPOST_H_
12#define O2_FRAMEWORK_SIGNPOST_H_
22 char const*
name =
nullptr;
32 std::array<char, N>
res = {};
35 for (
int i = 0;
i < N; ++
i) {
36 if (
src[
i] ==
'%' &&
src[
i + 1] ==
'{') {
38 while (
src[
i] !=
'}' &&
src[
i] != 0) {
58#ifdef O2_SIGNPOST_IMPLEMENTATION
63 static std::atomic<o2_log_handle_t*>
first =
nullptr;
78 bool cont = callback(current->
name, current->
log, context);
83 current = current->
next;
91#include <os/signpost.h>
93#define O2_LOG_DEBUG_MAC(log, format, ...) os_log_debug(private_o2_log_##log, format __VA_OPT__(, ) __VA_ARGS__)
94#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__)
95#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__)
96#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__)
97#define O2_SIGNPOST_ENABLED_MAC(log) os_signpost_enabled(private_o2_log_##log->os_log)
100#define O2_DECLARE_LOG_MAC(x, category)
101#define O2_LOG_DEBUG_MAC(log, ...)
102#define O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ...)
103#define O2_SIGNPOST_START_MAC(log, id, name, format, ...)
104#define O2_SIGNPOST_END_MAC(log, id, name, format, ...)
105#define O2_SIGNPOST_ENABLED_MAC(log) false
109#if defined(__APPLE__) || defined(O2_FORCE_SIGNPOSTS) || !defined(O2_NSIGNPOSTS)
110#define O2_LOG_ENABLED(log) private_o2_log_##log->stacktrace
112#define O2_LOG_ENABLED(log) false
115#if !defined(O2_LOG_MACRO_RAW) && __has_include("Framework/Logger.h")
117#define O2_LOG_MACRO_RAW(level, ...) LOGF(level, __VA_ARGS__)
118#elif !defined(O2_LOG_MACRO_RAW)
121#define O2_LOG_MACRO_RAW(level, format, ...) \
123 printf(#level ":" #format, __VA_ARGS__); \
127#define O2_LOG_MACRO_RAW(...)
130#if !defined(O2_LOG_MACRO) && __has_include("Framework/Logger.h")
132#define O2_LOG_MACRO(...) LOGF(info, __VA_ARGS__)
133#elif !defined(O2_LOG_MACRO)
136#define O2_LOG_MACRO(...) \
138 printf(__VA_ARGS__); \
142#define O2_LOG_MACRO(...)
154 static constexpr size_t N = 1024;
155 std::atomic<size_t>
top = 0;
177 os_log_t os_log =
nullptr;
182 std::array<_o2_signpost_id_t, 256>
ids = {};
235 assert(((int64_t)
pointer & 1) != 1);
242#ifdef O2_SIGNPOST_IMPLEMENTATION
256 size_t currentTop =
stack.top.load(std::memory_order_relaxed);
262#if defined(__x86_64__) || defined(__i386__)
263 __asm__ __volatile__(
"pause" ::
265#elif defined(__aarch64__)
266 __asm__ __volatile__(
"yield" ::
272 if (
stack.top.compare_exchange_weak(currentTop, currentTop + 1,
273 std::memory_order_release,
274 std::memory_order_relaxed)) {
283 size_t currentTop =
stack.top.load(std::memory_order_relaxed);
285 if (currentTop == 0 && spin ==
false) {
287 }
else if (currentTop == 0) {
289#if defined(__x86_64__) || defined(__i386__)
290 __asm__ __volatile__(
"pause" ::
292#elif defined(__aarch64__)
293 __asm__ __volatile__(
"yield" ::
299 if (
stack.top.compare_exchange_weak(currentTop, currentTop - 1,
300 std::memory_order_acquire,
301 std::memory_order_relaxed)) {
313 char const*
name = (
char const*)context;
314 if (strcmp(
name, currentName) == 0) {
330 for (
int i = 0;
i <
n;
i++) {
334 log->defaultStacktrace = defaultStacktrace;
336 newHandle->log = log;
340 if (defaultStacktrace > 1) {
341 log->os_log = os_log_create(
name, OS_LOG_CATEGORY_DYNAMIC_STACK_TRACING);
343 log->os_log = os_log_create(
name, OS_LOG_CATEGORY_DYNAMIC_TRACING);
346 newHandle->name = strdup(
name);
351 while (!
o2_get_logs_tail().compare_exchange_weak(newHandle->next, newHandle,
352 std::memory_order_release,
353 std::memory_order_relaxed)) {
370 for (
i = 0;
i < log->
ids.size(); ++
i) {
371 if (log->
ids[
i].value ==
id.value) {
377 if (
i != log->
ids.size()) {
384 char prebuffer[4096];
385 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16s*>%*c",
id.
value,
name, leading,
' ');
386 vsnprintf(prebuffer + s, 4096 - s,
format, args);
401 _o2_signpost_event_emit_v(log,
id,
name,
format, args);
415 log->
ids[signpost_index].value =
id.value;
416 auto* activity = &log->
activities[signpost_index];
418 activity->name =
name;
419 int leading = activity->indentation * 2;
420 char prebuffer[4096];
421 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16sS>%*c",
id.
value,
name, leading,
' ');
422 vsnprintf(prebuffer + s, 4096 - s,
format, args);
434 for (
i = 0;
i < log->
ids.size(); ++
i) {
435 if (log->
ids[
i].value ==
id.value) {
442 if (
i == log->
ids.size()) {
443 _o2_signpost_event_emit_v(log,
id,
name,
format, args);
449 char prebuffer[4096];
450 int s = snprintf(prebuffer, 4096,
"id%.16" PRIx64
":%-16sE>%*c",
id.
value,
name, leading,
' ');
451 vsnprintf(prebuffer + s, 4096 - s,
format, args);
455 activity->
name =
nullptr;
456 log->
ids[
i].value = -1;
468 _o2_signpost_interval_end_v(log,
id,
name,
format, args);
479void o2_debug_log_set_stacktrace(
_o2_log_t* log,
int stacktrace)
486#if defined(__APPLE__) || defined(O2_FORCE_SIGNPOSTS) || !defined(O2_NSIGNPOSTS)
489#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)
491#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)
492#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)
494#define O2_LOG_ENABLE(log) _o2_log_set_stacktrace(private_o2_log_##log, private_o2_log_##log->defaultStacktrace)
495#define O2_LOG_DISABLE(log) _o2_log_set_stacktrace(private_o2_log_##log, 0)
498#define O2_LOG_DEBUG(log, ...) __extension__({ \
499 if (O2_BUILTIN_UNLIKELY(O2_LOG_ENABLED(log))) { \
500 O2_LOG_MACRO(__VA_ARGS__); \
501 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
502 O2_LOG_MACRO(__VA_ARGS__); \
505#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)
506#define O2_SIGNPOST_ID_GENERATE(name, log) _o2_signpost_id_t name = _o2_signpost_id_generate_local(private_o2_log_##log)
510#define O2_SIGNPOST_ACTION(log, callback) __extension__({ \
511 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
512 _o2_signpost_action(private_o2_log_##log, callback); \
513 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
514 _o2_signpost_action(private_o2_log_##log, callback); \
522#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format, ...) __extension__({ \
523 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
524 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
525 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
526 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
531#define O2_SIGNPOST_EVENT_EMIT_INFO(log, id, name, format, ...) __extension__({ \
532 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
533 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
534 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
535 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
537 O2_LOG_MACRO_RAW(info, remove_engineering_type(format).data(), ##__VA_ARGS__); \
542#define O2_SIGNPOST_EVENT_EMIT_DETAIL(log, id, name, format, ...) __extension__({ \
543 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
544 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
545 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
546 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
548 O2_LOG_MACRO_RAW(detail, remove_engineering_type(format).data(), ##__VA_ARGS__); \
553#define O2_SIGNPOST_EVENT_EMIT_ERROR(log, id, name, format, ...) __extension__({ \
554 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
555 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
556 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
557 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
559 O2_LOG_MACRO_RAW(error, remove_engineering_type(format).data(), ##__VA_ARGS__); \
563#define O2_SIGNPOST_EVENT_EMIT_WARN(log, id, name, format, ...) __extension__({ \
564 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
565 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
566 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
567 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
569 O2_LOG_MACRO_RAW(warn, remove_engineering_type(format).data(), ##__VA_ARGS__); \
573#define O2_SIGNPOST_EVENT_EMIT_CRITICAL(log, id, name, format, ...) __extension__({ \
574 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
575 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
576 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
577 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
579 O2_LOG_MACRO_RAW(critical, remove_engineering_type(format).data(), ##__VA_ARGS__); \
583#define O2_SIGNPOST_EVENT_EMIT_ALARM(log, id, name, format, ...) __extension__({ \
584 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
585 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
586 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
587 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
589 O2_LOG_MACRO_RAW(alarm, remove_engineering_type(format).data(), ##__VA_ARGS__); \
593#define O2_SIGNPOST_EVENT_EMIT_IMPORTANT(log, id, name, format, ...) __extension__({ \
594 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
595 O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \
596 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
597 _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
599 O2_LOG_MACRO_RAW(important, remove_engineering_type(format).data(), ##__VA_ARGS__); \
602#define O2_SIGNPOST_START(log, id, name, format, ...) \
603 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
604 O2_SIGNPOST_START_MAC(log, id, name, format, ##__VA_ARGS__); \
605 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
606 _o2_signpost_interval_begin(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
608#define O2_SIGNPOST_END(log, id, name, format, ...) \
609 if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \
610 O2_SIGNPOST_END_MAC(log, id, name, format, ##__VA_ARGS__); \
611 } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \
612 _o2_signpost_interval_end(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \
615#define O2_DECLARE_DYNAMIC_LOG(x)
616#define O2_DECLARE_DYNAMIC_STACKTRACE_LOG(x)
617#define O2_DECLARE_LOG(x, category)
618#define O2_LOG_ENABLE(log)
619#define O2_LOG_DISABLE(log)
620#define O2_LOG_DEBUG(log, ...)
621#define O2_SIGNPOST_ID_FROM_POINTER(name, log, pointer)
622#define O2_SIGNPOST_ID_GENERATE(name, log)
623#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format, ...)
624#define O2_SIGNPOST_START(log, id, name, format, ...)
625#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