Module: Stellate::MetricsLogging

Defined in:
lib/stellate.rb

Overview

Extend your GraphQL::Schema with this module to enable easy Stellate Metrics Logging.

Add ‘extend Stellate::MetricsLogging` within your schema class. This will add the class method `execute_with_logging`. Then replace the call to `MySchema.execute()` with `MySchema.execute_with_logging()`.

Instance Method Summary collapse

Instance Method Details

#execute_with_logging(query_str = nil, **kwargs) ⇒ Object

Executes a given GraphQL query on the schema and logs details about the request and execution to Stellate. This function accepts the same arguments as ‘GraphQL::Schema.execute()`, and also the following:

  • ‘headers` (`ActionDispatch::Http::Headers`): The HTTP headers from the incoming request

  • ‘callback` (`Method`): If passed, this will be called with a lambda as argument. Calling the passed lambda will log the request to Stellate via HTTP. This is useful if you want to move this request into a non- blocking process (e.g. using Sidekiq) rather than the default behavior of performing a blocking HTTP request which can increase overall response times of your API.



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
# File 'lib/stellate.rb', line 27

def execute_with_logging(query_str = nil, **kwargs)
  starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)

  result = execute(query_str, **kwargs.except(:headers, :callback))

  ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed = (ending - starting) * 1000

  headers = kwargs[:headers]
  has_headers = headers.is_a?(ActionDispatch::Http::Headers)

  return result if has_headers && headers['Gcdn-Request-Id'].is_a?(String)

  unless @stellate_service_name.is_a?(String)
    puts 'Missing service name in order to log metrics to Stellate'
    return result
  end

  unless @stellate_token.is_a?(String)
    puts 'Missing token in order to log metrics to Stellate'
    return result
  end

  unless query_str.is_a?(String)
    puts 'Cannot log metrics to Stellate without a query string'
    return result
  end

  response = result.to_json
  payload = {
    'operation' => query_str,
    'variableHash' => create_blake3_hash(kwargs[:variables].to_json),
    'method' => kwargs[:method].is_a?(String) ? kwargs[:method] : 'POST',
    'elapsed' => elapsed.round,
    'responseSize' => response.length,
    'responseHash' => create_blake3_hash(response),
    'statusCode' => 200,
    'operationName' => kwargs[:operation_name]
  }

  errors = result['errors']
  payload[:errors] = errors if errors.is_a?(Array)

  if has_headers
    forwarded_for = headers['X-Forwarded-For']
    ips = forwarded_for.is_a?(String) ? forwarded_for.split(',') : []

    payload['ip'] = ips[0] || headers['True-Client-Ip'] || headers['X-Real-Ip']
    payload['userAgent'] = headers['User-Agent']
    payload['referer'] = headers['referer']
    payload['graphqlClientName'] = headers['x-graphql-client-name']
    payload['graphqlClientVersion'] = headers['x-graphql-client-version']
  end

  stellate_request = {
    'url' => "https://#{@stellate_service_name}.stellate.sh/log",
    'headers' => {
      'Content-Type' => 'application/json',
      'Stellate-Logging-Token' => @stellate_token
    },
    'body' => payload.to_json
  }

  callback = kwargs[:callback]
  # The former check handles methods, the latter handles lambdas
  if callback.is_a?(Method) || callback.respond_to?(:call)
    callback.call(stellate_request)
  # This handles symbols that contain methods
  elsif callback.is_a?(Symbol) && method(callback).is_a?(Method)
    method(callback).call(stellate_request)
  else
    run_stellate_request(stellate_request)
  end

  result
end

#stellate_service_nameObject



104
105
106
# File 'lib/stellate.rb', line 104

def stellate_service_name
  @stellate_service_name
end

#stellate_tokenObject



108
109
110
# File 'lib/stellate.rb', line 108

def stellate_token
  @stellate_token
end