Revert "replace graphQL legacy tracer with official version"
This reverts commit 0975b499d1
.
Reason for revert: needs environment change first
Change-Id: I112b37aa92f825e43240dd49225eef887fa50fb1
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/357034
Reviewed-by: Isaac Moore <isaac.moore@instructure.com>
Build-Review: Isaac Moore <isaac.moore@instructure.com>
Tested-by: Aaron Ogata <aogata@instructure.com>
QA-Review: Aaron Ogata <aogata@instructure.com>
Product-Review: Aaron Ogata <aogata@instructure.com>
This commit is contained in:
parent
6addd9afe6
commit
2fdc82c631
|
@ -68,6 +68,12 @@ class GraphQLController < ApplicationController
|
||||||
in_app: in_app?,
|
in_app: in_app?,
|
||||||
deleted_models: {},
|
deleted_models: {},
|
||||||
request_id: (Thread.current[:context] || {})[:request_id],
|
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
|
Timeout.timeout(1.minute) do
|
||||||
|
|
|
@ -18,13 +18,11 @@
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
require "datadog/auto_instrument"
|
|
||||||
|
|
||||||
class CanvasSchema < GraphQL::Schema
|
class CanvasSchema < GraphQL::Schema
|
||||||
query Types::QueryType
|
query Types::QueryType
|
||||||
mutation Types::MutationType
|
mutation Types::MutationType
|
||||||
trace_with GraphQL::Tracing::DataDogTrace if Rails.env.production?
|
trace_with GraphQL::Tracing::CallLegacyTracers
|
||||||
trace_with GraphQL::Tracing::SentryTrace if Rails.env.production?
|
trace_with GraphQL::Tracing::SentryTrace
|
||||||
|
|
||||||
use GraphQL::Batch
|
use GraphQL::Batch
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
# 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
|
|
@ -10,7 +10,6 @@ services:
|
||||||
- dynamodb
|
- dynamodb
|
||||||
environment:
|
environment:
|
||||||
DB_VALIDITY_ENSURED: 1
|
DB_VALIDITY_ENSURED: 1
|
||||||
DD_TRACE_ENABLED: 'false'
|
|
||||||
ENCRYPTION_KEY: facdd3a131ddd8988b14f6e4e01039c93cfa0160
|
ENCRYPTION_KEY: facdd3a131ddd8988b14f6e4e01039c93cfa0160
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
|
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
|
||||||
|
|
|
@ -194,6 +194,83 @@ describe GraphQLController do
|
||||||
create_discussion_entry("Post 1")
|
create_discussion_entry("Post 1")
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
describe "subgraph_execute" do
|
describe "subgraph_execute" do
|
||||||
|
|
Loading…
Reference in New Issue