require 'graphql/rails_logger/configuration' require 'action_controller/log_subscriber' require 'rouge' require 'pp' module GraphQL module RailsLogger class << self attr_accessor :configuration end def self.configuration @configuration ||= Configuration.new end def self.configure yield(configuration) end class Subscriber < ActionController::LogSubscriber def start_processing(event) return unless logger.info? payload = event.payload params = payload[:params].except(*INTERNAL_PARAMS) format = payload[:format] format = format.to_s.upcase if format.is_a?(Symbol) config = GraphQL::RailsLogger.configuration info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}" if config.white_list.fetch(payload[:controller], []).include?(payload[:action]) formatter = Rouge::Formatters::Terminal256.new(config.theme) query_lexer = Rouge::Lexers::GraphQL.new variables_lexer = Rouge::Lexers::Ruby.new (params['_json'] || [params.slice('query', 'variables', 'extensions')]).each do |data| next if config.skip_introspection_query && data['query']&.index(/query IntrospectionQuery/) # Cleanup and indent params for logging query = indent(data.fetch('query', '')) variables = indent(pretty(data.fetch('variables', ''))) extensions = indent(pretty(data.fetch('extensions', ''))) info "\nVariables:\n#{formatter.format(variables_lexer.lex(variables))}" if variables.present? info "\nQuery:\n#{formatter.format(query_lexer.lex(query))}" if query.present? info "\nExtensions:\n#{formatter.format(variables_lexer.lex(extensions))}" if extensions.present? end else info "\nParameters:\n#{params.inspect}" unless params.empty? end end private def indent(data) data.lines.map { |line| " #{line}" }.join.chomp end def pretty(data) return '' if data.blank? data = JSON.parse(data) if data.is_a?(String) PP.pp(data, '') end end end end