aboutsummaryrefslogtreecommitdiff
path: root/src/zen/trace/trace_viewer_service.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zen/trace/trace_viewer_service.cpp')
-rw-r--r--src/zen/trace/trace_viewer_service.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/zen/trace/trace_viewer_service.cpp b/src/zen/trace/trace_viewer_service.cpp
index 7d8301ae2..cd5517613 100644
--- a/src/zen/trace/trace_viewer_service.cpp
+++ b/src/zen/trace/trace_viewer_service.cpp
@@ -382,6 +382,14 @@ TraceViewerService::HandleApiRequest(HttpServerRequest& Request, std::string_vie
{
HandleCsvMetadataApi(Request);
}
+ else if (Path == "counters"sv)
+ {
+ HandleCountersApi(Request);
+ }
+ else if (Path == "counter-series"sv)
+ {
+ HandleCounterSeriesApi(Request);
+ }
else if (Path == "alloc-summary"sv)
{
HandleAllocSummaryApi(Request);
@@ -887,6 +895,89 @@ TraceViewerService::HandleCsvMetadataApi(HttpServerRequest& Request)
Request.WriteResponse(HttpResponseCode::OK, Writer.Save().AsArray());
}
+void
+TraceViewerService::HandleCountersApi(HttpServerRequest& Request)
+{
+ // Map id -> sample count so the front-end can hide empty defs without a
+ // second round-trip.
+ eastl::hash_map<uint16_t, uint32_t> SeriesByCounterId;
+ SeriesByCounterId.reserve(m_Model.CounterTimeSeries.size());
+ for (const trace_detail::TraceModel::CounterSeries& S : m_Model.CounterTimeSeries)
+ {
+ SeriesByCounterId[S.Id] = S.Count;
+ }
+
+ CbWriter Writer;
+ Writer.BeginArray();
+ for (const trace_detail::TraceModel::CounterDef& D : m_Model.CounterDefs)
+ {
+ auto It = SeriesByCounterId.find(D.Id);
+ Writer.BeginObject();
+ Writer << "id" << D.Id;
+ Writer << "type" << D.Type;
+ Writer << "display_hint" << D.DisplayHint;
+ Writer << "name" << D.Name;
+ Writer << "sample_count" << (It != SeriesByCounterId.end() ? It->second : 0u);
+ Writer.EndObject();
+ }
+ Writer.EndArray();
+
+ Request.WriteResponse(HttpResponseCode::OK, Writer.Save().AsArray());
+}
+
+void
+TraceViewerService::HandleCounterSeriesApi(HttpServerRequest& Request)
+{
+ HttpServerRequest::QueryParams Params = Request.GetQueryParams();
+ std::string_view IdStr = Params.GetValue("id");
+ if (IdStr.empty())
+ {
+ Request.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "missing required query parameter 'id'");
+ return;
+ }
+ uint32_t WantedId = ParseUintParam(IdStr, 0);
+ if (WantedId == 0 || WantedId > 0xFFFF)
+ {
+ Request.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "invalid 'id' (must be 1..65535)");
+ return;
+ }
+
+ const trace_detail::TraceModel::CounterSeries* Found = nullptr;
+ for (const trace_detail::TraceModel::CounterSeries& S : m_Model.CounterTimeSeries)
+ {
+ if (S.Id == uint16_t(WantedId))
+ {
+ Found = &S;
+ break;
+ }
+ }
+
+ CbObjectWriter Obj;
+ Obj << "id" << uint32_t(WantedId);
+ if (Found != nullptr)
+ {
+ Obj << "type" << uint32_t(Found->Type);
+ Obj << "count" << Found->Count;
+ Obj << "min" << Found->Min;
+ Obj << "max" << Found->Max;
+ }
+ Obj.BeginArray("samples");
+ if (Found != nullptr)
+ {
+ // [time_us, value] tuples to keep the payload tight for large series.
+ for (const trace_detail::TraceModel::CounterSample& S : Found->Samples)
+ {
+ Obj.BeginArray();
+ Obj.AddInteger(uint32_t(S.TimeUs));
+ Obj.AddFloat(S.Value);
+ Obj.EndArray();
+ }
+ }
+ Obj.EndArray();
+
+ Request.WriteResponse(HttpResponseCode::OK, Obj.Save());
+}
+
//////////////////////////////////////////////////////////////////////////////
// Memory allocation endpoints