sentry-ruby
sentry-ruby copied to clipboard
Sentry support for GraphQL-Ruby
GraphQL::Tracing::Trace provides hooks to observe and modify events during runtime, link to docs.
Several monitoring platforms are supported out-of-the box by GraphQL-Ruby:
- AppOptics
- Appsignal
- New Relic
- Scout
- Skylight
- Datadog
- Prometheus
- Statsd
The requirement is for Sentry support in GraphQL-Ruby.
There is a GitHub Issue created for this here - https://github.com/rmosolgo/graphql-ruby/issues/3655
And it looks like they would welcome a PR for it as detailed here - https://github.com/rmosolgo/graphql-ruby/issues/3655#issuecomment-1322711825
FWIW this is my custom sentry tracer:
# typed: false
# frozen_string_literal: true
module Tracing
class SentryTracing < ::GraphQL::Tracing::PlatformTracing
self.platform_keys = {
lex: "lex.graphql",
parse: "parse.graphql",
validate: "validate.graphql",
analyze_query: "analyze.graphql",
analyze_multiplex: "analyze.graphql",
execute_multiplex: "execute.graphql",
execute_query: "execute.graphql",
execute_query_lazy: "execute.graphql",
}.stringify_keys
# @param set_action_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
# This is not advised if you run more than one query per HTTP request, for example,
# with `graphql-client` or multiplexing.
# It can also be specified per-query with `context[:set_sentry_action_name]`.
def initialize(options = {})
@set_action_name = options.fetch(:set_action_name, false)
super
end
def platform_trace(_platform_key, key, data)
if key == "execute_query"
set_this_txn_name = data[:query].context[:set_sentry_action_name]
if set_this_txn_name == true ||
(set_this_txn_name.nil? && @set_transaction_name)
Sentry.configure_scope do |scope|
scope.set_transaction_name(transaction_name(data[:query]))
end
end
end
# Ideally we could use `transaction.with_child_span`
# but that resulted in an infinite loop of exceptions that
# i was unable to debug. This is less pretty but works.
#
# Temporary stop creating spans as the transaction will
# be oversized and never sent to Sentry
# Sentry.with_child_span(op: platform_key) do
# yield
# end
# Instead just yield
yield
end
def platform_field_key(type, field)
"#{type.graphql_name}.#{field.graphql_name}.graphql"
end
def platform_authorized_key(type)
"#{type.graphql_name}.authorized.graphql"
end
def platform_resolve_type_key(type)
"#{type.graphql_name}.resolve_type.graphql"
end
private
def transaction_name(query)
[query.context[:sentry_action_name_prefix], super(query)].join("/")
end
end
end
I basically just sets the transaction name based on the graphql query name. For our usecase we needed to add support for a prefix
to that name (we have 2 graphql endpoints - one public and one for admins). There's also support for spans but I had to disable that as the payload to sentry would get too large and then just be dropped.
Feel free to use this as a starting point if it's of any help.
We have the same issue, would be really helpful to get support
thx @Prithvirajkumar we'll try to schedule some dev time on this in the next months
I've opened a PR on the ruby-graphql repo this morning for this.
oh thanks @patch0, we would also be okay with this code living on our side, but if it fits better with the graphql gem's design, also fine. I'll try to review this in the next days.
oh thanks @patch0, we would also be okay with this code living on our side, but if it fits better with the graphql gem's design, also fine. I'll try to review this in the next days.
Can do. I think that's how skylight are doing it. Everyone else has put the code in graphql-ruby. AppOptics have taken a different approach that seems to compare a Gem version, so maybe the tracing is now in two places for them?
follow up with steps outlined here
https://github.com/rmosolgo/graphql-ruby/pull/4775#issuecomment-1892244170