Feature Flag Service
This service is written in Erlang/Elixir and it is responsible for creating, reading, updating and deleting feature flags in a PostgreSQL DB. It is called by Product Catalog and Shipping services.
Traces
Initializing Tracing
In order to set up OpenTelemetry instrumentation for Phoenix, and Ecto, we need to call the setup methods of their instrumentation packages before starting the Supervisor.
This is done in the application.ex
as follows:
@impl true
def start(_type, _args) do
OpentelemetryEcto.setup([:featureflagservice, :repo])
OpentelemetryPhoenix.setup()
children = [
# Start the Ecto repository
Featureflagservice.Repo,
# Start the PubSub system
{Phoenix.PubSub, name: Featureflagservice.PubSub},
# Start the Endpoint (http/https)
FeatureflagserviceWeb.Endpoint
# Start a worker by calling: Featureflagservice.Worker.start_link(arg)
# {Featureflagservice.Worker, arg}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Featureflagservice.Supervisor]
Supervisor.start_link(children, opts)
end
To add tracing to grpcbox, we need to add the appropriate interceptor.
This is configured in the runtime.exs
file, as follows:
config :grpcbox,
servers: [
%{
:grpc_opts => %{
:service_protos => [:ffs_demo_pb],
:unary_interceptor => {:otel_grpcbox_interceptor, :unary},
:services => %{:"oteldemo.FeatureFlagService" => :ffs_service}
},
:listen_opts => %{:port => grpc_port}
}
]
Add attributes to auto-instrumented spans
Adding attributes to a span is accomplished by using ?set_attribute
on the
span object. In the get_flag
function two attributes are added to the span.
-include_lib("grpcbox/include/grpcbox.hrl").
-include_lib("opentelemetry_api/include/otel_tracer.hrl").
-spec get_flag(ctx:t(), ffs_demo_pb:get_flag_request()) ->
{ok, ffs_demo_pb:get_flag_response(), ctx:t()} | grpcbox_stream:grpc_error_response().
get_flag(Ctx, #{name := Name}) ->
case 'Elixir.Featureflagservice.FeatureFlags':get_feature_flag_by_name(Name) of
nil ->
{grpc_error, {?GRPC_STATUS_NOT_FOUND, <<"the requested feature flag does not exist">>}};
#{'__struct__' := 'Elixir.Featureflagservice.FeatureFlags.FeatureFlag',
description := Description,
enabled := Enabled,
inserted_at := CreatedAt,
updated_at := UpdatedAt
} ->
?set_attribute('app.featureflag.name', Name),
?set_attribute('app.featureflag.enabled', Enabled),
{ok, Epoch} = 'Elixir.NaiveDateTime':from_erl({{1970, 1, 1}, {0, 0, 0}}),
CreatedAtSeconds = 'Elixir.NaiveDateTime':diff(CreatedAt, Epoch),
UpdatedAtSeconds = 'Elixir.NaiveDateTime':diff(UpdatedAt, Epoch),
Flag = #{name => Name,
description => Description,
enabled => Enabled,
created_at => #{seconds => CreatedAtSeconds, nanos => 0},
updated_at => #{seconds => UpdatedAtSeconds, nanos => 0}},
{ok, #{flag => Flag}, Ctx}
end.
Metrics
TBD
Logs
TBD
Last modified December 2, 2023: Remove extra comma (#3638) (75471b41)