Add GraphQL operation name, user ID and actor name in logs

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2022-11-06 11:57:53 +01:00
parent de8433cdbb
commit 30b0d3ca08
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
5 changed files with 38 additions and 5 deletions

View file

@ -138,7 +138,7 @@ config :vite_phx,
config :logger, :console, config :logger, :console,
backends: [:console], backends: [:console],
format: "$time $metadata[$level] $message\n", format: "$time $metadata[$level] $message\n",
metadata: [:request_id] metadata: [:request_id, :graphql_operation_name, :user_id, :actor_name]
config :mobilizon, Mobilizon.Web.Auth.Guardian, config :mobilizon, Mobilizon.Web.Auth.Guardian,
issuer: "mobilizon", issuer: "mobilizon",

View file

@ -48,7 +48,7 @@ config :mobilizon, Mobilizon.Web.Endpoint,
] ]
# Do not include metadata nor timestamps in development logs # Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n", level: :debug config :logger, :console, format: "$metadata[$level] $message\n", level: :debug
config :mobilizon, Mobilizon.Service.Geospatial, service: Mobilizon.Service.Geospatial.Nominatim config :mobilizon, Mobilizon.Service.Geospatial, service: Mobilizon.Service.Geospatial.Nominatim

View file

@ -18,7 +18,13 @@ defmodule Mobilizon.GraphQL.Middleware.CurrentActorProvider do
case Cachex.fetch(:default_actors, to_string(user_id), fn -> default(user) end) do case Cachex.fetch(:default_actors, to_string(user_id), fn -> default(user) end) do
{status, %Actor{preferred_username: preferred_username} = current_actor} {status, %Actor{preferred_username: preferred_username} = current_actor}
when status in [:ok, :commit] -> when status in [:ok, :commit] ->
Logger.metadata(user_id: user_id)
Logger.metadata(actor_name: "@" <> preferred_username)
if Application.get_env(:sentry, :dsn) != nil do
Sentry.Context.set_user_context(%{name: preferred_username}) Sentry.Context.set_user_context(%{name: preferred_username})
end
context = Map.put(context, :current_actor, current_actor) context = Map.put(context, :current_actor, current_actor)
%Absinthe.Resolution{resolution | context: context} %Absinthe.Resolution{resolution | context: context}

View file

@ -0,0 +1,27 @@
defmodule Mobilizon.GraphQL.Middleware.OperationNameLogger do
@moduledoc """
An Absinthe middleware to add to logging providers the GraphQL Operation name as context
"""
@behaviour Absinthe.Middleware
alias Absinthe.Blueprint.Document.Operation
def call(resolution, _opts) do
case Enum.find(resolution.path, &current_operation?/1) do
%Operation{name: name} when not is_nil(name) ->
Logger.metadata(graphql_operation_name: name)
if Application.get_env(:sentry, :dsn) != nil do
Sentry.Context.set_extra_context(%{"graphql_operation_name" => name})
end
_ ->
Logger.metadata(graphql_operation_name: "#NULL")
end
resolution
end
defp current_operation?(%Operation{current: true}), do: true
defp current_operation?(_), do: false
end

View file

@ -20,7 +20,7 @@ defmodule Mobilizon.GraphQL.Schema do
alias Mobilizon.Actors.{Actor, Follower, Member} alias Mobilizon.Actors.{Actor, Follower, Member}
alias Mobilizon.Discussions.Comment alias Mobilizon.Discussions.Comment
alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Events.{Event, Participant}
alias Mobilizon.GraphQL.Middleware.{CurrentActorProvider, ErrorHandler} alias Mobilizon.GraphQL.Middleware.{CurrentActorProvider, ErrorHandler, OperationNameLogger}
alias Mobilizon.GraphQL.Schema alias Mobilizon.GraphQL.Schema
alias Mobilizon.GraphQL.Schema.Custom alias Mobilizon.GraphQL.Schema.Custom
alias Mobilizon.Storage.Repo alias Mobilizon.Storage.Repo
@ -199,7 +199,7 @@ defmodule Mobilizon.GraphQL.Schema do
@spec middleware(list(module()), any(), map()) :: list(module()) @spec middleware(list(module()), any(), map()) :: list(module())
def middleware(middleware, _field, %{identifier: type}) when type in [:query, :mutation] do def middleware(middleware, _field, %{identifier: type}) when type in [:query, :mutation] do
[CurrentActorProvider] ++ middleware ++ [ErrorHandler] [CurrentActorProvider] ++ middleware ++ [ErrorHandler, OperationNameLogger]
end end
def middleware(middleware, _field, _object) do def middleware(middleware, _field, _object) do