stellate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []