stellate 0.0.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/stellate.rb +83 -35
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf645f43b4d1c0d62fd71ce6739b62c5046f84387a4687d34f0dbe5155d16150
4
- data.tar.gz: bea394e5b879a938810d0d0555071032fedd117494af2452be7ad67f9ee4fa6b
3
+ metadata.gz: 1c1a2d292de035b6fce0fd0caa8d9e2c1a03aa5034e8b18e3da3e212f5c1690b
4
+ data.tar.gz: 4e71e1ec928e81c737083c48766644d606180bdb83dee4f41989f201bc8bc135
5
5
  SHA512:
6
- metadata.gz: 87209538300252aa2fde91ebe1fa8b97ed64346aa90d7740fcd07fd5493490326a012d63b13a87b4c1d304f22be283f05ac5d55f9fe2a8b8f308ab41324ff843
7
- data.tar.gz: 247e1efc7ca6bf954e482af75b3dccd587ba7ace9393e699358a936e0fc04d507a9219d9c61db125d6b53c62b692a7bcf15f9f5234c2b9b42a0b388b66cee55a
6
+ metadata.gz: 021e9f325d3434df6ee2d004a06b543cbe475e9784ffc068c544f0d48d45eb44978642d41bf0eda20482629012435d049ccedac9d0c7be39f5ae810aa6652e08
7
+ data.tar.gz: b74619cf8782d5afac11d2f32330ae33dcaa3269b51f5876d01df30884502847160031b49f8445cc50cb02ff43f9b05f4c1c3f140c5d4b418f07762ff1bcf826
data/lib/stellate.rb CHANGED
@@ -4,7 +4,7 @@ require 'uri'
4
4
  require 'net/http'
5
5
 
6
6
  module Stellate
7
- VERSION = '0.0.2'
7
+ VERSION = '1.0.0'
8
8
 
9
9
  # Extend your GraphQL::Schema with this module to enable easy Stellate
10
10
  # Metrics Logging.
@@ -18,14 +18,25 @@ module Stellate
18
18
  # arguments as `GraphQL::Schema.execute()`, and also the following:
19
19
  # - `headers` (`ActionDispatch::Http::Headers`): The HTTP headers from the
20
20
  # incoming request
21
+ # - `callback` (`Method`): If passed, this will be called with a lambda as
22
+ # argument. Calling the passed lambda will log the request to Stellate
23
+ # via HTTP. This is useful if you want to move this request into a non-
24
+ # blocking process (e.g. using Sidekiq) rather than the default behavior
25
+ # of performing a blocking HTTP request which can increase overall
26
+ # response times of your API.
21
27
  def execute_with_logging(query_str = nil, **kwargs)
22
28
  starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
23
29
 
24
- result = execute(query_str, **kwargs.except(:service_name, :token, :headers))
30
+ result = execute(query_str, **kwargs.except(:headers, :callback))
25
31
 
26
32
  ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
27
33
  elapsed = (ending - starting) * 1000
28
34
 
35
+ headers = kwargs[:headers]
36
+ has_headers = headers.is_a?(ActionDispatch::Http::Headers)
37
+
38
+ return result if has_headers && headers['Gcdn-Request-Id'].is_a?(String)
39
+
29
40
  unless @stellate_service_name.is_a?(String)
30
41
  puts 'Missing service name in order to log metrics to Stellate'
31
42
  return result
@@ -43,41 +54,46 @@ module Stellate
43
54
 
44
55
  response = result.to_json
45
56
  payload = {
46
- "operation": query_str,
47
- "variableHash": create_blake3_hash(kwargs[:variables].to_json),
48
- "method": kwargs[:method].is_a?(String) ? kwargs[:method] : 'POST',
49
- "elapsed": elapsed.round,
50
- "responseSize": response.length,
51
- "responseHash": create_blake3_hash(response),
52
- "statusCode": 200,
53
- "operationName": kwargs[:operation_name]
57
+ 'operation' => query_str,
58
+ 'variableHash' => create_blake3_hash(kwargs[:variables].to_json),
59
+ 'method' => kwargs[:method].is_a?(String) ? kwargs[:method] : 'POST',
60
+ 'elapsed' => elapsed.round,
61
+ 'responseSize' => response.length,
62
+ 'responseHash' => create_blake3_hash(response),
63
+ 'statusCode' => 200,
64
+ 'operationName' => kwargs[:operation_name]
54
65
  }
55
66
 
56
67
  errors = result['errors']
57
68
  payload[:errors] = errors if errors.is_a?(Array)
58
69
 
59
- headers = kwargs[:headers]
60
- if headers.is_a?(ActionDispatch::Http::Headers)
70
+ if has_headers
61
71
  forwarded_for = headers['X-Forwarded-For']
62
72
  ips = forwarded_for.is_a?(String) ? forwarded_for.split(',') : []
63
73
 
64
- payload[:id] = ips[0] || headers['True-Client-Ip'] || headers['X-Real-Ip']
65
- payload[:userAgent] = headers['User-Agent']
66
- payload[:referer] = headers['referer']
67
-
74
+ payload['ip'] = ips[0] || headers['True-Client-Ip'] || headers['X-Real-Ip']
75
+ payload['userAgent'] = headers['User-Agent']
76
+ payload['referer'] = headers['referer']
68
77
  end
69
78
 
70
- # TODO: make this an async request to avoid blocking the response
71
- begin
72
- res = Net::HTTP.post(
73
- URI("https://#{@stellate_service_name}.stellate.sh/log"),
74
- payload.to_json,
79
+ stellate_request = {
80
+ 'url' => "https://#{@stellate_service_name}.stellate.sh/log",
81
+ 'headers' => {
75
82
  'Content-Type' => 'application/json',
76
83
  'Stellate-Logging-Token' => @stellate_token
77
- )
78
- puts "Failed to log metrics to Stellate: #{res.body}" if res.code.to_i >= 300
79
- rescue StandardError => e
80
- puts "Failed to log metrics to Stellate: #{e}"
84
+ },
85
+ 'body' => payload.to_json
86
+ }
87
+
88
+ callback = kwargs[:callback]
89
+ # The former check handles methods, the latter handles lambdas
90
+ if callback.is_a?(Method) || callback.respond_to?(:call)
91
+ callback.call(stellate_request)
92
+ # This handles symbols that contain methods
93
+ elsif callback.is_a?(Symbol) && method(callback).is_a?(Method)
94
+ method(callback).call(stellate_request)
95
+ else
96
+ run_stellate_request(stellate_request)
81
97
  end
82
98
 
83
99
  result
@@ -95,7 +111,15 @@ module Stellate
95
111
  # Use this plugin in your GraphQL::Schema to automatically sync your GraphQL
96
112
  # schema with your Stellate service.
97
113
  class SchemaSyncing
98
- def self.use(schema)
114
+ # The first argument is the GraphQLSchema class that this plugin is used
115
+ # on. It accepts the following names arguments:
116
+ # - `callback` (`Method`): If passed, this will be called with a lambda as
117
+ # argument. Calling the passed lambda will sync the schema to Stellate
118
+ # via HTTP. This is useful if you want to move this request into a non-
119
+ # blocking process (e.g. using Sidekiq) rather than the default behavior
120
+ # of performing a blocking HTTP request which can increase overall
121
+ # response times of your API.
122
+ def self.use(schema, **kwargs)
99
123
  unless schema.stellate_service_name.is_a?(String)
100
124
  puts 'Missing service name in order to sync schema to Stellate'
101
125
  return
@@ -108,20 +132,44 @@ module Stellate
108
132
 
109
133
  introspection = JSON.parse(schema.to_json)['data']
110
134
 
111
- # TODO: make this an async request to avoid blocking the request
112
- begin
113
- res = Net::HTTP.post(
114
- URI("https://#{schema.stellate_service_name}.stellate.sh/schema"),
115
- { schema: introspection }.to_json,
135
+ stellate_request = {
136
+ 'url' => "https://#{schema.stellate_service_name}.stellate.sh/schema",
137
+ 'headers' => {
116
138
  'Content-Type' => 'application/json',
117
139
  'Stellate-Schema-Token' => schema.stellate_token
118
- )
119
- puts "Failed to sync schema to Stellate: #{res.body}" if res.code.to_i >= 300
120
- rescue StandardError => e
121
- puts "Failed to sync schema to Stellate: #{e}"
140
+ },
141
+ 'body' => { schema: introspection }.to_json
142
+ }
143
+
144
+ callback = kwargs[:callback]
145
+ # The former check handles methods, the latter handles lambdas
146
+ if callback.is_a?(Method) || callback.respond_to?(:call)
147
+ callback.call(stellate_request)
148
+ # This handles symbols that contain methods
149
+ elsif callback.is_a?(Symbol) && method(callback).is_a?(Method)
150
+ method(callback).call(stellate_request)
151
+ else
152
+ run_stellate_request(stellate_request)
122
153
  end
123
154
  end
124
155
  end
156
+
157
+ def self.run_stellate_request(stellate_request)
158
+ url = URI.parse(stellate_request['url'])
159
+
160
+ http = Net::HTTP.new(url.host, url.port)
161
+ http.use_ssl = true
162
+
163
+ req = Net::HTTP::Post.new(url)
164
+ stellate_request['headers'].each do |key, value|
165
+ req[key] = value
166
+ end
167
+ req.body = stellate_request['body']
168
+ res = http.request(req)
169
+ puts "HTTP request to Stellate failed: #{res.body}" if res.code.to_i >= 300
170
+ rescue StandardError => e
171
+ puts "HTTP request to Stellate failed: #{e}"
172
+ end
125
173
  end
126
174
 
127
175
  def create_blake3_hash(str)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stellate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stellate
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-13 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-http