From 88c65689de8e87286add27637c1d6b55dce6b816 Mon Sep 17 00:00:00 2001 From: Aleksey Kashapov Date: Thu, 4 Dec 2025 15:10:14 +0300 Subject: [PATCH 1/3] Conforms rpc context with woody helper --- apps/mg_core/src/mg_core_machine.erl | 8 ++-- apps/mg_core/src/mg_core_otel.erl | 48 ------------------- .../test/mg_core_machine_full_test_SUITE.erl | 6 +-- apps/mg_woody/rebar.config | 2 +- apps/mg_woody/src/mg_woody_automaton.erl | 5 +- rebar.lock | 18 ++++--- 6 files changed, 19 insertions(+), 68 deletions(-) diff --git a/apps/mg_core/src/mg_core_machine.erl b/apps/mg_core/src/mg_core_machine.erl index 5178913..ccde518 100644 --- a/apps/mg_core/src/mg_core_machine.erl +++ b/apps/mg_core/src/mg_core_machine.erl @@ -1566,11 +1566,9 @@ attach_otel_ctx(ReqCtx) -> mg_core_otel:maybe_attach_otel_ctx(request_context_to_otel_context(ReqCtx)). -spec request_context_to_otel_context(mg_core_events_machine:request_context()) -> otel_ctx:t(). -request_context_to_otel_context(#{<<"otel">> := OpaqueOtelCtx}) -> - OtelCtx0 = otel_ctx:get_current(), - mg_core_otel:restore_otel_stub(OtelCtx0, OpaqueOtelCtx); -request_context_to_otel_context(_Other) -> - otel_ctx:get_current(). +request_context_to_otel_context(Ctx) -> + {_WoodyContext, OtelContext} = woody_rpc_helper:decode_rpc_context(Ctx), + OtelContext. %% %% retrying diff --git a/apps/mg_core/src/mg_core_otel.erl b/apps/mg_core/src/mg_core_otel.erl index ec27196..68db449 100644 --- a/apps/mg_core/src/mg_core_otel.erl +++ b/apps/mg_core/src/mg_core_otel.erl @@ -2,8 +2,6 @@ -include_lib("opentelemetry_api/include/opentelemetry.hrl"). --export([pack_otel_stub/1]). --export([restore_otel_stub/2]). -export([maybe_attach_otel_ctx/1]). -export([span_start/3]). @@ -27,38 +25,6 @@ %% -%% @doc Packs OTEL context for storage. --spec pack_otel_stub(otel_ctx:t()) -> packed_otel_stub(). -pack_otel_stub(Ctx) -> - case otel_tracer:current_span_ctx(Ctx) of - undefined -> - []; - #span_ctx{trace_id = TraceID, span_id = SpanID, trace_flags = TraceFlags} -> - [trace_id_to_binary(TraceID), span_id_to_binary(SpanID), TraceFlags] - end. - -%% @doc Restores OTEL context with current span. Restored span context -%% status is nor actual nor have according data in OTEL storage -%% backend. Its only purpose is to preserve ability to start new child -%% spans in compliance with OTEL tracer API. -%% -%% Restored otel span can be unfinished if machine is interrupted -%% with node stop, thus span data is lost anyway. -%% -%% We can't get around this issue without implementing our own -%% tracer with distributed storage with write order guarantee. -%% -%% However we can start new span for 'resumption' signal. And set -%% original machine start call as its parent. Same goes for 'timeouts' -%% and 'retries' signals. --spec restore_otel_stub(otel_ctx:t(), packed_otel_stub()) -> otel_ctx:t(). -restore_otel_stub(Ctx, [TraceID, SpanID, TraceFlags]) -> - SpanCtx = otel_tracer:from_remote_span(binary_to_id(TraceID), binary_to_id(SpanID), TraceFlags), - %% NOTE Thus restored span context is considered being remote and not recording. - otel_tracer:set_current_span(Ctx, SpanCtx); -restore_otel_stub(Ctx, _Other) -> - Ctx. - -spec maybe_attach_otel_ctx(otel_ctx:t()) -> ok. maybe_attach_otel_ctx(NewCtx) when map_size(NewCtx) =:= 0 -> %% Don't attach empty context @@ -167,20 +133,6 @@ span_id(#span_ctx{span_id = SpanID}) -> span_id(_) -> undefined. --spec trace_id_to_binary(opentelemetry:trace_id()) -> binary(). -trace_id_to_binary(TraceID) -> - {ok, EncodedTraceID} = otel_utils:format_binary_string("~32.16.0b", [TraceID]), - EncodedTraceID. - --spec span_id_to_binary(opentelemetry:span_id()) -> binary(). -span_id_to_binary(SpanID) -> - {ok, EncodedSpanID} = otel_utils:format_binary_string("~16.16.0b", [SpanID]), - EncodedSpanID. - --spec binary_to_id(binary()) -> non_neg_integer(). -binary_to_id(Opaque) when is_binary(Opaque) -> - binary_to_integer(Opaque, 16). - -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/apps/mg_core/test/mg_core_machine_full_test_SUITE.erl b/apps/mg_core/test/mg_core_machine_full_test_SUITE.erl index 49582c9..c4a7c77 100644 --- a/apps/mg_core/test/mg_core_machine_full_test_SUITE.erl +++ b/apps/mg_core/test/mg_core_machine_full_test_SUITE.erl @@ -202,10 +202,10 @@ do_action(Options, ID, Seq, Action) -> -spec req_ctx(id(), seq()) -> mg_core:request_context(). req_ctx(ID, Seq) -> - #{ + Ctx = woody_rpc_helper:encode_rpc_context(woody_context:new(), otel_ctx:get_current()), + Ctx#{ <<"id">> => ID, - <<"seq">> => Seq, - <<"otel">> => mg_core_otel:pack_otel_stub(otel_ctx:get_current()) + <<"seq">> => Seq }. -spec id(id()) -> mg_core:id(). diff --git a/apps/mg_woody/rebar.config b/apps/mg_woody/rebar.config index e5673ee..8a0ab5b 100644 --- a/apps/mg_woody/rebar.config +++ b/apps/mg_woody/rebar.config @@ -1,6 +1,6 @@ {deps, [ {mg_proto, {git, "https://github.com/valitydev/machinegun-proto", {branch, master}}}, {genlib, {git, "https://github.com/valitydev/genlib", {tag, "v1.1.0"}}}, - {woody, {git, "https://github.com/valitydev/woody_erlang", {tag, "v1.1.0"}}}, + {woody, {git, "https://github.com/valitydev/woody_erlang", {branch, "ft/woody-rpc-helper"}}}, {opentelemetry_api, "1.4.0"} ]}. diff --git a/apps/mg_woody/src/mg_woody_automaton.erl b/apps/mg_woody/src/mg_woody_automaton.erl index 27a5030..c0a55eb 100644 --- a/apps/mg_woody/src/mg_woody_automaton.erl +++ b/apps/mg_woody/src/mg_woody_automaton.erl @@ -321,7 +321,4 @@ simplify_machine_status(_) -> -spec to_request_context(otel_ctx:t(), woody_context:ctx()) -> mg_core:request_context(). to_request_context(OtelContext, WoodyContext) -> - #{ - <<"otel">> => mg_core_otel:pack_otel_stub(OtelContext), - <<"woody">> => mg_woody_utils:woody_context_to_opaque(WoodyContext) - }. + woody_rpc_helper:encode_rpc_context(WoodyContext, OtelContext). diff --git a/rebar.lock b/rebar.lock index dfa7e3f..65e8851 100644 --- a/rebar.lock +++ b/rebar.lock @@ -36,6 +36,10 @@ {<<"gproc">>,{pkg,<<"gproc">>,<<"0.9.0">>},0}, {<<"grpcbox">>,{pkg,<<"grpcbox">>,<<"0.17.1">>},1}, {<<"hackney">>,{pkg,<<"hackney">>,<<"1.18.0">>},1}, + {<<"hamcrest">>, + {git,"https://github.com/basho/hamcrest-erlang.git", + {ref,"ad3dbab419762fc2d5821abb88b989da006b85c6"}}, + 2}, {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.3.0">>},3}, {<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},2}, {<<"jsone">>,{pkg,<<"jsone">>,<<"1.8.0">>},3}, @@ -46,7 +50,7 @@ {git,"https://github.com/valitydev/machinegun-proto", {ref,"3decc8f8b13c9cd1701deab47781aacddd7dbc92"}}, 0}, - {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.3.0">>},2}, + {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.4.0">>},2}, {<<"msgpack">>, {git,"https://github.com/msgpack/msgpack-erlang", {ref,"6b544de60723839244866b109d6a79c7caca6bc9"}}, @@ -93,10 +97,10 @@ {<<"tls_certificate_check">>, {pkg,<<"tls_certificate_check">>,<<"1.26.0">>}, 1}, - {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2}, + {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.1">>},2}, {<<"woody">>, {git,"https://github.com/valitydev/woody_erlang", - {ref,"cc983a9423325ba1d6a509775eb6ff7ace721539"}}, + {ref,"5f733a98c186d32558a202e7948f0200ade6e4e0"}}, 0}, {<<"yamerl">>, {git,"https://github.com/valitydev/yamerl", @@ -123,7 +127,7 @@ {<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>}, {<<"kafka_protocol">>, <<"FC696880C73483C8B032C4BB60F2873046035C7824E1EDCB924CFCE643CF23DD">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, - {<<"mimerl">>, <<"D0CD9FC04B9061F82490F6581E0128379830E78535E017F7780F37FEA7545726">>}, + {<<"mimerl">>, <<"3882A5CA67FBBE7117BA8947F27643557ADEC38FA2307490C4C4207624CB213B">>}, {<<"opentelemetry">>, <<"7DDA6551EDFC3050EA4B0B40C0D2570423D6372B97E9C60793263EF62C53C3C2">>}, {<<"opentelemetry_api">>, <<"63CA1742F92F00059298F478048DFB826F4B20D49534493D6919A0DB39B6DB04">>}, {<<"opentelemetry_exporter">>, <<"5D546123230771EF4174E37BEDFD77E3374913304CD6EA3CA82A2ADD49CD5D56">>}, @@ -138,7 +142,7 @@ {<<"ssl_verify_fun">>, <<"354C321CF377240C7B8716899E182CE4890C5938111A1296ADD3EC74CF1715DF">>}, {<<"supervisor3">>, <<"D81CDEC31D102FDE407423E1D05B569572850DEEBED86B951D5233C387CBA80B">>}, {<<"tls_certificate_check">>, <<"C0E8FFAB875748F2B122D4D4E465AEAA7249EA539F1004B7922CB3C61FFE261D">>}, - {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]}, + {<<"unicode_util_compat">>, <<"A48703A25C170EEDADCA83B11E88985AF08D35F37C6F664D6DCFB106A97782FC">>}]}, {pkg_hash_ext,[ {<<"accept">>, <<"A5167FA1AE90315C3F1DD189446312F8A55D00EFA357E9C569BDA47736B874C3">>}, {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>}, @@ -159,7 +163,7 @@ {<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>}, {<<"kafka_protocol">>, <<"687BFD9989998EC8FBBC3ED50D1239A6C07A7DC15B52914AD477413B89ECB621">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, - {<<"mimerl">>, <<"A1E15A50D1887217DE95F0B9B0793E32853F7C258A5CD227650889B38839FE9D">>}, + {<<"mimerl">>, <<"13AF15F9F68C65884ECCA3A3891D50A7B57D82152792F3E19D88650AA126B144">>}, {<<"opentelemetry">>, <<"CDF4F51D17B592FC592B9A75F86A6F808C23044BA7CF7B9534DEBBCC5C23B0EE">>}, {<<"opentelemetry_api">>, <<"3DFBBFAA2C2ED3121C5C483162836C4F9027DEF469C41578AF5EF32589FCFC58">>}, {<<"opentelemetry_exporter">>, <<"A1F9F271F8D3B02B81462A6BFEF7075FD8457FDB06ADFF5D2537DF5E2264D9AF">>}, @@ -174,5 +178,5 @@ {<<"ssl_verify_fun">>, <<"FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8">>}, {<<"supervisor3">>, <<"E6C2DEDBCABCBA24995A218ACA12DB5E208B80D3252692B22EF0F1A266104B50">>}, {<<"tls_certificate_check">>, <<"1BAD73D88637F788B554A8E939C25DB2BDAAC88B10FFFD5BBA9D1B65F43A6B54">>}, - {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]} + {<<"unicode_util_compat">>, <<"B3A917854CE3AE233619744AD1E0102E05673136776FB2FA76234F3E03B23642">>}]} ]. From 1c68f86d5e2fd6acbd7a28f91bff0db3f607154b Mon Sep 17 00:00:00 2001 From: Aleksey Kashapov Date: Thu, 4 Dec 2025 18:31:41 +0300 Subject: [PATCH 2/3] Uses `otel_ctx` attachement from woody rpc helper --- apps/mg_core/src/mg_core_machine.erl | 2 +- apps/mg_core/src/mg_core_otel.erl | 59 ---------------------------- rebar.lock | 2 +- 3 files changed, 2 insertions(+), 61 deletions(-) diff --git a/apps/mg_core/src/mg_core_machine.erl b/apps/mg_core/src/mg_core_machine.erl index ccde518..dbf8678 100644 --- a/apps/mg_core/src/mg_core_machine.erl +++ b/apps/mg_core/src/mg_core_machine.erl @@ -1563,7 +1563,7 @@ try_suicide(#{}, _) -> -spec attach_otel_ctx(mg_core_events_machine:request_context()) -> ok. attach_otel_ctx(ReqCtx) -> - mg_core_otel:maybe_attach_otel_ctx(request_context_to_otel_context(ReqCtx)). + woody_rpc_helper:attach_otel_context(request_context_to_otel_context(ReqCtx)). -spec request_context_to_otel_context(mg_core_events_machine:request_context()) -> otel_ctx:t(). request_context_to_otel_context(Ctx) -> diff --git a/apps/mg_core/src/mg_core_otel.erl b/apps/mg_core/src/mg_core_otel.erl index 68db449..cafbbe9 100644 --- a/apps/mg_core/src/mg_core_otel.erl +++ b/apps/mg_core/src/mg_core_otel.erl @@ -2,8 +2,6 @@ -include_lib("opentelemetry_api/include/opentelemetry.hrl"). --export([maybe_attach_otel_ctx/1]). - -export([span_start/3]). -export([span_end/1]). -export([record_current_span_ctx/3]). @@ -25,27 +23,6 @@ %% --spec maybe_attach_otel_ctx(otel_ctx:t()) -> ok. -maybe_attach_otel_ctx(NewCtx) when map_size(NewCtx) =:= 0 -> - %% Don't attach empty context - ok; -maybe_attach_otel_ctx(NewCtx) -> - _ = otel_ctx:attach(choose_viable_otel_ctx(NewCtx, otel_ctx:get_current())), - ok. - -%% lowest bit is if it is sampled --define(IS_NOT_SAMPLED(SpanCtx), SpanCtx#span_ctx.trace_flags band 2#1 =/= 1). - --spec choose_viable_otel_ctx(T, T) -> T when T :: otel_ctx:t(). -choose_viable_otel_ctx(NewCtx, CurrentCtx) -> - case {otel_tracer:current_span_ctx(NewCtx), otel_tracer:current_span_ctx(CurrentCtx)} of - %% Don't attach if new context is without sampled span and old - %% context has span defined - {SpanCtx = #span_ctx{}, #span_ctx{}} when ?IS_NOT_SAMPLED(SpanCtx) -> CurrentCtx; - {undefined, #span_ctx{}} -> CurrentCtx; - {_, _} -> NewCtx - end. - -spec span_start(term(), opentelemetry:span_name(), otel_span:start_opts()) -> ok. span_start(Key, SpanName, Opts) -> Tracer = opentelemetry:get_application_tracer(?MODULE), @@ -132,39 +109,3 @@ span_id(#span_ctx{span_id = SpanID}) -> SpanID; span_id(_) -> undefined. - --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). - --type testgen() :: {_ID, fun(() -> _)}. --spec test() -> _. - --define(IS_SAMPLED, 1). --define(NOT_SAMPLED, 0). --define(OTEL_CTX(IsSampled), - otel_tracer:set_current_span( - otel_ctx:new(), - (otel_tracer_noop:noop_span_ctx())#span_ctx{ - trace_id = otel_id_generator:generate_trace_id(), - span_id = otel_id_generator:generate_span_id(), - is_valid = true, - is_remote = true, - is_recording = false, - trace_flags = IsSampled - } - ) -). - --spec choose_viable_otel_ctx_test_() -> [testgen()]. -choose_viable_otel_ctx_test_() -> - A = ?OTEL_CTX(?IS_SAMPLED), - B = ?OTEL_CTX(?NOT_SAMPLED), - [ - ?_assertEqual(A, choose_viable_otel_ctx(A, B)), - ?_assertEqual(A, choose_viable_otel_ctx(B, A)), - ?_assertEqual(A, choose_viable_otel_ctx(A, otel_ctx:new())), - ?_assertEqual(B, choose_viable_otel_ctx(otel_ctx:new(), B)), - ?_assertEqual(otel_ctx:new(), choose_viable_otel_ctx(otel_ctx:new(), otel_ctx:new())) - ]. - --endif. diff --git a/rebar.lock b/rebar.lock index 65e8851..a812495 100644 --- a/rebar.lock +++ b/rebar.lock @@ -100,7 +100,7 @@ {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.1">>},2}, {<<"woody">>, {git,"https://github.com/valitydev/woody_erlang", - {ref,"5f733a98c186d32558a202e7948f0200ade6e4e0"}}, + {ref,"43175ef5930a28c3e44ea7ad57d18665d0b8a01f"}}, 0}, {<<"yamerl">>, {git,"https://github.com/valitydev/yamerl", From b8eacd5bf6cbbf9c230bd9fe2be3eabe41692520 Mon Sep 17 00:00:00 2001 From: Aleksey Kashapov Date: Mon, 8 Dec 2025 11:17:13 +0300 Subject: [PATCH 3/3] Bumps woody@v1.1.1 --- apps/mg_woody/rebar.config | 2 +- rebar.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/mg_woody/rebar.config b/apps/mg_woody/rebar.config index 8a0ab5b..bbe85ec 100644 --- a/apps/mg_woody/rebar.config +++ b/apps/mg_woody/rebar.config @@ -1,6 +1,6 @@ {deps, [ {mg_proto, {git, "https://github.com/valitydev/machinegun-proto", {branch, master}}}, {genlib, {git, "https://github.com/valitydev/genlib", {tag, "v1.1.0"}}}, - {woody, {git, "https://github.com/valitydev/woody_erlang", {branch, "ft/woody-rpc-helper"}}}, + {woody, {git, "https://github.com/valitydev/woody_erlang", {tag, "v1.1.1"}}}, {opentelemetry_api, "1.4.0"} ]}. diff --git a/rebar.lock b/rebar.lock index a812495..80e2518 100644 --- a/rebar.lock +++ b/rebar.lock @@ -100,7 +100,7 @@ {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.1">>},2}, {<<"woody">>, {git,"https://github.com/valitydev/woody_erlang", - {ref,"43175ef5930a28c3e44ea7ad57d18665d0b8a01f"}}, + {ref,"3de9a236b66807d5397b28aed42e2b1c85f36739"}}, 0}, {<<"yamerl">>, {git,"https://github.com/valitydev/yamerl",