File: sentry_trace_spec.rb

package info (click to toggle)
ruby-graphql 2.2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,584 kB
  • sloc: ruby: 67,505; ansic: 1,753; yacc: 831; javascript: 331; makefile: 6
file content (160 lines) | stat: -rw-r--r-- 5,156 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# frozen_string_literal: true
require "spec_helper"

describe GraphQL::Tracing::SentryTrace do
  module SentryTraceTest
    class Thing < GraphQL::Schema::Object
      field :str, String
      def str; "blah"; end
    end

    class Query < GraphQL::Schema::Object
      field :int, Integer, null: false

      def int
        1
      end

      field :thing, Thing
      def thing; :thing; end
    end

    class SchemaWithoutTransactionName < GraphQL::Schema
      query(Query)

      module OtherTrace
        def execute_query(query:)
          query.context[:other_trace_ran] = true
          super
        end
      end
      trace_with OtherTrace
      trace_with GraphQL::Tracing::SentryTrace
    end

    class SchemaWithTransactionName < GraphQL::Schema
      query(Query)
      trace_with(GraphQL::Tracing::SentryTrace, set_transaction_name: true)
    end
  end

  before do
    Sentry.clear_all
  end

  it "works with other trace modules" do
    res = SentryTraceTest::SchemaWithoutTransactionName.execute("{ int }")
    assert res.context[:other_trace_ran]
  end

  describe "When Sentry is not configured" do
    it "does not initialize any spans" do
      Sentry.stub(:initialized?, false) do
        SentryTraceTest::SchemaWithoutTransactionName.execute("{ int thing { str } }")
        assert_equal [], Sentry::SPAN_DATA
        assert_equal [], Sentry::SPAN_DESCRIPTIONS
        assert_equal [], Sentry::SPAN_OPS
      end
    end
  end

  describe "When Sentry.with_child_span returns nil" do
    it "does not initialize any spans" do
      Sentry.stub(:with_child_span, nil) do
        SentryTraceTest::SchemaWithoutTransactionName.execute("{ int thing { str } }")
        assert_equal [], Sentry::SPAN_DATA
        assert_equal [], Sentry::SPAN_DESCRIPTIONS
        assert_equal [], Sentry::SPAN_OPS
      end
    end
  end

  it "sets the expected spans" do
    SentryTraceTest::SchemaWithoutTransactionName.execute("{ int thing { str } }")
    expected_span_ops = [
      "graphql.execute_multiplex",
      "graphql.analyze_multiplex",
      (USING_C_PARSER ? "graphql.lex" : nil),
      "graphql.parse",
      "graphql.validate",
      "graphql.analyze",
      "graphql.execute",
      "graphql.authorized.Query",
      "graphql.field.Query.thing",
      "graphql.authorized.Thing",
      "graphql.execute"
    ].compact

    assert_equal expected_span_ops, Sentry::SPAN_OPS
  end

  it "sets span descriptions for an anonymous query" do
    SentryTraceTest::SchemaWithoutTransactionName.execute("{ int }")

    assert_equal ["query", "query"], Sentry::SPAN_DESCRIPTIONS
  end

  it "sets span data for an anonymous query" do
    SentryTraceTest::SchemaWithoutTransactionName.execute("{ int }")
    expected_span_data = [
      ["graphql.document", "{ int }"],
      ["graphql.operation.type", "query"]
    ].compact

    assert_equal expected_span_data.sort, Sentry::SPAN_DATA.sort
  end

  it "sets span descriptions for a named query" do
    SentryTraceTest::SchemaWithoutTransactionName.execute("query Ab { int }")

    assert_equal ["query Ab", "query Ab"], Sentry::SPAN_DESCRIPTIONS
  end

  it "sets span data for a named query" do
    SentryTraceTest::SchemaWithoutTransactionName.execute("query Ab { int }")
    expected_span_data = [
      ["graphql.document", "query Ab { int }"],
      ["graphql.operation.name", "Ab"],
      ["graphql.operation.type", "query"]
    ].compact

    assert_equal expected_span_data.sort, Sentry::SPAN_DATA.sort
  end

  it "can leave the transaction name in place" do
    SentryTraceTest::SchemaWithoutTransactionName.execute "query X { int }"
    assert_equal [], Sentry::TRANSACTION_NAMES
  end

  it "can override the transaction name" do
    SentryTraceTest::SchemaWithTransactionName.execute "query X { int }"
    assert_equal ["GraphQL/query.X"], Sentry::TRANSACTION_NAMES
  end

  it "can override the transaction name per query" do
    # Override with `false`
    SentryTraceTest::SchemaWithTransactionName.execute "{ int }", context: { set_sentry_transaction_name: false }
    assert_equal [], Sentry::TRANSACTION_NAMES
    # Override with `true`
    SentryTraceTest::SchemaWithoutTransactionName.execute "{ int }", context: { set_sentry_transaction_name: true }
    assert_equal ["GraphQL/query.anonymous"], Sentry::TRANSACTION_NAMES
  end

  it "falls back to a :tracing_fallback_transaction_name when provided" do
    SentryTraceTest::SchemaWithTransactionName.execute("{ int }", context: { tracing_fallback_transaction_name: "Abcd" })
    assert_equal ["GraphQL/query.Abcd"], Sentry::TRANSACTION_NAMES
  end

  it "does not use the :tracing_fallback_transaction_name if an operation name is present" do
    SentryTraceTest::SchemaWithTransactionName.execute(
      "query Ab { int }",
      context: { tracing_fallback_transaction_name: "Cd" }
    )
    assert_equal ["GraphQL/query.Ab"], Sentry::TRANSACTION_NAMES
  end

  it "does not require a :tracing_fallback_transaction_name even if an operation name is not present" do
    SentryTraceTest::SchemaWithTransactionName.execute("{ int }")
    assert_equal ["GraphQL/query.anonymous"], Sentry::TRANSACTION_NAMES
  end
end