Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sentry support for GraphQL-Ruby #2091

Closed
Prithvirajkumar opened this issue Aug 16, 2023 · 7 comments · Fixed by #2308
Closed

Sentry support for GraphQL-Ruby #2091

Prithvirajkumar opened this issue Aug 16, 2023 · 7 comments · Fixed by #2308
Assignees

Comments

@Prithvirajkumar
Copy link
Member

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 - rmosolgo/graphql-ruby#3655

And it looks like they would welcome a PR for it as detailed here - rmosolgo/graphql-ruby#3655 (comment)

@jgrau
Copy link

jgrau commented Sep 4, 2023

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.

@palexvs
Copy link

palexvs commented Sep 19, 2023

We have the same issue, would be really helpful to get support

@sl0thentr0py
Copy link
Member

thx @Prithvirajkumar we'll try to schedule some dev time on this in the next months

@patch0
Copy link

patch0 commented Jan 10, 2024

I've opened a PR on the ruby-graphql repo this morning for this.

@sl0thentr0py
Copy link
Member

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.

@patch0
Copy link

patch0 commented Jan 11, 2024

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?

@sl0thentr0py
Copy link
Member

follow up with steps outlined here

rmosolgo/graphql-ruby#4775 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants