Skip to content
Snippets Groups Projects
Commit af7d7ad9 authored by Brett Walker's avatar Brett Walker
Browse files

Create the new AST LoggerAnalyzer

ported from the original LoggerAnalyzer
parent 818cd77f
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,7 @@ class GitlabSchema < GraphQL::Schema
DEFAULT_MAX_DEPTH = 15
AUTHENTICATED_MAX_DEPTH = 20
if Feature.enabled?(:graphql_interpeter)
if Feature.enabled?(:graphql_interpreter)
use GraphQL::Execution::Interpreter
# And, when you have updated your analyzers:
use GraphQL::Analysis::AST
......@@ -23,7 +23,7 @@ class GitlabSchema < GraphQL::Schema
use Gitlab::Graphql::GenericTracing
use Gitlab::Graphql::Timeout, max_seconds: Gitlab.config.gitlab.graphql_timeout
if Feature.enabled?(:graphql_interpeter)
if Feature.enabled?(:graphql_interpreter)
query_analyzer Gitlab::Graphql::QueryAnalyzers::AST::LoggerAnalyzer
query_analyzer Gitlab::Graphql::QueryAnalyzers::AST::RecursionAnalyzer
else
......
---
name: graphql_interpreter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27536
rollout_issue_url:
milestone: '13.11'
type: development
group: group::project management
default_enabled: false
......@@ -5,39 +5,43 @@ module Graphql
module QueryAnalyzers
module AST
class LoggerAnalyzer < GraphQL::Analysis::AST::Analyzer
COMPLEXITY_ANALYZER = GraphQL::Analysis::QueryComplexity.new { |query, complexity_value| complexity_value }
DEPTH_ANALYZER = GraphQL::Analysis::QueryDepth.new { |query, depth_value| depth_value }
COMPLEXITY_ANALYZER = GraphQL::Analysis::AST::QueryComplexity
DEPTH_ANALYZER = GraphQL::Analysis::AST::QueryDepth
FIELD_USAGE_ANALYZER = GraphQL::Analysis::AST::FieldUsage
ALL_ANALYZERS = [COMPLEXITY_ANALYZER, DEPTH_ANALYZER, FIELD_USAGE_ANALYZER].freeze
def analyze?
Feature.enabled?(:graphql_logging, default_enabled: true)
end
attr_reader :results
def initialize(query)
super
def initial_value(query)
variables = process_variables(query.provided_variables)
default_initial_values(query).merge({
query_string: query.query_string,
variables: variables
})
@results = default_initial_values(query).merge({
operation_name: query.operation_name,
query_string: query.query_string,
variables: variables
})
rescue => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
default_initial_values(query)
end
def call(memo, visit_type, irep_node)
memo
@results = default_initial_values(query_or_multiplex)
end
def final_value(memo)
return if memo.nil?
def result
complexity, depth, field_usages = GraphQL::Analysis::AST.analyze_query(@subject, ALL_ANALYZERS, multiplex_analyzers: [])
analyzers = [COMPLEXITY_ANALYZER, DEPTH_ANALYZER]
complexity, depth = GraphQL::Analysis.analyze_query(memo[:query], analyzers)
results[:depth] = depth
results[:complexity] = complexity
# This duration is not the execution time of the
# query but the execution time of the analyzer.
results[:duration_s] = duration(results[:time_started]).round(1)
results[:used_fields] = field_usages[:used_fields]
results[:used_deprecated_fields] = field_usages[:used_deprecated_fields]
memo[:depth] = depth
memo[:complexity] = complexity
memo[:duration_s] = duration(memo[:time_started]).round(1)
RequestStore.store[:graphql_logs] ||= []
RequestStore.store[:graphql_logs] << results
GraphqlLogger.info(results.except!(:time_started, :query))
GraphqlLogger.info(memo.except!(:time_started, :query))
results
rescue => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
end
......@@ -45,11 +49,14 @@ def final_value(memo)
private
def process_variables(variables)
if variables.respond_to?(:to_s)
variables.to_s
else
variables
end
filtered_variables = filter_sensitive_variables(variables)
filtered_variables.try(:to_s) || filtered_variables
end
def filter_sensitive_variables(variables)
ActiveSupport::ParameterFilter
.new(::Rails.application.config.filter_parameters)
.filter(variables)
end
def duration(time_started)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Graphql::QueryAnalyzers::AST::LoggerAnalyzer do
let(:query) { GraphQL::Query.new(GitlabSchema, document: document, context: {}, variables: { body: 'some note' }) }
let(:document) do
GraphQL.parse <<-GRAPHQL
mutation createNote($body: String!) {
createNote(input: {noteableId: "1", body: $body}) {
note {
id
}
}
}
GRAPHQL
end
describe '#result' do
let(:monotonic_time_before) { 42 }
let(:monotonic_time_after) { 500 }
let(:monotonic_time_duration) { monotonic_time_after - monotonic_time_before }
before do
RequestStore.store[:graphql_logs] = nil
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_before, monotonic_time_after)
end
it 'returns the complexity, depth, duration, etc' do
expect(Gitlab::GraphqlLogger).to receive(:info).and_return(true)
result = GraphQL::Analysis::AST.analyze_query(query, [described_class], multiplex_analyzers: [])
expect(result.first[:duration_s]).to eq monotonic_time_duration
expect(result.first[:variables]).to eq '{:body=>"[FILTERED]"}'
expect(result.first[:depth]).to eq 3
expect(result.first[:complexity]).to eq 3
expect(result.first[:used_fields]).to eq ['Note.id', 'CreateNotePayload.note', 'Mutation.createNote']
expect(RequestStore.store[:graphql_logs]).to eq result
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment