diff options
Diffstat (limited to 'src/zen/trace/trace_viewer_service.cpp')
| -rw-r--r-- | src/zen/trace/trace_viewer_service.cpp | 91 |
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 |