opentelemetry-erlang-contrib/instrumentation/opentelemetry_grpcbox/test/routeguide_route_guide.erl

130 lines
4.3 KiB
Erlang
Raw Permalink Normal View History

-module(routeguide_route_guide).
-include_lib("grpcbox/include/grpcbox.hrl").
-export([get_feature/2,
list_features/2,
record_route/2,
route_chat/2,
generate_error/2,
streaming_generate_error/2]).
-type route_summary() ::
#{point_count => integer(),
feature_count => integer(),
distance => integer(),
elapsed_time => integer()}.
-type point() ::
#{latitude => integer(),
longitude => integer()}.
-type rectangle() ::
#{lo => point(),
hi => point()}.
-type route_note() ::
#{location => point(),
message => string()}.
-type feature() ::
#{name => string(),
location => point()}.
-spec get_feature(Ctx :: ctx:ctx(), Message :: point()) -> {ok, feature(), ctx:ctx()}.
get_feature(Ctx, Message) ->
Feature = #{name => find_point(Message, data()),
location => Message},
{ok, Feature, Ctx}.
-spec list_features(Message::rectangle(), GrpcStream :: grpcbox_stream:t()) -> ok.
list_features(_Message, GrpcStream) ->
grpcbox_stream:add_headers([{<<"info">>, <<"this is a test-implementation">>}], GrpcStream),
grpcbox_stream:send(#{name => <<"Tour Eiffel">>,
location => #{latitude => 3,
longitude => 5}}, GrpcStream),
grpcbox_stream:send(#{name => <<"Louvre">>,
location => #{latitude => 4,
longitude => 5}}, GrpcStream),
grpcbox_stream:add_trailers([{<<"nr_of_points_sent">>, <<"2">>}], GrpcStream),
ok.
-spec record_route(reference(), GrpcStream :: grpcbox_stream:t()) -> {ok, route_summary(), grpcbox_stream:t()}.
record_route(Ref, GrpcStream) ->
record_route(Ref, #{t_start => erlang:system_time(1),
acc => []}, GrpcStream).
record_route(Ref, Data=#{t_start := T0, acc := Points}, GrpcStream) ->
receive
{Ref, eos} ->
%% receiving 'eos' tells us that we need to return a result.
{ok, #{elapsed_time => erlang:system_time(1) - T0,
point_count => length(Points),
feature_count => count_features(Points),
distance => distance(Points)}, GrpcStream};
{Ref, Point} ->
record_route(Ref, Data#{acc => [Point | Points]}, GrpcStream)
end.
-spec route_chat(reference(), GrpcStream :: grpcbox_stream:t()) -> ok.
route_chat(Ref, GrpcStream) ->
route_chat(Ref, [], GrpcStream).
route_chat(Ref, Data, GrpcStream) ->
receive
{Ref, eos} ->
ok;
{Ref, #{location := Location} = P} ->
Messages = proplists:get_all_values(Location, Data),
[grpcbox_stream:send(Message, GrpcStream) || Message <- Messages],
route_chat(Ref, [{Location, P} | Data], GrpcStream)
end.
-spec generate_error(Ctx :: ctx:ctx(), Message :: map()) -> grpcbox_stream:grpc_extended_error_response().
generate_error(_Ctx, _Message) ->
{
grpc_extended_error, #{
status => ?GRPC_STATUS_INTERNAL,
message => <<"error_message">>,
trailers => #{
<<"generate_error_trailer">> => <<"error_trailer">>
}
}
}.
-spec streaming_generate_error(Message :: map(), GrpcStream :: grpcbox_stream:t()) -> no_return().
streaming_generate_error(_Message, _GrpcStream) ->
exit(
{
grpc_extended_error, #{
status => ?GRPC_STATUS_INTERNAL,
message => <<"error_message">>,
trailers => #{
<<"generate_error_trailer">> => <<"error_trailer">>
}
}
}
).
%% Supporting functions
data() ->
case file:read_file("test/otel_interceptor_SUITE_data/route_guide_db.json") of
{ok, Json} ->
jsx:decode(Json, [return_maps, {labels, atom}]);
{error, enoent} ->
{ok, Json} = file:read_file("../../../../test/otel_interceptor_SUITE_data/route_guide_db.json"),
jsx:decode(Json, [return_maps, {labels, atom}])
end.
find_point(_Location, []) ->
"";
find_point(Location, [#{location := Location, name := Name} | _]) ->
Name;
find_point(Location, [_ | T]) ->
find_point(Location, T).
count_features(_) -> 42.
distance(_) -> 42.