replace graphQL legacy tracer with official version

refs AE-1198

Change-Id: I10060ef5569944c3c618a6718bf4e735e2c6f411
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/357232
Reviewed-by: Isaac Moore <isaac.moore@instructure.com>
Build-Review: Isaac Moore <isaac.moore@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Aaron Ogata <aogata@instructure.com>
Product-Review: Aaron Ogata <aogata@instructure.com>
This commit is contained in:
Aaron Ogata 2024-09-11 10:30:21 -07:00
parent 0b1a813a42
commit 0975b499d1
5 changed files with 5 additions and 154 deletions

View File

@ -68,12 +68,6 @@ class GraphQLController < ApplicationController
in_app: in_app?,
deleted_models: {},
request_id: (Thread.current[:context] || {})[:request_id],
tracers: [
Tracers::DatadogTracer.new(
request.headers["GraphQL-Metrics"] == "true",
request.host_with_port.sub(":", "_")
)
]
}
Timeout.timeout(1.minute) do

View File

@ -18,11 +18,13 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require "datadog/auto_instrument"
class CanvasSchema < GraphQL::Schema
query Types::QueryType
mutation Types::MutationType
trace_with GraphQL::Tracing::CallLegacyTracers
trace_with GraphQL::Tracing::SentryTrace
trace_with GraphQL::Tracing::DataDogTrace if Rails.env.production?
trace_with GraphQL::Tracing::SentryTrace if Rails.env.production?
use GraphQL::Batch

View File

@ -1,69 +0,0 @@
# frozen_string_literal: true
#
# Copyright (C) 2018 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require "datadog/statsd"
module Tracers
class DatadogTracer
def initialize(first_party, domain)
@third_party = !first_party
@domain = domain
end
def trace(key, metadata, &)
if key == "validate"
tags = {}
tags[:operation_name] = @third_party ? "3rdparty" : metadata[:query].operation_name || "unnamed"
op, fields = op_type_and_fields(metadata)
fields.each do |field|
InstStatsd::Statsd.increment("graphql.#{op}.count", tags: tags.merge(field:))
end
InstStatsd::Statsd.increment("graphql.operation.count", tags:)
InstStatsd::Statsd.time("graphql.operation.time", tags:, &)
else
yield
end
end
# easiest to describe what this does by example. if the operation is:
# query MyQuery {
# course(id: "1") { name }
# legacyNode(type: User, id: "5") { sisId }
# }
# then this will return ["query", ["course", "legacyNode"]]
#
# if the operation is:
# mutation MyMutation {
# createAssignment(input: {courseId: "1", name: "Do my bidding"}) {
# assignment {
# name
# }
# }
# }
# then this will return ["mutation", ["createAssignment"]]
def op_type_and_fields(metadata)
op = metadata[:query].selected_operation
op_type = op.operation_type || "query"
[op_type, op.selections.map(&:name)]
end
end
end

View File

@ -10,6 +10,7 @@ services:
- dynamodb
environment:
DB_VALIDITY_ENSURED: 1
DD_TRACE_ENABLED: 'false'
ENCRYPTION_KEY: facdd3a131ddd8988b14f6e4e01039c93cfa0160
RAILS_ENV: test
POSTGRES_PASSWORD: $POSTGRES_PASSWORD

View File

@ -194,83 +194,6 @@ describe GraphQLController do
create_discussion_entry("Post 1")
end
end
context "datadog metrics" do
before { allow(InstStatsd::Statsd).to receive(:increment).and_call_original }
def expect_increment(metric, tags)
expect(InstStatsd::Statsd).to have_received(:increment).with(metric, tags:)
end
context "for first-party queries" do
def mark_first_party(request)
request.headers["GraphQL-Metrics"] = "true"
end
it "counts each operation and query top-level field" do
mark_first_party(request)
test_query = <<~GQL
query GetStuff {
course(id: "1") { name }
assignment(id: "1") { name }
legacyNode(type: User, id: "1") {
... on User { email }
}
}
GQL
post :execute, params: { query: test_query }, format: :json
expect_increment("graphql.operation.count", operation_name: "GetStuff")
expect_increment("graphql.query.count", operation_name: "GetStuff", field: "course")
expect_increment("graphql.query.count", operation_name: "GetStuff", field: "assignment")
expect_increment("graphql.query.count", operation_name: "GetStuff", field: "legacyNode")
end
it "counts unnamed operations" do
mark_first_party(request)
test_query = <<~GQL
query {
course(id: "1") { name }
assignment(id: "1") { name }
}
GQL
post :execute, params: { query: test_query }, format: :json
expect_increment("graphql.operation.count", operation_name: "unnamed")
expect_increment("graphql.query.count", operation_name: "unnamed", field: "course")
expect_increment("graphql.query.count", operation_name: "unnamed", field: "assignment")
end
it "counts each mutation top-level field" do
mark_first_party(request)
test_query = <<~GQL
mutation {
createAssignment(input: {courseId: "1", name: "Do my bidding"}) {
assignment { name }
}
updateAssignment(input: {id: "1", name: "Do it good"}) {
assignment { name }
}
}
GQL
post :execute, params: { query: test_query }, format: :json
expect_increment("graphql.operation.count", operation_name: "unnamed")
expect_increment("graphql.mutation.count", operation_name: "unnamed", field: "createAssignment")
expect_increment("graphql.mutation.count", operation_name: "unnamed", field: "updateAssignment")
end
end
context "for third-party queries" do
it "names all operations '3rdparty' and omits hashes" do
test_query = <<~GQL
query GetStuff {
course(id: "1") { name }
}
GQL
post :execute, params: { query: test_query }, format: :json
expect_increment("graphql.operation.count", operation_name: "3rdparty")
expect_increment("graphql.query.count", operation_name: "3rdparty", field: "course")
end
end
end
end
describe "subgraph_execute" do