jfjoch_broker: Add option to HTTP profiling

This commit is contained in:
2025-12-03 16:31:20 +01:00
parent 396b132af4
commit d74c9694fa
9 changed files with 101 additions and 14 deletions

View File

@@ -10,10 +10,12 @@
#include "../preview/JFJochTIFF.h"
JFJochBrokerHttp::JFJochBrokerHttp(const DiffractionExperiment &experiment,
const SpotFindingSettings& spot_finding_settings,
std::shared_ptr<Pistache::Rest::Router> &rtr)
: DefaultApi(rtr),
state_machine(experiment, services, logger, spot_finding_settings) {
const SpotFindingSettings &spot_finding_settings,
std::shared_ptr<Pistache::Rest::Router> &rtr,
bool profiling)
: DefaultApi(rtr),
http_profiling(profiling),
state_machine(experiment, services, logger, spot_finding_settings) {
Pistache::Rest::Routes::Get(*rtr, "/", Pistache::Rest::Routes::bind(&JFJochBrokerHttp::GetStaticFile, this));
Pistache::Rest::Routes::Get(*rtr, "/frontend", Pistache::Rest::Routes::bind(&JFJochBrokerHttp::GetStaticFile, this));
Pistache::Rest::Routes::Get(*rtr, "/frontend/*", Pistache::Rest::Routes::bind(&JFJochBrokerHttp::GetStaticFile, this));
@@ -55,7 +57,9 @@ void JFJochBrokerHttp::start_post(const org::openapitools::server::model::Datase
}
void JFJochBrokerHttp::status_get(Pistache::Http::ResponseWriter &response) {
const auto start = std::chrono::steady_clock::now();
ProcessOutput(Convert(state_machine.GetStatus()), response);
LogRequestDuration("status_get", start);
}
@@ -460,15 +464,20 @@ void JFJochBrokerHttp::image_buffer_clear_post(Pistache::Http::ResponseWriter &r
void JFJochBrokerHttp::image_buffer_image_cbor_get(const std::optional<int64_t> &imageNumber,
Pistache::Http::ResponseWriter &response) {
const auto start = std::chrono::steady_clock::now();
std::vector<uint8_t> tmp_vector;
state_machine.GetImageFromBuffer(tmp_vector, imageNumber.value_or(-1));
std::string s = std::string((char *) tmp_vector.data(), tmp_vector.size());
if (!s.empty())
if (!s.empty()) {
LogRequestDuration("image_buffer_image_cbor_get", start);
response.send(Pistache::Http::Code::Ok, s,
Pistache::Http::Mime::MediaType::fromString("application/cbor"));
else
} else {
LogRequestDuration("image_buffer_image_cbor_get (not found)", start);
response.send(Pistache::Http::Code::Not_Found);
}
}
void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t> &id,
@@ -482,6 +491,8 @@ void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t>
const std::optional<std::string> &color,
const std::optional<bool> &showResEst,
Pistache::Http::ResponseWriter &response) {
const auto start = std::chrono::steady_clock::now();
int64_t image_id = id.value_or(ImageBuffer::MaxImage);
PreviewImageSettings settings{};
@@ -501,10 +512,13 @@ void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t>
settings.show_beam_center = showBeamCenter.value_or(true);
settings.format = PreviewImageFormat::JPEG;
std::string s = state_machine.GetPreviewJPEG(settings, image_id);
if (!s.empty())
if (!s.empty()) {
LogRequestDuration("image_buffer_image_jpeg_get", start);
response.send(Pistache::Http::Code::Ok, s, Pistache::Http::Mime::MediaType::fromString("image/jpeg"));
else
} else {
LogRequestDuration("image_buffer_image_jpeg_get (not found)", start);
response.send(Pistache::Http::Code::Not_Found);
}
}
void
@@ -521,15 +535,20 @@ JFJochBrokerHttp::image_buffer_image_tiff_get(const std::optional<int64_t> &id,
}
void JFJochBrokerHttp::image_buffer_start_cbor_get(Pistache::Http::ResponseWriter &response) {
const auto start = std::chrono::steady_clock::now();
std::vector<uint8_t> tmp_vector;
state_machine.GetStartMessageFromBuffer(tmp_vector);
std::string s = std::string((char *) tmp_vector.data(), tmp_vector.size());
if (!s.empty())
if (!s.empty()) {
LogRequestDuration("image_buffer_start_cbor_get", start);
response.send(Pistache::Http::Code::Ok, s,
Pistache::Http::Mime::MediaType::fromString("application/cbor"));
else
} else {
LogRequestDuration("image_buffer_start_cbor_get (not found)", start);
response.send(Pistache::Http::Code::Not_Found);
}
}
void JFJochBrokerHttp::image_buffer_status_get(Pistache::Http::ResponseWriter &response) {
@@ -551,6 +570,8 @@ void JFJochBrokerHttp::preview_plot_get(const std::optional<std::string> &type,
const std::optional<bool> &compression, const std::optional<float> &fill,
const std::optional<bool> &experimentalCoord,
const std::optional<std::string> &azintUnit, Pistache::Http::ResponseWriter &response) {
const auto start = std::chrono::steady_clock::now();
PlotAzintUnit unit = PlotAzintUnit::Q_recipA;
if (azintUnit.has_value()) {
if (azintUnit == "Q_recipA" || azintUnit == "q_recipa")
@@ -576,9 +597,12 @@ void JFJochBrokerHttp::preview_plot_get(const std::optional<std::string> &type,
req.binning = binning.value();
}
auto plot = state_machine.GetPlots(req);
LogRequestDuration("preview_plot_get", start);
ProcessOutput(Convert(plot), response, compression.value_or(false));
}
void JFJochBrokerHttp::config_indexing_get(Pistache::Http::ResponseWriter &response) {
ProcessOutput(Convert(state_machine.GetIndexingSettings()), response);
}
@@ -605,3 +629,11 @@ void JFJochBrokerHttp::config_dark_mask_put(const org::openapitools::server::mod
void JFJochBrokerHttp::config_dark_mask_get(Pistache::Http::ResponseWriter &response) {
ProcessOutput(Convert(state_machine.GetDarkMaskSettings()), response);
}
void JFJochBrokerHttp::LogRequestDuration(const char *operation,
const std::chrono::steady_clock::time_point &start) noexcept {
using namespace std::chrono;
const auto elapsed_ms = duration_cast<milliseconds>(steady_clock::now() - start).count();
if (http_profiling)
logger.Info("HTTP {} completed in {} ms", operation, static_cast<long long>(elapsed_ms));
}

View File

@@ -19,6 +19,8 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
Logger logger{"JFJochBroker"};
JFJochServices services {logger};
bool http_profiling = false;
void config_image_format_get(Pistache::Http::ResponseWriter &response) override;
void config_image_format_put(const org::openapitools::server::model::Image_format_settings &imageFormatSettings,
@@ -183,7 +185,8 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
public:
JFJochBrokerHttp(const DiffractionExperiment& experiment,
const SpotFindingSettings &spot_finding_settings,
std::shared_ptr<Pistache::Rest::Router> &rtr);
std::shared_ptr<Pistache::Rest::Router> &rtr,
bool profiling = false);
void AddDetectorSetup(const DetectorSetup &setup);
JFJochServices& Services();
@@ -197,6 +200,9 @@ private:
void config_file_writer_put(const org::openapitools::server::model::File_writer_settings &fileWriterSettings,
Pistache::Http::ResponseWriter &response) override;
void LogRequestDuration(const char *operation,
const std::chrono::steady_clock::time_point &start) noexcept;
};

View File

@@ -33,6 +33,8 @@ Jfjoch_settings::Jfjoch_settings()
m_Image_buffer_MiBIsSet = false;
m_Verbose = false;
m_VerboseIsSet = false;
m_Http_profile = false;
m_Http_profileIsSet = false;
m_Receiver_threads = 64;
m_Receiver_threadsIsSet = false;
m_Numa_policy = "";
@@ -121,7 +123,7 @@ bool Jfjoch_settings::validate(std::stringstream& msg, const std::string& pathPr
}
}
if (receiverThreadsIsSet())
{
const int32_t& value = m_Receiver_threads;
@@ -183,6 +185,9 @@ bool Jfjoch_settings::operator==(const Jfjoch_settings& rhs) const
((!verboseIsSet() && !rhs.verboseIsSet()) || (verboseIsSet() && rhs.verboseIsSet() && isVerbose() == rhs.isVerbose())) &&
((!httpProfileIsSet() && !rhs.httpProfileIsSet()) || (httpProfileIsSet() && rhs.httpProfileIsSet() && isHttpProfile() == rhs.isHttpProfile())) &&
((!receiverThreadsIsSet() && !rhs.receiverThreadsIsSet()) || (receiverThreadsIsSet() && rhs.receiverThreadsIsSet() && getReceiverThreads() == rhs.getReceiverThreads())) &&
@@ -241,6 +246,8 @@ void to_json(nlohmann::json& j, const Jfjoch_settings& o)
j["image_buffer_MiB"] = o.m_Image_buffer_MiB;
if(o.verboseIsSet())
j["verbose"] = o.m_Verbose;
if(o.httpProfileIsSet())
j["http_profile"] = o.m_Http_profile;
if(o.receiverThreadsIsSet())
j["receiver_threads"] = o.m_Receiver_threads;
if(o.numaPolicyIsSet())
@@ -313,6 +320,11 @@ void from_json(const nlohmann::json& j, Jfjoch_settings& o)
j.at("verbose").get_to(o.m_Verbose);
o.m_VerboseIsSet = true;
}
if(j.find("http_profile") != j.end())
{
j.at("http_profile").get_to(o.m_Http_profile);
o.m_Http_profileIsSet = true;
}
if(j.find("receiver_threads") != j.end())
{
j.at("receiver_threads").get_to(o.m_Receiver_threads);
@@ -531,6 +543,23 @@ void Jfjoch_settings::unsetVerbose()
{
m_VerboseIsSet = false;
}
bool Jfjoch_settings::isHttpProfile() const
{
return m_Http_profile;
}
void Jfjoch_settings::setHttpProfile(bool const value)
{
m_Http_profile = value;
m_Http_profileIsSet = true;
}
bool Jfjoch_settings::httpProfileIsSet() const
{
return m_Http_profileIsSet;
}
void Jfjoch_settings::unsetHttp_profile()
{
m_Http_profileIsSet = false;
}
int32_t Jfjoch_settings::getReceiverThreads() const
{
return m_Receiver_threads;

View File

@@ -150,6 +150,13 @@ public:
bool verboseIsSet() const;
void unsetVerbose();
/// <summary>
/// Print profiling information for HTTP requests
/// </summary>
bool isHttpProfile() const;
void setHttpProfile(bool const value);
bool httpProfileIsSet() const;
void unsetHttp_profile();
/// <summary>
/// Number of threads used by the receiver
/// </summary>
int32_t getReceiverThreads() const;
@@ -234,6 +241,8 @@ protected:
bool m_Image_buffer_MiBIsSet;
bool m_Verbose;
bool m_VerboseIsSet;
bool m_Http_profile;
bool m_Http_profileIsSet;
int32_t m_Receiver_threads;
bool m_Receiver_threadsIsSet;
std::string m_Numa_policy;

View File

@@ -2116,6 +2116,10 @@ components:
type: boolean
default: false
description: Print extra debug information
http_profile:
type: boolean
default: false
description: Print profiling information for HTTP requests
receiver_threads:
type: integer
minimum: 1

View File

@@ -129,7 +129,9 @@ int main (int argc, char **argv) {
std::vector<int> sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP};
setUpUnixSignals(sigs);
JFJochBrokerHttp broker(experiment, spot_finding_settings, router);
JFJochBrokerHttp broker(experiment, spot_finding_settings, router,
settings.isHttpProfile());
broker.FrontendDirectory(settings.getFrontendDirectory());
for (const auto &d: det_setup)

File diff suppressed because one or more lines are too long

View File

@@ -17,6 +17,7 @@ Name | Type | Description | Notes
**image_format** | [**ImageFormatSettings**](ImageFormatSettings.md) | | [optional]
**image_buffer_mi_b** | **int** | Size of internal buffer in MiB for images before they are sent to a stream | [optional] [default to 2048]
**verbose** | **bool** | Print extra debug information | [optional] [default to False]
**http_profile** | **bool** | Print profiling information for HTTP requests | [optional] [default to False]
**receiver_threads** | **int** | Number of threads used by the receiver | [optional] [default to 64]
**numa_policy** | **str** | NUMA policy to bind CPUs | [optional]
**frontend_directory** | **str** | Location of built JavaScript web frontend |

View File

@@ -41,6 +41,10 @@ export type jfjoch_settings = {
* Print extra debug information
*/
verbose?: boolean;
/**
* Print profiling information for HTTP requests
*/
http_profile?: boolean;
/**
* Number of threads used by the receiver
*/