summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorRutger Broekhoff2026-09-10 01:30:43 +0200
committerRutger Broekhoff2026-09-10 01:30:43 +0200
commit4031e77edd2abd694114be698312d086bce6b425 (patch)
tree85f13a278339841cacc81314170b59c97587fa27 /server
parent1417e6cf41d27c594d2bdc92f87746d2383a1b1d (diff)
downloadroutemon-4031e77edd2abd694114be698312d086bce6b425.tar.gz
routemon-4031e77edd2abd694114be698312d086bce6b425.zip
More tracing stuff
Diffstat (limited to 'server')
-rw-r--r--server/src/api.cpp14
-rw-r--r--server/src/api.cppm3
-rw-r--r--server/src/http_server.cpp34
-rw-r--r--server/src/http_server.cppm66
-rw-r--r--server/src/srv.cpp37
-rw-r--r--server/src/srv.cppm5
6 files changed, 101 insertions, 58 deletions
diff --git a/server/src/api.cpp b/server/src/api.cpp
index 41c49c8..f1ca24e 100644
--- a/server/src/api.cpp
+++ b/server/src/api.cpp
@@ -144,9 +144,11 @@ handler::handler(log::logger const& l, datex2::situation_publication pub)
144 l_.info("Point index size: {}", bpe_index_.size()); 144 l_.info("Point index size: {}", bpe_index_.size());
145} 145}
146 146
147auto handler::process_gpx(gpx::file&& gpx_file) 147auto handler::process_gpx(trace::id trace_id, gpx::file&& gpx_file)
148 -> std::optional<process_gpx_result> 148 -> std::optional<process_gpx_result>
149{ 149{
150 auto l = l_.with("trace_id", trace_id.as_string());
151
150 auto const now = chrono::utc_clock::now(); 152 auto const now = chrono::utc_clock::now();
151 auto const relevant = std::initializer_list<time::period>{ 153 auto const relevant = std::initializer_list<time::period>{
152 time::period{now - chrono::days(7), now + chrono::days(7)} 154 time::period{now - chrono::days(7), now + chrono::days(7)}
@@ -162,7 +164,7 @@ auto handler::process_gpx(gpx::file&& gpx_file)
162 164
163 auto vincenty_strategy = geo::wgs84::vincenty_strategy{}; 165 auto vincenty_strategy = geo::wgs84::vincenty_strategy{};
164 166
165 l_.debug("Querying for relevant situations"); 167 l.debug("Querying for relevant situations");
166 auto relevant_road_closures = 168 auto relevant_road_closures =
167 std::unordered_set<std::shared_ptr<datex2::road_closure>>{}; 169 std::unordered_set<std::shared_ptr<datex2::road_closure>>{};
168 auto ls_checked = 0uz; 170 auto ls_checked = 0uz;
@@ -170,7 +172,7 @@ auto handler::process_gpx(gpx::file&& gpx_file)
170 auto i = 0; 172 auto i = 0;
171 for (auto const& part : segments) 173 for (auto const& part : segments)
172 { 174 {
173 l_.debug("Checking part [{}/{}]", ++i, segments.size()); 175 l.debug("Checking part [{}/{}]", ++i, segments.size());
174 176
175 auto part_zone_lss = 177 auto part_zone_lss =
176 geo::utm::multizonal::split_linestring_across_zones(part); 178 geo::utm::multizonal::split_linestring_across_zones(part);
@@ -206,7 +208,7 @@ auto handler::process_gpx(gpx::file&& gpx_file)
206 } 208 }
207 209
208 auto const after_query = chrono::steady_clock::now(); 210 auto const after_query = chrono::steady_clock::now();
209 l_.debug( 211 l.debug(
210 "Done (checked {} line string(s) and {} point(s)) in {}", ls_checked, 212 "Done (checked {} line string(s) and {} point(s)) in {}", ls_checked,
211 p_checked, 213 p_checked,
212 chrono::duration_cast<chrono::milliseconds>(after_query - before_query)); 214 chrono::duration_cast<chrono::milliseconds>(after_query - before_query));
@@ -216,12 +218,12 @@ auto handler::process_gpx(gpx::file&& gpx_file)
216 for (auto const& rc : relevant_road_closures) 218 for (auto const& rc : relevant_road_closures)
217 relevant_situations.emplace(rc->parent); 219 relevant_situations.emplace(rc->parent);
218 220
219 l_.debug( 221 l.debug(
220 "Identified {} relevant road closure(s), part of {} unique " 222 "Identified {} relevant road closure(s), part of {} unique "
221 "situation(s)", 223 "situation(s)",
222 relevant_road_closures.size(), relevant_situations.size()); 224 relevant_road_closures.size(), relevant_situations.size());
223 for (auto const& sit : relevant_situations) 225 for (auto const& sit : relevant_situations)
224 l_.debug("Relevant situation: {}", sit->id); 226 l.debug("Relevant situation: {}", sit->id);
225 227
226 return process_gpx_result{ 228 return process_gpx_result{
227 .tracks = gpx_file.tracks 229 .tracks = gpx_file.tracks
diff --git a/server/src/api.cppm b/server/src/api.cppm
index 7166ad0..b2744cb 100644
--- a/server/src/api.cppm
+++ b/server/src/api.cppm
@@ -93,7 +93,8 @@ class handler
93public: 93public:
94 explicit handler(log::logger const& l, datex2::situation_publication pub); 94 explicit handler(log::logger const& l, datex2::situation_publication pub);
95 95
96 auto process_gpx(gpx::file&& gpx_file) -> std::optional<process_gpx_result>; 96 auto process_gpx(trace::id trace_id, gpx::file&& gpx_file)
97 -> std::optional<process_gpx_result>;
97 auto sysinfo() -> sysinfo; 98 auto sysinfo() -> sysinfo;
98}; 99};
99 100
diff --git a/server/src/http_server.cpp b/server/src/http_server.cpp
index da8e6f0..c3a9ed7 100644
--- a/server/src/http_server.cpp
+++ b/server/src/http_server.cpp
@@ -13,6 +13,9 @@ module;
13module routemon:http.server$impl; 13module routemon:http.server$impl;
14 14
15import :http.server; 15import :http.server;
16import :trace;
17
18namespace chrono = std::chrono;
16 19
17namespace routemon::http { 20namespace routemon::http {
18 21
@@ -86,10 +89,10 @@ auto global_options_handler(base_ctx const& ctx, readable_request r)
86 co_return std::move(rsp); 89 co_return std::move(rsp);
87} 90}
88 91
89auto router::handle_request(readable_request r) const 92auto router::handle_request(trace::id trace_id, readable_request r) const
90 -> net::awaitable<presponse> 93 -> net::awaitable<presponse>
91{ 94{
92 return impl_->handle_request(r); 95 return impl_->handle_request(trace_id, r);
93} 96}
94 97
95server::server(log::logger const& l, router&& r) 98server::server(log::logger const& l, router&& r)
@@ -112,16 +115,35 @@ auto server::do_session(beast::tcp_stream strm) -> net::awaitable<void>
112 else if (ec) 115 else if (ec)
113 throw boost::system::system_error{ec}; 116 throw boost::system::system_error{ec};
114 117
118 auto trace_id = trace::id{};
119 auto l = l_.sub("do_session").with("trace_id", trace_id.as_string());
120 l.debug("Read header, invoking request handler");
121 auto const before_hdl = chrono::steady_clock::now();
122
115 auto http_version = p0.get().version(); 123 auto http_version = p0.get().version();
116 auto&& rsp = co_await r_.handle_request( 124 auto&& rsp = co_await r_.handle_request(
117 readable_request{ 125 trace_id, readable_request{
118 .p = util::not_null{&p0}, 126 .p = util::not_null{&p0},
119 .strm = util::not_null{&strm}, 127 .strm = util::not_null{&strm},
120 .buf = util::not_null{&buf}, 128 .buf = util::not_null{&buf},
129 });
130
131 l.debug(
132 "Request handler returned after {}, writing response",
133 chrono::duration<double, std::milli>{
134 chrono::steady_clock::now() - before_hdl
121 }); 135 });
136 auto before_write_rsp = chrono::steady_clock::now();
137
122 rsp.header().version(http_version); 138 rsp.header().version(http_version);
123 bool keep_alive = rsp.keep_alive(); 139 bool keep_alive = rsp.keep_alive();
124 co_await beast::async_write(strm, std::move(rsp)); 140 co_await beast::async_write(strm, std::move(rsp));
141
142 l.debug(
143 "Wrote response in {}", chrono::duration<double, std::milli>{
144 chrono::steady_clock::now() - before_write_rsp
145 });
146
125 if (!keep_alive) 147 if (!keep_alive)
126 { 148 {
127 break; 149 break;
diff --git a/server/src/http_server.cppm b/server/src/http_server.cppm
index b16f3a8..12c83db 100644
--- a/server/src/http_server.cppm
+++ b/server/src/http_server.cppm
@@ -164,6 +164,19 @@ auto id_middleware(
164 co_return co_await next(std::move(ctx)); 164 co_return co_await next(std::move(ctx));
165} 165}
166 166
167struct base_ctx
168{
169 std::locale locale;
170 trace::id trace_id;
171};
172
173template <class Ctx>
174using basic_route_handler_fn_t =
175 std::function<auto(
176 Ctx, readable_request,
177 std::vector<std::string> const& matches)
178 ->net::awaitable<presponse>>;
179
167template <class Ctx> 180template <class Ctx>
168auto cors_middleware(std::vector<std::string> const& allow_origins) 181auto cors_middleware(std::vector<std::string> const& allow_origins)
169 -> middleware_t<Ctx, Ctx> 182 -> middleware_t<Ctx, Ctx>
@@ -186,39 +199,21 @@ auto cors_middleware(std::vector<std::string> const& allow_origins)
186 }; 199 };
187} 200}
188 201
189template <class InnerCtx> 202template <class Ctx>
190struct trace_id_ctx : InnerCtx
191{
192 trace::id trace_id = {};
193};
194
195template <class OuterCtx>
196auto trace_id_middleware( 203auto trace_id_middleware(
197 OuterCtx ctx0, bhttp::request_header<bhttp::fields>& req_hdr, 204 Ctx ctx, bhttp::request_header<bhttp::fields>& req_hdr,
198 next_handler_t<trace_id_ctx<OuterCtx>> next) -> net::awaitable<presponse> 205 next_handler_t<Ctx> next) -> net::awaitable<presponse>
199{ 206{
200 std::ignore = req_hdr; 207 std::ignore = req_hdr;
201 auto ctx = trace_id_ctx{std::move(ctx0)};
202 auto prersp = co_await next(std::move(ctx)); 208 auto prersp = co_await next(std::move(ctx));
203 prersp.header().set( 209 prersp.header().set(
204 "X-Routemon-Trace-Id", std::string_view{ctx.trace_id.as_string()}); 210 "X-Routemon-Trace-Id",
211 std::string_view{static_cast<base_ctx const&>(ctx).trace_id.as_string()});
205 prersp.header().insert( 212 prersp.header().insert(
206 bhttp::field::access_control_expose_headers, "X-Routemon-Trace-Id"); 213 bhttp::field::access_control_expose_headers, "X-Routemon-Trace-Id");
207 co_return std::move(prersp); 214 co_return std::move(prersp);
208} 215}
209 216
210struct base_ctx
211{
212 std::locale locale;
213};
214
215template <class Ctx>
216using basic_route_handler_fn_t =
217 std::function<auto(
218 Ctx, readable_request,
219 std::vector<std::string> const& matches)
220 ->net::awaitable<presponse>>;
221
222struct keep_alive 217struct keep_alive
223{ 218{
224 bool value; 219 bool value;
@@ -555,7 +550,7 @@ class router
555 struct impl_base 550 struct impl_base
556 { 551 {
557 virtual ~impl_base() = default; 552 virtual ~impl_base() = default;
558 virtual auto handle_request(readable_request r) const 553 virtual auto handle_request(trace::id trace_id, readable_request r) const
559 -> net::awaitable<presponse> = 0; 554 -> net::awaitable<presponse> = 0;
560 }; 555 };
561 556
@@ -564,16 +559,17 @@ class router
564 template <std::derived_from<base_ctx> PreRouteCtx> 559 template <std::derived_from<base_ctx> PreRouteCtx>
565 class impl : public impl_base 560 class impl : public impl_base
566 { 561 {
562 log::logger l_;
567 locale::selector lsel_; 563 locale::selector lsel_;
568 middleware_t<base_ctx, PreRouteCtx> global_middleware_; 564 middleware_t<base_ctx, PreRouteCtx> global_middleware_;
569 route_tree<routed_ctx<PreRouteCtx>> routes_; 565 route_tree<routed_ctx<PreRouteCtx>> routes_;
570 566
571 public: 567 public:
572 explicit impl( 568 explicit impl(
573 locale::selector&& lsel, 569 log::logger const& l, locale::selector&& lsel,
574 middleware_t<base_ctx, PreRouteCtx> global_middleware, 570 middleware_t<base_ctx, PreRouteCtx> global_middleware,
575 route_tree<routed_ctx<PreRouteCtx>> routes) 571 route_tree<routed_ctx<PreRouteCtx>> routes)
576 : lsel_{std::move(lsel)}, 572 : l_{l.sub("router")}, lsel_{std::move(lsel)},
577 global_middleware_{std::move(global_middleware)}, 573 global_middleware_{std::move(global_middleware)},
578 routes_{std::move(routes)} 574 routes_{std::move(routes)}
579 { 575 {
@@ -674,6 +670,13 @@ class router
674 co_return problem_rsp(ctx, problem, keep_alive{false}); 670 co_return problem_rsp(ctx, problem, keep_alive{false});
675 } 671 }
676 672
673 l_.with(
674 "trace_id",
675 static_cast<base_ctx const&>(ctx).trace_id.as_string())
676 .debug(
677 "Request targets {} {}", req_base.method_string(),
678 req_url.path());
679
677 auto mres = match(req_url.segments()); 680 auto mres = match(req_url.segments());
678 if (!mres) 681 if (!mres)
679 { 682 {
@@ -732,13 +735,13 @@ class router
732 } 735 }
733 } 736 }
734 737
735 auto handle_request(readable_request r) const 738 auto handle_request(trace::id trace_id, readable_request r) const
736 -> net::awaitable<presponse> override 739 -> net::awaitable<presponse> override
737 { 740 {
738 auto header = r.p->get().base(); 741 auto header = r.p->get().base();
739 auto locale = lsel_.select(header[bhttp::field::accept_language]); 742 auto locale = lsel_.select(header[bhttp::field::accept_language]);
740 co_return co_await global_middleware_( 743 co_return co_await global_middleware_(
741 base_ctx{.locale = locale}, header, 744 base_ctx{.locale = locale, .trace_id = trace_id}, header,
742 [&](PreRouteCtx ctx) -> net::awaitable<presponse> 745 [&](PreRouteCtx ctx) -> net::awaitable<presponse>
743 { co_return co_await route_request(std::move(ctx), std::move(r)); }); 746 { co_return co_await route_request(std::move(ctx), std::move(r)); });
744 } 747 }
@@ -747,15 +750,16 @@ class router
747public: 750public:
748 template <std::derived_from<base_ctx> PreRouteCtx> 751 template <std::derived_from<base_ctx> PreRouteCtx>
749 explicit router( 752 explicit router(
750 locale::selector&& lsel, 753 log::logger const& l, locale::selector&& lsel,
751 middleware_t<base_ctx, PreRouteCtx> global_middleware, 754 middleware_t<base_ctx, PreRouteCtx> global_middleware,
752 route_tree<routed_ctx<PreRouteCtx>> routes) 755 route_tree<routed_ctx<PreRouteCtx>> routes)
753 : impl_{std::make_unique<impl<PreRouteCtx>>( 756 : impl_{std::make_unique<impl<PreRouteCtx>>(
754 std::move(lsel), std::move(global_middleware), std::move(routes))} 757 l, std::move(lsel), std::move(global_middleware), std::move(routes))}
755 { 758 {
756 } 759 }
757 760
758 auto handle_request(readable_request r) const -> net::awaitable<presponse>; 761 auto handle_request(trace::id trace_id, readable_request r) const
762 -> net::awaitable<presponse>;
759}; 763};
760 764
761class server 765class server
diff --git a/server/src/srv.cpp b/server/src/srv.cpp
index b70f05c..f79da33 100644
--- a/server/src/srv.cpp
+++ b/server/src/srv.cpp
@@ -19,6 +19,7 @@ import :gpx;
19import :srv; 19import :srv;
20 20
21namespace beast = boost::beast; 21namespace beast = boost::beast;
22namespace chrono = std::chrono;
22namespace json = boost::json; 23namespace json = boost::json;
23namespace net = boost::asio; 24namespace net = boost::asio;
24using tcp = boost::asio::ip::tcp; 25using tcp = boost::asio::ip::tcp;
@@ -157,12 +158,22 @@ static_assert(bhttp::concepts::body_reader<readable_gpx_body>);
157auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r) 158auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r)
158 -> net::awaitable<http::presponse> 159 -> net::awaitable<http::presponse>
159{ 160{
161 auto l =
162 l_.sub("handle_process_gpx").with("trace_id", ctx.trace_id.as_string());
163
160 auto gpx_file = gpx::file{}; 164 auto gpx_file = gpx::file{};
161 try 165 try
162 { 166 {
167 l.debug("Reading GPX request body");
168 auto const before_read_gpx = chrono::steady_clock::now();
163 auto req = 169 auto req =
164 co_await http::read_request<readable_gpx_body>(ctx, std::move(r)); 170 co_await http::read_request<readable_gpx_body>(ctx, std::move(r));
165 gpx_file = std::move(req->body().unwrap()); 171 gpx_file = std::move(req->body().unwrap());
172 l.debug(
173 "Read GPX request body in {}",
174 chrono::duration<double, std::milli>{
175 chrono::steady_clock::now() - before_read_gpx
176 });
166 } 177 }
167 catch (std::exception& ex) 178 catch (std::exception& ex)
168 { 179 {
@@ -178,7 +189,7 @@ auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r)
178 189
179 // TODO: catch handler exceptions and return 500 when raised? 190 // TODO: catch handler exceptions and return 500 when raised?
180 // (keep-alive depends on whether whole request was read) 191 // (keep-alive depends on whether whole request was read)
181 auto mres = inner_.process_gpx(std::move(gpx_file)); 192 auto mres = inner_.process_gpx(ctx.trace_id, std::move(gpx_file));
182 if (!mres) 193 if (!mres)
183 { 194 {
184 auto tpl = problem::tpl{ 195 auto tpl = problem::tpl{
@@ -212,7 +223,10 @@ auto handler::handle_sysinfo(l0_ctx ctx, http::readable_request r)
212 co_return rsp; 223 co_return rsp;
213} 224}
214 225
215handler::handler(api::handler&& inner) : inner_{std::move(inner)} {} 226handler::handler(log::logger const& l, api::handler&& inner)
227 : l_{l.sub("handler")}, inner_{std::move(inner)}
228{
229}
216 230
217auto handler::make_routes() -> http::route_tree<http::routed_ctx<outer_ctx>> 231auto handler::make_routes() -> http::route_tree<http::routed_ctx<outer_ctx>>
218{ 232{
@@ -235,22 +249,21 @@ auto handler::make_routes() -> http::route_tree<http::routed_ctx<outer_ctx>>
235auto server::make_global_middleware(config::http_server const& cfg) 249auto server::make_global_middleware(config::http_server const& cfg)
236 -> http::middleware_t<http::base_ctx, handler::outer_ctx> 250 -> http::middleware_t<http::base_ctx, handler::outer_ctx>
237{ 251{
238 return http::middleware_compose< 252 return http::
239 http::base_ctx, http::trace_id_ctx<http::base_ctx>, 253 middleware_compose<http::base_ctx, http::base_ctx, http::base_ctx>(
240 http::trace_id_ctx<http::base_ctx> 254 http::trace_id_middleware<http::base_ctx>,
241 >(http::trace_id_middleware<http::base_ctx>, 255 http::cors_middleware<http::base_ctx>(cfg.allow_origins));
242 http::cors_middleware<http::trace_id_ctx<http::base_ctx>>(
243 cfg.allow_origins));
244} 256}
245 257
246server::server( 258server::server(
247 log::logger const& l, config::http_server const& cfg, 259 log::logger const& l, config::http_server const& cfg,
248 locale::selector&& lsel, api::handler&& inner) 260 locale::selector&& lsel, api::handler&& inner)
249 : handler_{std::move(inner)}, 261 : handler_{l, std::move(inner)},
250 srv_{ 262 srv_{
251 l, http::router{ 263 l,
252 std::move(lsel), make_global_middleware(cfg), handler_.make_routes() 264 http::router{
253 } 265 l, std::move(lsel), make_global_middleware(cfg), handler_.make_routes()
266 }
254 } 267 }
255{ 268{
256} 269}
diff --git a/server/src/srv.cppm b/server/src/srv.cppm
index 063617e..b06dc3b 100644
--- a/server/src/srv.cppm
+++ b/server/src/srv.cppm
@@ -11,10 +11,11 @@ namespace routemon::srv {
11 11
12class handler 12class handler
13{ 13{
14 log::logger l_;
14 api::handler inner_; 15 api::handler inner_;
15 16
16public: 17public:
17 using outer_ctx = http::trace_id_ctx<http::base_ctx>; 18 using outer_ctx = http::base_ctx;
18 using l0_ctx = http::routed_ctx<outer_ctx>; 19 using l0_ctx = http::routed_ctx<outer_ctx>;
19 20
20private: 21private:
@@ -25,7 +26,7 @@ private:
25 -> net::awaitable<http::presponse>; 26 -> net::awaitable<http::presponse>;
26 27
27public: 28public:
28 handler(api::handler&& inner); 29 handler(log::logger const& l, api::handler&& inner);
29 30
30 auto make_routes() -> http::route_tree<http::routed_ctx<outer_ctx>>; 31 auto make_routes() -> http::route_tree<http::routed_ctx<outer_ctx>>;
31}; 32};