Я новичок в Erlang/Elixir и занимаюсь исследованием того, как использовать otel_resource_detector
в Elixir.
Некоторое время назад мне удалось заставить это работать в Erlang, но я изо всех сил пытаюсь сделать все правильно в Elixir.
Это то, что у меня есть в Erlang:
-module(extra_metadata).
-behaviour(otel_resource_detector).
-export([get_resource/1]).
get_resource(_) ->
Resource1 = otel_resource:create(otel_resource_app_env:parse(get_metadata("/data/extrametadata.properties")), []),
{ok, HiddenMetadataFile} = file:read_file("/data/hiddenpath.properties"),
Resource2 = otel_resource:create(otel_resource_app_env:parse(get_metadata(HiddenMetadataFile)), []),
otel_resource:merge(Resource1, Resource2).
get_metadata(FileName) ->
try
{ok, MetadataFile} = file:read_file(FileName),
Lines = binary:split(MetadataFile, <<"\n">>, [trim, global]),
make_tuples(Lines, [])
catch _:_ -> "Extra Metadata not found"
end.
make_tuples([Line|Lines], Acc) ->
[Key, Value] = binary:split(Line, <<" = ">>),
make_tuples(Lines, [{Key, Value}|Acc]);
make_tuples([], Acc) -> Acc.
Полное приложение Erlang здесь: https://github.com/julianocosta89/erlang_otel_hello_server/tree/main
Я пытаюсь использовать otel_resource_detector
из OpenTelemetry:
https://github.com/open-telemetry/opentelemetry-erlang/blob/37f3cecd9ad2a7b8f3b94c89118585991f0023b1/apps/opentelemetry/src/otel_resource_detector.erl
Как бы я использовал это в Эликсире?
🤔 А знаете ли вы, что...
Erlang обладает мощными инструментами для тестирования и юнит-тестирования приложений.
Модули erlang можно легко назвать из elixir. Первый модуль будет выглядеть
defmodule ExtraMetadata do
@behaviour :otel_resource_detector
def get_resource(_) do
resource1 =
:otel_resource.create(
:otel_resource_app_env.parse(
get_metadata("/data/extrametadata.properties")), [])
{:ok, hidden_metadata_file} =
File.read("/data/hiddenpath.properties")
resource2 =
:otel_resource.create(
:otel_resource_app_env.parse(
get_metadata(hidden_metadata_file)), [])
:otel_resource.merge(resource1, resource2)
end
defp get_metadata(file_name) do
try do
{:ok, metadata_file} = File.read(file_name)
lines = :binary.split(metadata_file, <<"\n">>, [:trim, :global])
make_tuples(lines)
catch
_ -> "Extra Metadata not found"
end
end
# Enum.map/2 would be probably more idiomatic
defp make_tuples(lines, acc \\ [])
defp make_tuples([line|lines], acc) do
[key, value] = :binary.split(line, <<" = ">>)
make_tuples(lines, [{key, value}|cc])
defp make_tuples([], acc), do: acc
end
NB Я, очевидно, не проверял приведенный выше код, некоторые глюки могут потребовать дополнительной обработки.
Вот рабочий фрагмент:
defmodule ExtraMetadata do
@behaviour :otel_resource_detector
def get_resource(_) do
lines = read_file("/data/extrametadata.properties") |> unwrap_lines
file_path = read_file("/data/hiddenpath.properties") |> unwrap_lines
lines2 = read_file(file_path) |> unwrap_lines
attributes = get_attributes(Enum.concat(lines, lines2))
:otel_resource.create(attributes)
end
defp unwrap_lines({:ok, lines}), do: lines
defp unwrap_lines({:error, _}), do: []
defp read_file(file_name) do
try do
{:ok, String.split(File.read!(file_name), "\n")}
rescue
File.Error ->
{:error, "File does not exist, safe to continue"}
end
end
defp get_attributes(lines) do
# Transform each string into a tuple
Enum.map(lines, fn(line) ->
if String.length(line) > 0 do
[key, value] = String.split(line, " = ")
{key, value}
else
{:error, "Empty string"}
end
end)
end
end
Я также выложил весь проект сюда: https://github.com/julianocosta89/elixir-hello.