blob: 54b2eb86dc337be3371b029b71f7d6e33264f6c4 [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//==============================================================================
//
// This file provides the interface for working with the tokenized trace
// backend.
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#ifndef PW_TRACE_GET_TIME_DELTA
#ifdef __cplusplus
#include <type_traits>
#endif // __cplusplus
#endif // PW_TRACE_GET_TIME_DELTA
#include "pw_tokenizer/tokenize.h"
#include "pw_trace_tokenized/internal/trace_tokenized_internal.h"
// Configurable options
// Since not all strings are tokenizeable, labels can be passed as arguments.
// PW_TRACE_CONFIG_ARG_LABEL_SIZE_BYTES configures the maximum number of
// characters to include, if more are provided the string will be clipped.
#ifndef PW_TRACE_CONFIG_ARG_LABEL_SIZE_BYTES
#define PW_TRACE_CONFIG_ARG_LABEL_SIZE_BYTES 20
#endif // PW_TRACE_CONFIG_ARG_LABEL_SIZE_BYTES
// PW_TRACE_TIME_TYPE sets the type for trace time.
#ifndef PW_TRACE_TIME_TYPE
#define PW_TRACE_TIME_TYPE uint32_t
#endif // PW_TRACE_TIME_TYPE
// PW_TRACE_GET_TIME is the macro which is called to get the current time for a
// trace event. It's default is to use pw_trace_GetTraceTime() which needs to be
// provided by the platform.
#ifndef PW_TRACE_GET_TIME
#define PW_TRACE_GET_TIME() pw_trace_GetTraceTime()
extern PW_TRACE_TIME_TYPE pw_trace_GetTraceTime();
#endif // PW_TRACE_GET_TIME
// PW_TRACE_GET_TIME_TICKS_PER_SECOND is the macro which is called to determine
// the unit of the trace time. It's default is to use
// pw_trace_GetTraceTimeTicksPerSecond() which needs to be provided by the
// platform.
#ifndef PW_TRACE_GET_TIME_TICKS_PER_SECOND
#define PW_TRACE_GET_TIME_TICKS_PER_SECOND() \
pw_trace_GetTraceTimeTicksPerSecond()
extern size_t pw_trace_GetTraceTimeTicksPerSecond();
#endif // PW_TRACE_GET_TIME_TICKS_PER_SECOND
// PW_TRACE_GET_TIME_DELTA is te macro which is called to determine
// the delta between two PW_TRACE_TIME_TYPE variables. It should return a
// delta of the two times, in the same type.
// The default implementation just subtracts the two, which is suitable if
// values either never wrap, or are unsigned and do not wrap multiple times
// between trace events. If either of these are not the case a different
// implemention should be used.
#ifndef PW_TRACE_GET_TIME_DELTA
#define PW_TRACE_GET_TIME_DELTA(last_time, current_time) \
((current_time) - (last_time))
#ifdef __cplusplus
static_assert(
std::is_unsigned<PW_TRACE_TIME_TYPE>::value,
"Default time delta implementation only works for unsigned time types.");
#endif // __cplusplus
#endif // PW_TRACE_GET_TIME_DELTA
// PW_TRACE_LOCK is called when a new event is being processed to ensure only
// one event is sent to the sinks at a time. Is is also called when registering
// and unregistering callbacks and sinks.
#ifndef PW_TRACE_LOCK
#define PW_TRACE_LOCK()
#endif // PW_TRACE_LOCK
// PW_TRACE_UNLOCK is called after sending the data to all the sinks.
#ifndef PW_TRACE_UNLOCK
#define PW_TRACE_UNLOCK()
#endif // PW_TRACE_UNLOCK
#ifdef __cplusplus
namespace pw {
namespace trace {
using EventType = pw_trace_EventType;
class TokenizedTraceImpl {
public:
void Enable(bool enable) { enabled_ = enable; }
bool IsEnabled() const { return enabled_; }
void HandleTraceEvent(uint32_t trace_token,
EventType event_type,
const char* module,
uint32_t trace_id,
uint8_t flags,
const void* data_buffer,
size_t data_size);
private:
PW_TRACE_TIME_TYPE last_trace_time_ = 0;
bool enabled_ = false;
};
// A singleton object of the TokenizedTraceImpl class which can be used to
// interface with trace using the C++ API.
// Example: pw::trace::TokenizedTrace::Instance().Enable(true);
class TokenizedTrace {
public:
static TokenizedTraceImpl& Instance() { return instance_; };
private:
static TokenizedTraceImpl instance_;
};
} // namespace trace
} // namespace pw
#endif // __cplusplus
// PW_TRACE_SET_ENABLED is used to enable or disable tracing.
#define PW_TRACE_SET_ENABLED(enabled) pw_trace_Enable(enabled)
// PW_TRACE_REF provides the uint32_t token value for a specific trace event.
// this can be used in the callback to perform specific actions for that trace.
// All the fields must match exactly to generate the correct trace reference.
// If the trace does not have a group, use PW_TRACE_GROUP_LABEL_DEFAULT.
//
// For example this can be used to skip a specific trace:
// pw_trace_TraceEventReturnFlags TraceEventCallback(
// uint32_t trace_ref,
// pw_trace_EventType event_type,
// const char* module,
// uint32_t trace_id,
// uint8_t flags) {
// auto skip_trace_ref = PW_TRACE_REF(PW_TRACE_TYPE_INSTANT,
// "test_module", // Module
// "test_label", // Label
// PW_TRACE_FLAGS_DEFAULT,
// PW_TRACE_GROUP_LABEL_DEFAULT);
// if (trace_ref == skip_trace_ref) {
// return PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT;
// }
// return 0;
// }
//
// The above trace ref would provide the tokenize value for the string:
// "1|0|test_module||test_label"
//
// Another example:
// #define PW_TRACE_MODULE test_module
// PW_TRACE_INSTANT_DATA_FLAG(2, "label", "group", id, "%d", 5, 1);
// Would internally generate a token value for the string:
// "1|2|test_module|group|label|%d"
// The trace_id, and data value are runtime values and not included in the
// token string.
#define PW_TRACE_REF(event_type, module, label, flags, group) \
PW_TOKENIZE_STRING_DOMAIN("trace", \
PW_STRINGIFY(event_type) "|" PW_STRINGIFY( \
flags) "|" module "|" group "|" label)
#define PW_TRACE_REF_DATA(event_type, module, label, flags, group, type) \
PW_TOKENIZE_STRING_DOMAIN( \
"trace", \
PW_STRINGIFY(event_type) "|" PW_STRINGIFY(flags) "|" module "|" group \
"|" label "|" type)