stellate 0.0.1

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 +7 -0
  2. data/lib/stellate.rb +136 -0
  3. metadata +75 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: da10403f9f3b492a01b3235917a2f2b22d47f3bf76069814bbc71058f9ba5215
4
+ data.tar.gz: c35711a3b7d8190b33ab12d94430943aef000de2d1aa4a37ca0213e1e542195e
5
+ SHA512:
6
+ metadata.gz: 5e3d1fda26252c534a53384a6bb7cf614a30fb4805d07da6b0999a5ff1a9b2e7f3ca63b31f0c38d1a4235806154d0c3c9ac9bb2cee3e2a1147511444a5d658f2
7
+ data.tar.gz: a44b57f67ab67cff8f6f88f181449eccd4666de3c9344352b075a74c38bc2ce71ec5b0a6909106560abb441d6765b2c338f79167c2d13c8242d7ea5fe1666600
data/lib/stellate.rb ADDED
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+
6
+ module Stellate
7
+ VERSION = '0.0.1'
8
+
9
+ # Extend your GraphQL::Schema with this module to enable easy Stellate
10
+ # Metrics Logging.
11
+ #
12
+ # Add `extend Stellate::MetricsLogging` within your schema class. This will
13
+ # add the class method `execute_with_logging`. Then replace the call to
14
+ # `MySchema.execute()` with `MySchema.execute_with_logging()`.
15
+ module MetricsLogging
16
+ # Executes a given GraphQL query on the schema and logs details about the
17
+ # request and execution to Stellate. This function accepts the same
18
+ # arguments as `GraphQL::Schema.execute()`, and also the following:
19
+ # - `headers` (`ActionDispatch::Http::Headers`): The HTTP headers from the
20
+ # incoming request
21
+ def execute_with_logging(query_str = nil, **kwargs)
22
+ starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
23
+
24
+ result = execute(query_str, **kwargs.except(:service_name, :token, :headers))
25
+
26
+ ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
27
+ elapsed = (ending - starting) * 1000
28
+
29
+ unless @stellate_service_name.is_a?(String)
30
+ puts 'Missing service name in order to log metrics to Stellate'
31
+ return result
32
+ end
33
+
34
+ unless @stellate_token.is_a?(String)
35
+ puts 'Missing token in order to log metrics to Stellate'
36
+ return result
37
+ end
38
+
39
+ unless query_str.is_a?(String)
40
+ puts 'Cannot log metrics to Stellate without a query string'
41
+ return result
42
+ end
43
+
44
+ response = result.to_json
45
+ 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,
50
+ "responseSize": response.length,
51
+ "responseHash": create_blake3_hash(response),
52
+ "statusCode": 200,
53
+ "operationName": kwargs[:operation_name]
54
+ }
55
+
56
+ errors = result['errors']
57
+ payload[:errors] = errors if errors.is_a?(Array)
58
+
59
+ headers = kwargs[:headers]
60
+ if headers.is_a?(ActionDispatch::Http::Headers)
61
+ forwarded_for = headers['X-Forwarded-For']
62
+ ips = forwarded_for.is_a?(String) ? forwarded_for.split(',') : []
63
+
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
+
68
+ end
69
+
70
+ # TODO: make this an async request to avoid blocking the response
71
+ begin
72
+ Net::HTTP.post(
73
+ URI("https://#{@stellate_service_name}.stellate.sh/log"),
74
+ payload.to_json,
75
+ 'Content-Type' => 'application/json',
76
+ 'Stellate-Logging-Token' => @stellate_token
77
+ )
78
+ rescue StandardError => e
79
+ puts "Failed to log metrics to Stellate: #{e}"
80
+ end
81
+
82
+ result
83
+ end
84
+
85
+ def stellate_service_name
86
+ @stellate_service_name
87
+ end
88
+
89
+ def stellate_token
90
+ @stellate_token
91
+ end
92
+ end
93
+
94
+ # Use this plugin in your GraphQL::Schema to automatically sync your GraphQL
95
+ # schema with your Stellate service.
96
+ class SchemaSyncing
97
+ def self.use(schema)
98
+ unless schema.stellate_service_name.is_a?(String)
99
+ puts 'Missing service name in order to sync schema to Stellate'
100
+ return
101
+ end
102
+
103
+ unless schema.stellate_token.is_a?(String)
104
+ puts 'Missing token in order to log metrics to Stellate'
105
+ return
106
+ end
107
+
108
+ introspection = JSON.parse(schema.to_json)['data']
109
+
110
+ # TODO: make this an async request to avoid blocking the request
111
+ begin
112
+ Net::HTTP.post(
113
+ URI("https://#{schema.stellate_service_name}.stellate.sh/schema"),
114
+ { schema: introspection }.to_json,
115
+ 'Content-Type' => 'application/json',
116
+ 'Stellate-Schema-Token' => schema.stellate_token
117
+ )
118
+ rescue StandardError => e
119
+ puts "Failed to sync schema to Stellate: #{e}"
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ def create_blake3_hash(str)
126
+ val = 0
127
+
128
+ return val if str.empty?
129
+
130
+ str.each_byte do |code|
131
+ val = (val << 5) - val + code
132
+ val &= 0xffffffff # Int32
133
+ end
134
+
135
+ val >> 0 # uInt32
136
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stellate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Stellate
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-http
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: uri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.13.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.13.0
41
+ description: Add Stellate Metrics Logging and Schema Syncing to your GraphQL Ruby
42
+ API with a few lines of code
43
+ email: eng@stellate.co
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/stellate.rb
49
+ homepage: https://rubygems.org/gems/stellate
50
+ licenses:
51
+ - MIT
52
+ metadata:
53
+ bug_tracker_uri: https://github.com/StellateHQ/stellate-graphql-ruby/issues
54
+ homepage_uri: https://rubygems.org/gems/stellate
55
+ source_code_uri: https://github.com/StellateHQ/stellate-graphql-ruby
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.5.6
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Integrate Stellate with your GraphQL Ruby API
75
+ test_files: []