Add foundation tracing and platform build wrapper
This commit is contained in:
98
src/foundation/trace.cpp
Normal file
98
src/foundation/trace.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "foundation/trace.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace pp::foundation {
|
||||
|
||||
Result<TraceSpanId> TraceRecorder::begin_span(TraceSpanDesc desc, std::uint64_t start_us)
|
||||
{
|
||||
if (desc.component.empty()) {
|
||||
return Result<TraceSpanId>::failure(
|
||||
Status::invalid_argument("trace component must not be empty"));
|
||||
}
|
||||
|
||||
if (desc.name.empty()) {
|
||||
return Result<TraceSpanId>::failure(
|
||||
Status::invalid_argument("trace span name must not be empty"));
|
||||
}
|
||||
|
||||
if (next_id_ == std::numeric_limits<TraceSpanId>::max()) {
|
||||
return Result<TraceSpanId>::failure(
|
||||
Status::out_of_range("trace span id space is exhausted"));
|
||||
}
|
||||
|
||||
const auto id = next_id_++;
|
||||
ActiveSpan span;
|
||||
span.id = id;
|
||||
span.component.assign(desc.component);
|
||||
span.name.assign(desc.name);
|
||||
span.desc = desc;
|
||||
span.desc.component = span.component;
|
||||
span.desc.name = span.name;
|
||||
span.start_us = start_us;
|
||||
span.active = true;
|
||||
active_spans_.push_back(span);
|
||||
|
||||
return Result<TraceSpanId>::success(id);
|
||||
}
|
||||
|
||||
Status TraceRecorder::end_span(TraceSpanId id, std::uint64_t end_us)
|
||||
{
|
||||
ActiveSpan* span = find_active_span(id);
|
||||
if (span == nullptr) {
|
||||
return Status::out_of_range("trace span id is not active");
|
||||
}
|
||||
|
||||
if (end_us < span->start_us) {
|
||||
return Status::invalid_argument("trace span cannot end before it starts");
|
||||
}
|
||||
|
||||
TraceEvent event;
|
||||
event.component = span->component;
|
||||
event.name = span->name;
|
||||
event.thread_id = span->desc.thread_id;
|
||||
event.frame_id = span->desc.frame_id;
|
||||
event.stroke_id = span->desc.stroke_id;
|
||||
event.start_us = span->start_us;
|
||||
event.duration_us = end_us - span->start_us;
|
||||
events_.push_back(event);
|
||||
|
||||
span->active = false;
|
||||
return Status::success();
|
||||
}
|
||||
|
||||
std::span<const TraceEvent> TraceRecorder::events() const noexcept
|
||||
{
|
||||
return events_;
|
||||
}
|
||||
|
||||
std::size_t TraceRecorder::active_span_count() const noexcept
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for (const auto& span : active_spans_) {
|
||||
if (span.active) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void TraceRecorder::clear() noexcept
|
||||
{
|
||||
active_spans_.clear();
|
||||
events_.clear();
|
||||
next_id_ = 1;
|
||||
}
|
||||
|
||||
TraceRecorder::ActiveSpan* TraceRecorder::find_active_span(TraceSpanId id) noexcept
|
||||
{
|
||||
for (auto& span : active_spans_) {
|
||||
if (span.active && span.id == id) {
|
||||
return &span;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
60
src/foundation/trace.h
Normal file
60
src/foundation/trace.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace pp::foundation {
|
||||
|
||||
using TraceSpanId = std::uint64_t;
|
||||
|
||||
struct TraceSpanDesc {
|
||||
std::string_view component;
|
||||
std::string_view name;
|
||||
std::uint64_t thread_id = 0;
|
||||
std::uint64_t frame_id = 0;
|
||||
std::uint64_t stroke_id = 0;
|
||||
};
|
||||
|
||||
struct TraceEvent {
|
||||
std::string component;
|
||||
std::string name;
|
||||
std::uint64_t thread_id = 0;
|
||||
std::uint64_t frame_id = 0;
|
||||
std::uint64_t stroke_id = 0;
|
||||
std::uint64_t start_us = 0;
|
||||
std::uint64_t duration_us = 0;
|
||||
};
|
||||
|
||||
class TraceRecorder {
|
||||
public:
|
||||
[[nodiscard]] Result<TraceSpanId> begin_span(TraceSpanDesc desc, std::uint64_t start_us);
|
||||
[[nodiscard]] Status end_span(TraceSpanId id, std::uint64_t end_us);
|
||||
|
||||
[[nodiscard]] std::span<const TraceEvent> events() const noexcept;
|
||||
[[nodiscard]] std::size_t active_span_count() const noexcept;
|
||||
|
||||
void clear() noexcept;
|
||||
|
||||
private:
|
||||
struct ActiveSpan {
|
||||
TraceSpanId id = 0;
|
||||
TraceSpanDesc desc;
|
||||
std::string component;
|
||||
std::string name;
|
||||
std::uint64_t start_us = 0;
|
||||
bool active = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] ActiveSpan* find_active_span(TraceSpanId id) noexcept;
|
||||
|
||||
std::vector<ActiveSpan> active_spans_;
|
||||
std::vector<TraceEvent> events_;
|
||||
TraceSpanId next_id_ = 1;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user