diff --git a/docker-compose.yml b/docker-compose.yml index a94aba38..29477d55 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -211,6 +211,8 @@ services: container_name: prometheus ports: - "9090:9090" + extra_hosts: + - "host.docker.internal:host-gateway" volumes: - ./prometheus-config.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus diff --git a/prometheus-config.yml b/prometheus-config.yml index d2e6b8ed..3388fbb0 100644 --- a/prometheus-config.yml +++ b/prometheus-config.yml @@ -6,4 +6,9 @@ scrape_configs: - job_name: "fastapi" metrics_path: /metrics static_configs: - - targets: ["backend:8000"] \ No newline at end of file + - targets: ["backend:8000"] + + - job_name: "renderer" + metrics_path: /metrics + static_configs: + - targets: ["host.docker.internal:9092"] \ No newline at end of file diff --git a/renderer/CMakeLists.txt b/renderer/CMakeLists.txt index dc8b87ae..88641e97 100644 --- a/renderer/CMakeLists.txt +++ b/renderer/CMakeLists.txt @@ -49,6 +49,5 @@ if(BUILD_WORKER) endif() if(BUILD_TESTS) - message(STATUS "Building tests") add_subdirectory(tests) endif() \ No newline at end of file diff --git a/renderer/README.md b/renderer/README.md index 6e98daf8..e42d8c18 100644 --- a/renderer/README.md +++ b/renderer/README.md @@ -145,6 +145,7 @@ docker run --rm renderer renderer_cli [ | `-c, --camera` | `vec3 vec3 float` | Set camera: `position lookAt fov` | | `-B, --background` | `vec3` | Set background color (default: vec3(0,0,0)) | | `-S, --sun` | `vec3 vec3 float` | Set sun: `color direction exponent` | +| `-M, --metrics` | `-` | Shows rendering statistics |; --- @@ -331,7 +332,9 @@ docker run --rm --entrypoint /bin/sh renderer -c "cd build/tests && ctest --outp ```bash cd renderer mkdir build && cd build -cmake .. -DBUILD_MODE=CORE +cmake .. -DBUILD_MODE=CORE -DBUILD_TESTS=ON cmake --build . +cd tests +ctest --output-on-failure ./test ``` diff --git a/renderer/cli/src/main.cpp b/renderer/cli/src/main.cpp index c7320264..2705be4c 100644 --- a/renderer/cli/src/main.cpp +++ b/renderer/cli/src/main.cpp @@ -6,6 +6,7 @@ #include "context-guard.hpp" #include "logger.hpp" +#include "metrics.hpp" #include "render-engine.hpp" #include "scene-loader.hpp" #include "scene.hpp" @@ -30,6 +31,7 @@ void printHelp(std::string_view programName) { std::println(" -c, --camera Set camera properties: origin, direction, fov"); std::println(" -B, --background Set background color (default: vec3(0,0,0))"); std::println(" -S, --sun Set sun properties: color, direction, exponent"); + std::println(" -M, --metrics Shows rendering statistics"); } void printUsage(std::string_view programName) { @@ -74,6 +76,7 @@ int main(int argc, char* argv[]) { bool cameraSet = false; bool sunSet = false; Scene::Sun sun; + bool showMetrics = false; for (int i = 5; i < argc; i++) { std::string arg = argv[i]; @@ -84,6 +87,8 @@ int main(int argc, char* argv[]) { logger.showDebug = true; else if (arg == "-d" || arg == "--debug") debugImages = true; + else if (arg == "-M" || arg == "--metrics") + showMetrics = true; else if (arg == "-o" || arg == "--output") { if (i + 1 == argc) { std::println(std::cerr, "Error: {} requires an argument", arg); @@ -174,7 +179,8 @@ int main(int argc, char* argv[]) { if (cameraSet) scene.setCamera(userCamera); if (sunSet) scene.setSun(sun); std::shared_ptr egl = TargetManager::getInstance().createEGLTarget(width, height); - engine.renderFrame(*egl, scene, samples); + Metrics metrics; + engine.renderFrame(*egl, scene, samples, metrics); auto* eglTarget = dynamic_cast(egl.get()); if (eglTarget) { @@ -203,6 +209,56 @@ int main(int argc, char* argv[]) { absoluteDirectoryPath / (outputFilename + "-heat.png")); } } + if (showMetrics) { + auto line = [](std::string_view label, auto&& value, std::string_view unit = "") { + std::println(" {:<18}{:>10} {}", label, value, unit); + }; + auto timeLine = [&](std::string_view label, const std::optional& t) { + if (!t) return; + std::string pct; + if (metrics.totalTime && metrics.totalTime->count() > 0) { + const double p = 100.0 * t->count() / metrics.totalTime->count(); + pct = std::format(" ({:>5.1f}%)", p); + } + std::println(" {:<18}{:>8} ms{}", label, t->count(), pct); + }; + + std::println("\nRender statistics"); + std::println("─────────────────────────────────────────"); + + bool anyImage = metrics.width || metrics.height || metrics.samples; + if (anyImage) { + std::println("[ Image ]"); + if (metrics.width && metrics.height) + std::println(" {:<18}{:>5} x {:<5}", "Resolution", *metrics.width, *metrics.height); + if (metrics.samples) line("Samples", *metrics.samples); + } + + if (metrics.polygonsCount || metrics.texturesCount) { + if (anyImage) std::println(); + std::println("[ Scene ]"); + if (metrics.polygonsCount) line("Polygons", *metrics.polygonsCount); + if (metrics.texturesCount) line("Textures", *metrics.texturesCount); + } + + bool anyTime = metrics.BVHBuildingTime || metrics.pathTracingTime || metrics.gbufferFillingTime || + metrics.postProcessingTime || metrics.denoisingTime || metrics.upscalingTime; + if (anyTime) { + if (anyImage || metrics.polygonsCount || metrics.texturesCount) std::println(); + std::println("[ Timings ]"); + timeLine("BVH building", metrics.BVHBuildingTime); + timeLine("Path tracing", metrics.pathTracingTime); + timeLine("G-buffer", metrics.gbufferFillingTime); + timeLine("Denoising", metrics.denoisingTime); + timeLine("Post-processing", metrics.postProcessingTime); + timeLine("Upscaling", metrics.upscalingTime); + } + + if (metrics.totalTime) { + std::println("─────────────────────────────────────────"); + std::println(" {:<18}{:>8} ms", "Total", metrics.totalTime->count()); + } + } logger.info("Renderer application stopped successfully"); return EXIT_SUCCESS; } catch (const std::exception& e) { diff --git a/renderer/common/include/metrics.hpp b/renderer/common/include/metrics.hpp new file mode 100644 index 00000000..86db4ecd --- /dev/null +++ b/renderer/common/include/metrics.hpp @@ -0,0 +1,18 @@ +#pragma once +#include + +struct Metrics { + std::optional pathTracingTime; + std::optional gbufferFillingTime; + std::optional postProcessingTime; + std::optional BVHBuildingTime; + std::optional upscalingTime; + std::optional denoisingTime; + std::optional totalTime; + std::optional polygonsCount; + std::optional texturesCount; + std::optional width; + std::optional height; + std::optional samples; + std::optional renderingSuccess; +}; \ No newline at end of file diff --git a/renderer/core/include/render-engine.hpp b/renderer/core/include/render-engine.hpp index 7c69eccd..26f05348 100644 --- a/renderer/core/include/render-engine.hpp +++ b/renderer/core/include/render-engine.hpp @@ -1,8 +1,10 @@ #pragma once #include +#include +#include +#include #include -#include #include "bvh-builder.hpp" #include "bvh.hpp" @@ -59,6 +61,7 @@ class RenderEngine { public: RenderEngine(); + void renderFrame(RenderTarget& target, const Scene& scene, int samples, Metrics& metrics); void renderFrame(RenderTarget& target, const Scene& scene, int samples); void destroy(); std::atomic stopRequested{false}; @@ -66,9 +69,9 @@ class RenderEngine { private: void pathTracing(RenderTarget& target, const Scene::Camera& camera, const glm::vec3& backgroundColor, - const Scene::Sun& sun, int samples); - void fillGbuffer(RenderTarget& target, const GPUData& gpuData, const Scene::Camera& camera); - void postProcess(RenderTarget& target) const; + const Scene::Sun& sun, int samples, Metrics& metrics); + void fillGbuffer(RenderTarget& target, const GPUData& gpuData, const Scene::Camera& camera, Metrics& metrics); + void postProcess(RenderTarget& target, Metrics& metrics) const; void uploadGPUBuffers(const GPUData& gpuData, const BVH& bvh); GLuint compileShader(const std::string& source); void loadTextures(const std::vector& textures); diff --git a/renderer/core/src/render-engine.cpp b/renderer/core/src/render-engine.cpp index b60d1f7c..cc488ea2 100644 --- a/renderer/core/src/render-engine.cpp +++ b/renderer/core/src/render-engine.cpp @@ -178,7 +178,7 @@ GLuint RenderEngine::compileShader(const std::string& source) { } void RenderEngine::pathTracing(RenderTarget& target, const Scene::Camera& camera, const glm::vec3& backgroundColor, - const Scene::Sun& sun, int samples) { + const Scene::Sun& sun, int samples, Metrics& metrics) { logger.info("Path tracing started"); glUseProgram(pathTracingProgram); @@ -231,12 +231,14 @@ void RenderEngine::pathTracing(RenderTarget& target, const Scene::Camera& camera } auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end - start); + metrics.pathTracingTime = duration; logger.info(std::format("Path tracing finished in {}ms", duration.count())); glUseProgram(0); } -void RenderEngine::fillGbuffer(RenderTarget& target, const GPUData& gpuData, const Scene::Camera& camera) { +void RenderEngine::fillGbuffer(RenderTarget& target, const GPUData& gpuData, const Scene::Camera& camera, + Metrics& metrics) { logger.debug("Filling gbuffer"); glUseProgram(gbufferProgram); glBindImageTexture(0, target.getNormalMap(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); @@ -266,11 +268,12 @@ void RenderEngine::fillGbuffer(RenderTarget& target, const GPUData& gpuData, con glFinish(); auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end - start); + metrics.gbufferFillingTime = duration; logger.debug(std::format("gbuffer filling finished in {}ms", duration.count())); glUseProgram(0); } -void RenderEngine::postProcess(RenderTarget& target) const { +void RenderEngine::postProcess(RenderTarget& target, Metrics& metrics) const { logger.info("Post processing started"); glUseProgram(postProcessingProgram); glBindImageTexture(0, target.getDenoisedTexture(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); @@ -288,6 +291,7 @@ void RenderEngine::postProcess(RenderTarget& target) const { glFinish(); auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end - start); + metrics.postProcessingTime = duration; logger.info(std::format("Post processing finished in {}ms", duration.count())); glUseProgram(0); } @@ -427,7 +431,17 @@ void RenderEngine::loadTextures(const std::vector& textures) } void RenderEngine::renderFrame(RenderTarget& target, const Scene& scene, int samples) { + Metrics metrics; + renderFrame(target, scene, samples, metrics); +} + +void RenderEngine::renderFrame(RenderTarget& target, const Scene& scene, int samples, Metrics& metrics) { try { + metrics.samples = samples; + metrics.width = target.getWidth(); + metrics.height = target.getHeight(); + + auto toatalRenderingTimeStart = std::chrono::steady_clock::now(); logger.info(std::format("Rendering started ({}x{})", target.getWidth(), target.getHeight())); ContextGuard context(target); glClearTexImage(target.getRawTexture(), 0, GL_RGBA, GL_FLOAT, nullptr); @@ -437,7 +451,12 @@ void RenderEngine::renderFrame(RenderTarget& target, const Scene& scene, int sam GPUData gpuData = convertSceneToGPUData(scene); BVH bvh; try { + auto start = std::chrono::steady_clock::now(); bvh = std::move(bvhBuilder.build(gpuData.vertices, gpuData.vertexIndices)); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + metrics.BVHBuildingTime = duration; + } catch (const std::exception& e) { logger.error(std::format("BVH building failed: {}", e.what())); throw; @@ -449,7 +468,9 @@ void RenderEngine::renderFrame(RenderTarget& target, const Scene& scene, int sam return; } loadTextures(scene.getTexturesData()); + metrics.texturesCount = scene.getTexturesData().size(); uploadGPUBuffers(gpuData, bvh); + metrics.polygonsCount = gpuData.vertexIndices.size() / 3; if (stopRequested.load(std::memory_order_relaxed)) { stopRequested = false; logger.info("Rendering stopped"); @@ -457,13 +478,13 @@ void RenderEngine::renderFrame(RenderTarget& target, const Scene& scene, int sam } auto sun = scene.getSun(); sun.direction = glm::normalize(sun.direction); - pathTracing(target, camera, scene.getBackgroundColor(), sun, samples); + pathTracing(target, camera, scene.getBackgroundColor(), sun, samples, metrics); if (stopRequested.load(std::memory_order_relaxed)) { stopRequested = false; logger.info("Rendering stopped"); return; } - fillGbuffer(target, gpuData, camera); + fillGbuffer(target, gpuData, camera, metrics); if (stopRequested.load(std::memory_order_relaxed)) { stopRequested = false; logger.info("Rendering stopped"); @@ -474,14 +495,20 @@ void RenderEngine::renderFrame(RenderTarget& target, const Scene& scene, int sam denoiser.denoise(target); auto end = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end - start); + metrics.denoisingTime = duration; logger.info(std::format("Denoising finished in {}ms", duration.count())); if (stopRequested.load(std::memory_order_relaxed)) { stopRequested = false; logger.info("Rendering stopped"); return; } - postProcess(target); + postProcess(target, metrics); + auto toatalRenderingTimeEnd = std::chrono::steady_clock::now(); + metrics.totalTime = + std::chrono::duration_cast(toatalRenderingTimeEnd - toatalRenderingTimeStart); + metrics.renderingSuccess = true; } catch (const std::exception& e) { + metrics.renderingSuccess = false; logger.error(std::format("Rendering failed. Reason: {}", e.what())); throw; } diff --git a/renderer/worker/CMakeLists.txt b/renderer/worker/CMakeLists.txt index 1eec4522..27941dce 100644 --- a/renderer/worker/CMakeLists.txt +++ b/renderer/worker/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable(service src/s3-client.cpp src/dotenv.cpp src/config.cpp + src/prometheus.cpp ) target_include_directories(service PRIVATE diff --git a/renderer/worker/include/config.hpp b/renderer/worker/include/config.hpp index f6378ada..1c0e6cec 100644 --- a/renderer/worker/include/config.hpp +++ b/renderer/worker/include/config.hpp @@ -12,6 +12,7 @@ class Config { std::optional kafkaTopicOutput_; std::optional kafkaTopicDLQ_; std::optional kafkaTopicCommands_; + std::optional prometheusHost_; int maxRetries_ = 5; // default std::optional s3Host_; std::optional s3AccessKey_; @@ -29,6 +30,7 @@ class Config { void fromEnvironment(); std::string kafkaHost() const; + std::string prometheusHost() const; std::string kafkaTasksGroupID() const; std::string kafkaCommandsGroupId() const; std::string kafkaTopicTasks() const; diff --git a/renderer/worker/include/contract.hpp b/renderer/worker/include/contract.hpp index eac12b58..68551a0c 100644 --- a/renderer/worker/include/contract.hpp +++ b/renderer/worker/include/contract.hpp @@ -1,4 +1,5 @@ #pragma once +#include "metrics.hpp" struct TaskHeader { int width; @@ -15,4 +16,5 @@ struct TaskHeader { struct ResultHeader { unsigned long long resultDataSize; + Metrics metrics; }; \ No newline at end of file diff --git a/renderer/worker/include/prometheus.hpp b/renderer/worker/include/prometheus.hpp new file mode 100644 index 00000000..8c63c426 --- /dev/null +++ b/renderer/worker/include/prometheus.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include "logger.hpp" +#include "metrics.hpp" + +class Prometheus { + Logger logger; + + public: + explicit Prometheus(const std::string& address); + + void onRenderStarted(); + void onRenderFinished(const Metrics& metrics); + + private: + std::unique_ptr exposer; + std::shared_ptr registry; + + prometheus::Counter* rendersTotal; + prometheus::Counter* failedRenders; + + prometheus::Gauge* activeRenders; + + prometheus::Histogram* renderDuration; + prometheus::Histogram* bvhBuildDuration; + prometheus::Histogram* pathTracingDuration; + prometheus::Histogram* denoisingDuration; + prometheus::Histogram* upscalingDuration; +}; \ No newline at end of file diff --git a/renderer/worker/lib/CMakeLists.txt b/renderer/worker/lib/CMakeLists.txt index eea0236d..f7a81a39 100644 --- a/renderer/worker/lib/CMakeLists.txt +++ b/renderer/worker/lib/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(cppkafka) add_subdirectory(json) +add_subdirectory(prometheus) find_package(aws-sdk-cpp) @@ -9,6 +10,8 @@ target_link_libraries(renderer_worker_deps INTERFACE nlohmann_json::nlohmann_json aws-cpp-sdk-core aws-cpp-sdk-s3 + prometheus-cpp::core + prometheus-cpp::pull ) target_include_directories(renderer_worker_deps INTERFACE diff --git a/renderer/worker/lib/prometheus/CMakeLists.txt b/renderer/worker/lib/prometheus/CMakeLists.txt new file mode 100644 index 00000000..bbd4b8c3 --- /dev/null +++ b/renderer/worker/lib/prometheus/CMakeLists.txt @@ -0,0 +1,9 @@ +FetchContent_Declare( + prometheus-cpp + GIT_REPOSITORY https://github.com/jupp0r/prometheus-cpp.git + GIT_TAG v1.0.2 +) + +set(BUILD_TESTS OFF) +set(ENABLE_TESTING OFF) +FetchContent_MakeAvailable(prometheus-cpp) \ No newline at end of file diff --git a/renderer/worker/src/config.cpp b/renderer/worker/src/config.cpp index cc2cb258..22861634 100644 --- a/renderer/worker/src/config.cpp +++ b/renderer/worker/src/config.cpp @@ -22,6 +22,7 @@ void Config::apply(env::dotenv dotenv) { rendererPreviewMaxSize_ = dotenv["RENDERER_PREVIEW_MAX_SIZE"]; if (dotenv.hasVariable("RENDERER_PREVIEW_UPSCALE_FACTOR")) rendererPreviewUpscaleFactor_ = dotenv["RENDERER_PREVIEW_UPSCALE_FACTOR"]; + if (dotenv.hasVariable("PROMETHEUS_HOST")) prometheusHost_ = dotenv["PROMETHEUS_HOST"]; } catch (const env::Value::ValueError& e) { throw std::runtime_error(std::format("Invalid value format in .env file. Error: {}.", e.what())); } @@ -45,6 +46,7 @@ void Config::fromEnvironment() { if (char* ptr = std::getenv("RENDERER_PREVIEW")) rendererPreview_ = env::Value(ptr); if (char* ptr = std::getenv("RENDERER_PREVIEW_MAX_SIZE")) rendererPreviewMaxSize_ = env::Value(ptr); if (char* ptr = std::getenv("RENDERER_PREVIEW_UPSCALE_FACTOR")) rendererPreviewUpscaleFactor_ = env::Value(ptr); + if (char* ptr = std::getenv("PROMETHEUS_HOST")) prometheusHost_ = env::Value(ptr); } catch (const env::Value::ValueError& e) { throw std::runtime_error(std::format("Invalid environment variable value format. Error: {}.", e.what())); } @@ -119,6 +121,13 @@ std::string Config::s3SecretKey() const { return s3SecretKey_.value(); } +std::string Config::prometheusHost() const { + if (!prometheusHost_.has_value()) { + throw std::runtime_error("PROMETHEUS_HOST not configured"); + } + return prometheusHost_.value(); +} + Logger::Level Config::logLevel() const { return logLevel_; } bool Config::logDebug() const { return logDebug_; } bool Config::rendererPreview() const { return rendererPreview_; } diff --git a/renderer/worker/src/prometheus.cpp b/renderer/worker/src/prometheus.cpp new file mode 100644 index 00000000..b7a6d9b0 --- /dev/null +++ b/renderer/worker/src/prometheus.cpp @@ -0,0 +1,77 @@ +#include "prometheus.hpp" + +#include +#include +#include +Prometheus::Prometheus(const std::string& address) + : exposer(std::make_unique(address)), + registry(std::make_shared()), + logger("PROMETHEUS") { + rendersTotal = + &prometheus::BuildCounter().Name("renders_total").Help("Total number of renders.").Register(*registry).Add({}); + + activeRenders = + &prometheus::BuildGauge().Name("active_renders").Help("Number of active renders.").Register(*registry).Add({}); + + failedRenders = &prometheus::BuildCounter() + .Name("failed_renders_total") + .Help("Total number of failed renders.") + .Register(*registry) + .Add({}); + + const prometheus::Histogram::BucketBoundaries buckets{0.01, 0.1, 0.5, 1.0, 5.0, 10.0, + 30.0, 60.0, 120.0, 180.0, 240.0, 300.0}; + + renderDuration = &prometheus::BuildHistogram() + .Name("render_duration_seconds") + .Help("Render duration in seconds.") + .Register(*registry) + .Add({}, buckets); + + bvhBuildDuration = &prometheus::BuildHistogram() + .Name("bvh_build_duration_seconds") + .Help("BVH building duration in seconds.") + .Register(*registry) + .Add({}, buckets); + + pathTracingDuration = &prometheus::BuildHistogram() + .Name("path_tracing_duration_seconds") + .Help("Path tracing duration in seconds.") + .Register(*registry) + .Add({}, buckets); + + denoisingDuration = &prometheus::BuildHistogram() + .Name("denoising_duration_seconds") + .Help("Denoising duration in seconds.") + .Register(*registry) + .Add({}, buckets); + + upscalingDuration = &prometheus::BuildHistogram() + .Name("upscaling_duration_seconds") + .Help("Preview upscaling duration in seconds.") + .Register(*registry) + .Add({}, buckets); + + exposer->RegisterCollectable(registry); + + logger.debug(std::format("Prometheus metrics server started on {}", address)); +} + +void Prometheus::onRenderStarted() { activeRenders->Increment(); } + +void Prometheus::onRenderFinished(const Metrics& metrics) { + activeRenders->Decrement(); + rendersTotal->Increment(); + + if (metrics.renderingSuccess && !*metrics.renderingSuccess) failedRenders->Increment(); + + if (metrics.totalTime) renderDuration->Observe(metrics.totalTime->count() / 1000.0); + + if (metrics.BVHBuildingTime) bvhBuildDuration->Observe(metrics.BVHBuildingTime->count() / 1000.0); + + if (metrics.pathTracingTime) pathTracingDuration->Observe(metrics.pathTracingTime->count() / 1000.0); + + if (metrics.denoisingTime) denoisingDuration->Observe(metrics.denoisingTime->count() / 1000.0); + + if (metrics.upscalingTime) upscalingDuration->Observe(metrics.upscalingTime->count() / 1000.0); +} \ No newline at end of file diff --git a/renderer/worker/src/renderer.cpp b/renderer/worker/src/renderer.cpp index 01efe0a0..1761f7fd 100644 --- a/renderer/worker/src/renderer.cpp +++ b/renderer/worker/src/renderer.cpp @@ -162,7 +162,16 @@ int main() try { sun.exponent = task.sun.exponent; scene.setSun(sun); - engine->renderFrame(*egl, scene, task.samples); + Metrics metrics; + try { + engine->renderFrame(*egl, scene, task.samples, metrics); + } catch (const std::exception& e) { + ResultHeader resultHeader; + resultHeader.resultDataSize = 0; + resultHeader.metrics = metrics; + write(STDOUT_FILENO, &resultHeader, sizeof(resultHeader)); + logger.debug(std::format("Write {} bytes in pipe for resultHeader", sizeof(resultHeader))); + } if (!stopRequested) { ContextGuard guard(*egl); auto data = egl->getBufferData(egl->getOutputTexture()); @@ -176,6 +185,7 @@ int main() try { } std::vector result = utils::writeToPng(data, task.width, task.height, 4); ResultHeader resultHeader; + resultHeader.metrics = metrics; resultHeader.resultDataSize = result.size(); write(STDOUT_FILENO, &resultHeader, sizeof(resultHeader)); logger.debug(std::format("Written {} bytes in pipe for resultHeader", sizeof(resultHeader))); @@ -185,6 +195,7 @@ int main() try { stopRequested = false; ResultHeader resultHeader; resultHeader.resultDataSize = 0; + resultHeader.metrics = metrics; write(STDOUT_FILENO, &resultHeader, sizeof(resultHeader)); logger.debug(std::format("Write {} bytes in pipe for resultHeader", sizeof(resultHeader))); } diff --git a/renderer/worker/src/service.cpp b/renderer/worker/src/service.cpp index aa915572..b32ebe45 100644 --- a/renderer/worker/src/service.cpp +++ b/renderer/worker/src/service.cpp @@ -18,6 +18,7 @@ #include "kafka-consumer.hpp" #include "kafka-producer.hpp" #include "logger.hpp" +#include "prometheus.hpp" #include "s3-client.hpp" using json = nlohmann::json; @@ -167,6 +168,8 @@ int main() try { KafkaConsumer commandConsumer(config.kafkaHost(), config.kafkaCommandsGroupId(), config.kafkaTopicCommands()); KafkaProducer producer(config.kafkaHost()); + Prometheus prometheus(config.prometheusHost()); + logger.info(std::format("Listening for messages...")); while (running) { int status; @@ -232,6 +235,7 @@ int main() try { write(STDOUT_FILENO, glbData.data(), glbData.size()); logger.debug(std::format("Written {} bytes in pipe for scene", glbData.size())); + prometheus.onRenderStarted(); while (running) { int status; pid_t result = waitpid(renderer_pid, &status, WNOHANG); @@ -314,6 +318,7 @@ int main() try { std::format("Reading from pipe truncates image (read only {}/{} bytes)", total_read, result.size())); } + prometheus.onRenderFinished(resultHeader.metrics); } taskConsumer.commit(); logger.info(std::format("Current message processing finished successfully. Listening..."));