feat(graphql): improuve logs
This commit is contained in:
parent
5ca0ed18a4
commit
a5733002ed
6 changed files with 37 additions and 39 deletions
|
@ -1,9 +1,7 @@
|
||||||
class API::V2::GraphqlController < API::V2::BaseController
|
class API::V2::GraphqlController < API::V2::BaseController
|
||||||
def execute
|
def execute
|
||||||
result = API::V2::Schema.execute(query,
|
result = API::V2::Schema.execute(query:, variables:, context:, operation_name:)
|
||||||
variables: variables,
|
@query_info = result.context.query_info
|
||||||
context: context,
|
|
||||||
operation_name: params[:operationName])
|
|
||||||
|
|
||||||
render json: result
|
render json: result
|
||||||
rescue GraphQL::ParseError, JSON::ParserError => exception
|
rescue GraphQL::ParseError, JSON::ParserError => exception
|
||||||
|
@ -27,10 +25,7 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
|
|
||||||
super
|
super
|
||||||
|
|
||||||
payload.merge!({
|
payload.merge!(@query_info.presence || {})
|
||||||
graphql_query: query(fallback: params[:queryId]),
|
|
||||||
graphql_variables: to_unsafe_hash(params[:variables]).to_json
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_action(*args)
|
def process_action(*args)
|
||||||
|
@ -44,9 +39,9 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
}, status: 400
|
}, status: 400
|
||||||
end
|
end
|
||||||
|
|
||||||
def query(fallback: nil)
|
def query
|
||||||
if params[:queryId].present?
|
if params[:queryId].present?
|
||||||
API::V2::StoredQuery.get(params[:queryId], fallback: fallback)
|
API::V2::StoredQuery.get(params[:queryId])
|
||||||
else
|
else
|
||||||
params[:query]
|
params[:query]
|
||||||
end
|
end
|
||||||
|
@ -56,6 +51,10 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
ensure_hash(params[:variables])
|
ensure_hash(params[:variables])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def operation_name
|
||||||
|
params[:operationName]
|
||||||
|
end
|
||||||
|
|
||||||
# Handle form data, JSON body, or a blank value
|
# Handle form data, JSON body, or a blank value
|
||||||
def ensure_hash(ambiguous_param)
|
def ensure_hash(ambiguous_param)
|
||||||
case ambiguous_param
|
case ambiguous_param
|
||||||
|
@ -76,23 +75,6 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_unsafe_hash(ambiguous_param)
|
|
||||||
case ambiguous_param
|
|
||||||
when String
|
|
||||||
if ambiguous_param.present?
|
|
||||||
JSON.parse(ambiguous_param)
|
|
||||||
else
|
|
||||||
{}
|
|
||||||
end
|
|
||||||
when ActionController::Parameters
|
|
||||||
ambiguous_param.to_unsafe_h
|
|
||||||
else
|
|
||||||
ambiguous_param
|
|
||||||
end
|
|
||||||
rescue JSON::ParserError
|
|
||||||
{}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_parse_error(exception)
|
def handle_parse_error(exception)
|
||||||
render json: {
|
render json: {
|
||||||
errors: [
|
errors: [
|
||||||
|
@ -115,15 +97,15 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_error_in_production(exception)
|
def handle_error_in_production(exception)
|
||||||
id = SecureRandom.uuid
|
extra = { exception_id: SecureRandom.uuid }
|
||||||
Sentry.capture_exception(exception, extra: { exception_id: id })
|
Sentry.capture_exception(exception, extra:)
|
||||||
|
|
||||||
render json: {
|
render json: {
|
||||||
errors: [
|
errors: [
|
||||||
{
|
{
|
||||||
message: "Internal Server Error",
|
message: "Internal Server Error",
|
||||||
extensions: {
|
extensions: {
|
||||||
exception: { id: id }
|
exception: { id: extra[:exception_id] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -55,6 +55,15 @@ class API::V2::Context < GraphQL::Query::Context
|
||||||
self[:authorized][demarche.id]
|
self[:authorized][demarche.id]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def query_info
|
||||||
|
{
|
||||||
|
graphql_query: query.query_string,
|
||||||
|
graphql_variables: query.provided_variables&.to_json,
|
||||||
|
graphql_null_error: errors.any? { _1.is_a? GraphQL::InvalidNullError }.presence,
|
||||||
|
graphql_timeout_error: errors.any? { _1.is_a? GraphQL::Schema::Timeout::TimeoutError }.presence
|
||||||
|
}.compact
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def compute_demarche_authorization(demarche)
|
def compute_demarche_authorization(demarche)
|
||||||
|
|
|
@ -125,14 +125,13 @@ class API::V2::Schema < GraphQL::Schema
|
||||||
def self.type_error(error, ctx)
|
def self.type_error(error, ctx)
|
||||||
# Capture type errors in Sentry. Thouse errors are our responsability and usually linked to
|
# Capture type errors in Sentry. Thouse errors are our responsability and usually linked to
|
||||||
# instances of "bad data".
|
# instances of "bad data".
|
||||||
Sentry.capture_exception(error)
|
Sentry.capture_exception(error, extra: ctx.query_info)
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
class Timeout < GraphQL::Schema::Timeout
|
class Timeout < GraphQL::Schema::Timeout
|
||||||
def handle_timeout(error, query)
|
def handle_timeout(error, query)
|
||||||
extra = { query: query.query_string, variables: query.provided_variables&.to_json }
|
Sentry.capture_exception(error, extra: query.context.query_info)
|
||||||
Sentry.capture_exception(error, extra:)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class API::V2::StoredQuery
|
class API::V2::StoredQuery
|
||||||
def self.get(query_id, fallback: nil)
|
def self.get(query_id)
|
||||||
case query_id
|
case query_id
|
||||||
when 'ds-query-v2'
|
when 'ds-query-v2'
|
||||||
QUERY_V2
|
QUERY_V2
|
||||||
|
@ -8,11 +8,7 @@ class API::V2::StoredQuery
|
||||||
when 'introspection'
|
when 'introspection'
|
||||||
GraphQL::Introspection::INTROSPECTION_QUERY
|
GraphQL::Introspection::INTROSPECTION_QUERY
|
||||||
else
|
else
|
||||||
if fallback.nil?
|
|
||||||
raise GraphQL::ExecutionError.new("No query with id \"#{query_id}\"")
|
raise GraphQL::ExecutionError.new("No query with id \"#{query_id}\"")
|
||||||
else
|
|
||||||
fallback
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ Rails.application.configure do
|
||||||
user_agent: event.payload[:user_agent],
|
user_agent: event.payload[:user_agent],
|
||||||
graphql_query: event.payload[:graphql_query],
|
graphql_query: event.payload[:graphql_query],
|
||||||
graphql_variables: event.payload[:graphql_variables],
|
graphql_variables: event.payload[:graphql_variables],
|
||||||
|
graphql_null_error: event.payload[:graphql_null_error],
|
||||||
|
graphql_timeout_error: event.payload[:graphql_timeout_error],
|
||||||
browser: event.payload[:browser],
|
browser: event.payload[:browser],
|
||||||
browser_version: event.payload[:browser_version],
|
browser_version: event.payload[:browser_version],
|
||||||
platform: event.payload[:platform],
|
platform: event.payload[:platform],
|
||||||
|
|
|
@ -684,6 +684,16 @@ describe API::V2::GraphqlController do
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "error in degraded mode" do
|
||||||
|
before do
|
||||||
|
dossier.etablissement.update!(adresse: nil, siege_social: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return an error" do
|
||||||
|
expect(gql_errors).to eq([{ message: "Cannot return null for non-nullable field PersonneMorale.siegeSocial" }])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "champs" do
|
context "champs" do
|
||||||
|
|
Loading…
Reference in a new issue