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.
Feature Flag Service Source
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 => %{:"hipstershop.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