graphql-hive 0.4.2 → 0.5.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.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql-hive/sampling/sampling_context'
3
+ require "graphql-hive/sampling/sampling_context"
4
4
 
5
5
  module GraphQL
6
6
  class Hive
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql-hive/sampling/sampling_context'
3
+ require "graphql-hive/sampling/sampling_context"
4
4
 
5
5
  module GraphQL
6
6
  class Hive
@@ -16,7 +16,7 @@ module GraphQL
16
16
  def get_sample_context(operation)
17
17
  _, queries, results, = operation
18
18
 
19
- operation_name = queries.map(&:operations).map(&:keys).flatten.compact.join(', ')
19
+ operation_name = queries.map(&:operations).map(&:keys).flatten.compact.join(", ")
20
20
 
21
21
  parsed_definitions = []
22
22
  queries.each do |query|
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'digest'
4
- require 'graphql-hive/analyzer'
5
- require 'graphql-hive/printer'
3
+ require "digest"
4
+ require "graphql-hive/analyzer"
5
+ require "graphql-hive/printer"
6
6
 
7
7
  module GraphQL
8
8
  class Hive < GraphQL::Tracing::PlatformTracing
@@ -16,20 +16,19 @@ module GraphQL
16
16
 
17
17
  def initialize(options, client)
18
18
  @@instance = self
19
-
20
19
  @options = options
21
20
  @client = client
22
-
23
21
  @options_mutex = Mutex.new
24
- @queue = Queue.new
25
-
26
22
  @sampler = Sampler.new(options[:collect_usage_sampling], options[:logger]) # NOTE: logs for deprecated field
23
+ @queue = Thread::SizedQueue.new(options[:queue_size])
27
24
 
28
25
  start_thread
29
26
  end
30
27
 
31
28
  def add_operation(operation)
32
- @queue.push(operation)
29
+ @queue.push(operation, true)
30
+ rescue ThreadError
31
+ @options[:logger].error("SizedQueue is full, discarding operation. Size: #{@queue.size}, Max: #{@queue.max}")
33
32
  end
34
33
 
35
34
  def on_exit
@@ -45,30 +44,35 @@ module GraphQL
45
44
 
46
45
  def start_thread
47
46
  if @thread&.alive?
48
- @options[:logger].warn('Tried to start operations flushing thread but it was already alive')
47
+ @options[:logger].warn("Tried to start operations flushing thread but it was already alive")
49
48
  return
50
49
  end
51
50
 
52
51
  @thread = Thread.new do
53
52
  buffer = []
54
53
  while (operation = @queue.pop(false))
55
- @options[:logger].debug("processing operation from queue: #{operation}")
56
- buffer << operation if @sampler.sample?(operation)
57
-
58
- @options_mutex.synchronize do
59
- if buffer.size >= @options[:buffer_size]
60
- @options[:logger].debug('buffer is full, sending!')
61
- process_operations(buffer)
62
- buffer = []
54
+ begin
55
+ @options[:logger].debug("processing operation from queue: #{operation}")
56
+ buffer << operation if @sampler.sample?(operation)
57
+
58
+ @options_mutex.synchronize do
59
+ if buffer.size >= @options[:buffer_size]
60
+ @options[:logger].debug("buffer is full, sending!")
61
+ process_operations(buffer)
62
+ buffer = []
63
+ end
63
64
  end
65
+ rescue => e
66
+ buffer = []
67
+ @options[:logger].error(e)
64
68
  end
65
69
  end
66
70
 
67
71
  unless buffer.empty?
68
- @options[:logger].debug('shuting down with buffer, sending!')
72
+ @options[:logger].debug("shuting down with buffer, sending!")
69
73
  process_operations(buffer)
70
74
  end
71
- rescue StandardError => e
75
+ rescue => e
72
76
  # ensure configured logger receives exception as well in setups where STDERR might not be
73
77
  # monitored.
74
78
  @options[:logger].error(e)
@@ -88,7 +92,7 @@ module GraphQL
88
92
 
89
93
  @options[:logger].debug("sending report: #{report}")
90
94
 
91
- @client.send('/usage', report, :usage)
95
+ @client.send(:"/usage", report, :usage)
92
96
  end
93
97
 
94
98
  def add_operation_to_report(report, operation)
@@ -96,8 +100,8 @@ module GraphQL
96
100
 
97
101
  errors = errors_from_results(results)
98
102
 
99
- operation_name = queries.map(&:operations).map(&:keys).flatten.compact.join(', ')
100
- operation = ''
103
+ operation_name = queries.map(&:operations).map(&:keys).flatten.compact.join(", ")
104
+ operation = ""
101
105
  fields = Set.new
102
106
 
103
107
  queries.each do |query|
@@ -131,7 +135,7 @@ module GraphQL
131
135
 
132
136
  if results[0]
133
137
  context = results[0].query.context
134
- operation_record[:metadata] = { client: @options[:client_info].call(context) } if @options[:client_info]
138
+ operation_record[:metadata] = {client: @options[:client_info].call(context)} if @options[:client_info]
135
139
  end
136
140
 
137
141
  report[:map][operation_map_key] = {
@@ -144,9 +148,9 @@ module GraphQL
144
148
  end
145
149
 
146
150
  def errors_from_results(results)
147
- acc = { errorsTotal: 0 }
151
+ acc = {errorsTotal: 0}
148
152
  results.each do |result|
149
- errors = result.to_h.fetch('errors', [])
153
+ errors = result.to_h.fetch("errors", [])
150
154
  errors.each do
151
155
  acc[:errorsTotal] += 1
152
156
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Graphql
4
4
  module Hive
5
- VERSION = '0.4.2'
5
+ VERSION = "0.5.1"
6
6
  end
7
7
  end
data/lib/graphql-hive.rb CHANGED
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'logger'
4
- require 'securerandom'
3
+ require "logger"
4
+ require "securerandom"
5
5
 
6
- require 'graphql-hive/version'
7
- require 'graphql-hive/usage_reporter'
8
- require 'graphql-hive/client'
6
+ require "graphql-hive/version"
7
+ require "graphql-hive/usage_reporter"
8
+ require "graphql-hive/client"
9
9
 
10
- require 'graphql-hive/sampler'
11
- require 'graphql-hive/sampling/basic_sampler'
12
- require 'graphql-hive/sampling/dynamic_sampler'
10
+ require "graphql-hive/sampler"
11
+ require "graphql-hive/sampling/basic_sampler"
12
+ require "graphql-hive/sampling/dynamic_sampler"
13
+ require "graphql"
13
14
 
14
15
  module GraphQL
15
16
  # GraphQL Hive usage collector and schema reporter
@@ -31,24 +32,25 @@ module GraphQL
31
32
  DEFAULT_OPTIONS = {
32
33
  enabled: true,
33
34
  debug: false,
34
- port: '443',
35
+ port: "443",
35
36
  collect_usage: true,
36
37
  read_operations: true,
37
38
  report_schema: true,
38
39
  buffer_size: 50,
40
+ queue_size: 1000,
39
41
  logger: nil,
40
42
  collect_usage_sampling: 1.0
41
43
  }.freeze
42
44
 
43
45
  self.platform_keys = {
44
- 'lex' => 'lex',
45
- 'parse' => 'parse',
46
- 'validate' => 'validate',
47
- 'analyze_query' => 'analyze_query',
48
- 'analyze_multiplex' => 'analyze_multiplex',
49
- 'execute_multiplex' => 'execute_multiplex',
50
- 'execute_query' => 'execute_query',
51
- 'execute_query_lazy' => 'execute_query_lazy'
46
+ "lex" => "lex",
47
+ "parse" => "parse",
48
+ "validate" => "validate",
49
+ "analyze_query" => "analyze_query",
50
+ "analyze_multiplex" => "analyze_multiplex",
51
+ "execute_multiplex" => "execute_multiplex",
52
+ "execute_query" => "execute_query",
53
+ "execute_query_lazy" => "execute_query_lazy"
52
54
  }
53
55
 
54
56
  def initialize(options = {})
@@ -84,7 +86,7 @@ module GraphQL
84
86
  def platform_trace(platform_key, _key, data)
85
87
  return yield unless @options[:enabled] && @options[:collect_usage]
86
88
 
87
- if platform_key == 'execute_multiplex'
89
+ if platform_key == "execute_multiplex"
88
90
  if data[:multiplex]
89
91
  queries = data[:multiplex].queries
90
92
  timestamp = (Time.now.utc.to_f * 1000).to_i
@@ -134,25 +136,26 @@ module GraphQL
134
136
  options[:logger] = Logger.new($stderr)
135
137
  original_formatter = Logger::Formatter.new
136
138
  options[:logger].formatter = proc { |severity, datetime, progname, msg|
137
- original_formatter.call(severity, datetime, progname, "[hive] #{msg.dump}")
139
+ msg = msg.respond_to?(:dump) ? msg.dump : msg
140
+ original_formatter.call(severity, datetime, progname, "[hive] #{msg}")
138
141
  }
139
142
  options[:logger].level = options[:debug] ? Logger::DEBUG : Logger::INFO
140
143
  end
141
144
  if !options.include?(:token) && (!options.include?(:enabled) || options.enabled)
142
- options[:logger].warn('`token` options is missing')
145
+ options[:logger].warn("`token` options is missing")
143
146
  options[:enabled] = false
144
147
  false
145
148
  elsif options[:report_schema] &&
149
+ (
150
+ !options.include?(:reporting) ||
146
151
  (
147
- !options.include?(:reporting) ||
148
- (
149
- options.include?(:reporting) && (
150
- !options[:reporting].include?(:author) || !options[:reporting].include?(:commit)
151
- )
152
+ options.include?(:reporting) && (
153
+ !options[:reporting].include?(:author) || !options[:reporting].include?(:commit)
152
154
  )
153
155
  )
156
+ )
154
157
 
155
- options[:logger].warn('`reporting.author` and `reporting.commit` options are required')
158
+ options[:logger].warn("`reporting.author` and `reporting.commit` options are required")
156
159
  false
157
160
  end
158
161
  true
@@ -167,7 +170,7 @@ module GraphQL
167
170
 
168
171
  body = {
169
172
  query: REPORT_SCHEMA_MUTATION,
170
- operationName: 'schemaPublish',
173
+ operationName: "schemaPublish",
171
174
  variables: {
172
175
  input: {
173
176
  sdl: sdl,
@@ -180,7 +183,7 @@ module GraphQL
180
183
  }
181
184
  }
182
185
 
183
- @client.send('/registry', body, :'report-schema')
186
+ @client.send(:"/registry", body, :"report-schema")
184
187
  end
185
188
  end
186
189
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-hive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charly POLY
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-04 00:00:00.000000000 Z
11
+ date: 2024-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -30,62 +30,6 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3'
33
- - !ruby/object:Gem::Dependency
34
- name: bundler
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2'
40
- type: :development
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '2'
47
- - !ruby/object:Gem::Dependency
48
- name: rake
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '13'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '13'
61
- - !ruby/object:Gem::Dependency
62
- name: rspec
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '3'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '3'
75
- - !ruby/object:Gem::Dependency
76
- name: rubocop
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '1'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '1'
89
33
  description: '"Monitor operations, inspect your queries and publish your GraphQL schema
90
34
  with GraphQL Hive"'
91
35
  email:
@@ -94,11 +38,11 @@ executables: []
94
38
  extensions: []
95
39
  extra_rdoc_files: []
96
40
  files:
97
- - ".github/workflows/benchmark.yml"
98
41
  - ".github/workflows/ci.yml"
99
42
  - ".gitignore"
100
43
  - ".rspec"
101
44
  - ".rubocop.yml"
45
+ - ".ruby-version"
102
46
  - Gemfile
103
47
  - Gemfile.lock
104
48
  - LICENSE
@@ -106,21 +50,7 @@ files:
106
50
  - RELEASING.md
107
51
  - Rakefile
108
52
  - cover.png
109
- - examples/simple-api/Gemfile
110
- - examples/simple-api/Gemfile.lock
111
- - examples/simple-api/app.rb
112
- - examples/simple-api/config.ru
113
- - examples/simple-api/schema.rb
114
53
  - graphql-hive.gemspec
115
- - k6/graphql-api/Gemfile
116
- - k6/graphql-api/Gemfile.lock
117
- - k6/graphql-api/app.rb
118
- - k6/graphql-api/config.ru
119
- - k6/graphql-api/schema.rb
120
- - k6/k6.js
121
- - k6/package.json
122
- - k6/usage-api.js
123
- - k6/yarn.lock
124
54
  - lib/graphql-hive.rb
125
55
  - lib/graphql-hive/analyzer.rb
126
56
  - lib/graphql-hive/client.rb
@@ -1,67 +0,0 @@
1
- name: Benchmark
2
- on:
3
- pull_request:
4
- branches:
5
- - master
6
-
7
- jobs:
8
- benchmarks:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - name: Checkout Repository
12
- uses: actions/checkout@v4
13
-
14
- - name: Use Node
15
- uses: actions/setup-node@v4
16
- with:
17
- node-version: 22
18
- cache: 'yarn'
19
- cache-dependency-path: 'k6/yarn.lock'
20
-
21
- - name: Use Ruby
22
- uses: ruby/setup-ruby@2a9a743e19810b9f3c38060637daf594dbd7b37f
23
- with:
24
- working-directory: ./k6/graphql-api
25
- ruby-version: '3.3'
26
- bundler-cache: true
27
-
28
- - name: Start GraphQL API with hive enabled
29
- working-directory: ./k6/graphql-api
30
- run: |
31
- bundle
32
- bundle exec puma -t 0:1 -p 9292 &
33
- npx wait-on http://localhost:9292 --timeout 5s
34
- env:
35
- HIVE_ENABLED: 'true'
36
-
37
- - name: Start GraphQL API with hive disabled
38
- working-directory: ./k6/graphql-api
39
- run: |
40
- bundle
41
- bundle exec puma -t 0:1 -p 9291 &
42
- npx wait-on http://localhost:9291 --timeout 5s
43
- env:
44
- HIVE_ENABLED: 'false'
45
-
46
- - name: Start Fake Usage API
47
- working-directory: ./k6/
48
- run: |
49
- yarn
50
- node usage-api.js &
51
- npx wait-on http://localhost:8888 --timeout 5s
52
-
53
- - name: Install k6
54
- working-directory: ./k6
55
- env:
56
- K6_RELEASE_ARTIFACT_URL:
57
- https://github.com/grafana/k6/releases/download/v0.37.0/k6-v0.37.0-linux-amd64.tar.gz
58
- run: curl "${K6_RELEASE_ARTIFACT_URL}" -L | tar xvz --strip-components 1
59
-
60
- - name: Run Benchmark
61
- working-directory: ./k6
62
- run: |
63
- ./k6 \
64
- -e GITHUB_PR=${{ github.event.number }} \
65
- -e GITHUB_SHA=${{ github.sha }} \
66
- -e GITHUB_TOKEN=${{secrets.GH_PA_TOKEN}} \
67
- run k6.js
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'graphql'
4
- gem 'graphql-hive', path: '../../'
5
- gem 'puma'
6
- gem 'rack-contrib'
7
- gem 'sinatra'
8
- gem 'sinatra-contrib'
@@ -1,48 +0,0 @@
1
- PATH
2
- remote: ../..
3
- specs:
4
- graphql-hive (0.3.3)
5
- graphql (~> 2.0.9)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- graphql (2.0.9)
11
- multi_json (1.15.0)
12
- mustermann (1.1.1)
13
- ruby2_keywords (~> 0.0.1)
14
- nio4r (2.5.8)
15
- puma (5.6.4)
16
- nio4r (~> 2.0)
17
- rack (2.2.3.1)
18
- rack-contrib (2.3.0)
19
- rack (~> 2.0)
20
- rack-protection (2.2.0)
21
- rack
22
- ruby2_keywords (0.0.5)
23
- sinatra (2.2.0)
24
- mustermann (~> 1.0)
25
- rack (~> 2.2)
26
- rack-protection (= 2.2.0)
27
- tilt (~> 2.0)
28
- sinatra-contrib (2.2.0)
29
- multi_json
30
- mustermann (~> 1.0)
31
- rack-protection (= 2.2.0)
32
- sinatra (= 2.2.0)
33
- tilt (~> 2.0)
34
- tilt (2.0.10)
35
-
36
- PLATFORMS
37
- ruby
38
-
39
- DEPENDENCIES
40
- graphql
41
- graphql-hive!
42
- puma
43
- rack-contrib
44
- sinatra
45
- sinatra-contrib
46
-
47
- BUNDLED WITH
48
- 2.5.15
@@ -1,31 +0,0 @@
1
- require 'sinatra'
2
- require 'sinatra/json'
3
- require 'rack/contrib'
4
-
5
- require_relative 'schema'
6
-
7
- # Test query:
8
- #
9
- # query GetPost($input: [PostInput!]!) {
10
- # post(input: $input, test: TEST1) {
11
- # title
12
- # myId: id
13
- # }
14
- # }
15
-
16
- class DemoApp < Sinatra::Base
17
- use Rack::JSONBodyParser
18
-
19
- post '/graphql' do
20
- result = Schema.execute(
21
- params['query'],
22
- variables: params[:variables],
23
- operation_name: params[:operationName],
24
- context: {
25
- client_name: 'GraphQL Client',
26
- client_version: '1.0'
27
- }
28
- )
29
- json result
30
- end
31
- end
@@ -1,2 +0,0 @@
1
- require './app'
2
- run DemoApp
@@ -1,52 +0,0 @@
1
- require 'graphql'
2
- require 'graphql-hive'
3
-
4
- module Types
5
- class PostType < GraphQL::Schema::Object
6
- description 'A blog post'
7
- field :id, ID, null: false
8
- field :title, String, null: false
9
- # fields should be queried in camel-case (this will be `truncatedPreview`)
10
- field :truncated_preview, String, null: false
11
- end
12
- end
13
-
14
- class Types::PostInput < GraphQL::Schema::InputObject
15
- description 'Query Post arguments'
16
- argument :id, ID, required: true
17
- end
18
-
19
- class Types::TestEnum < GraphQL::Schema::Enum
20
- value 'TEST1'
21
- value 'TEST2'
22
- value 'TEST3'
23
- end
24
-
25
- class QueryType < GraphQL::Schema::Object
26
- description 'The query root of this schema'
27
-
28
- # First describe the field signature:
29
- field :post, Types::PostType, 'Find a post by ID' do
30
- argument :input, [Types::PostInput]
31
- argument :test, Types::TestEnum
32
- end
33
-
34
- # Then provide an implementation:
35
- def post(input:, test:)
36
- { id: 1, title: 'GraphQL Hive with `graphql-ruby`',
37
- truncated_preview: 'Monitor operations, inspect your queries and publish your GraphQL schema with GraphQL Hive' }
38
- end
39
- end
40
-
41
- class Schema < GraphQL::Schema
42
- query QueryType
43
-
44
- use(
45
- GraphQL::Hive,
46
- buffer_size: 2,
47
- token: 'YOUR_TOKEN',
48
- debug: true,
49
- reporting: { author: 'Charly Poly', commit: '109bb1e748bae21bdfe663c0ffc7e830' },
50
- client_info: proc { |context|{ name: context[:client_name], version: context[:client_version] }}
51
- )
52
- end
@@ -1,9 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'graphql', '~> 2'
4
- gem 'graphql-hive', path: '../../'
5
- gem 'puma', '~> 6'
6
- gem 'racc'
7
- gem 'rack-contrib', '~> 2'
8
- gem 'sinatra', '~> 2'
9
- gem 'sinatra-contrib'
@@ -1,52 +0,0 @@
1
- PATH
2
- remote: ../..
3
- specs:
4
- graphql-hive (0.4.2)
5
- graphql (>= 2.3, < 3)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- base64 (0.2.0)
11
- graphql (2.3.7)
12
- base64
13
- multi_json (1.15.0)
14
- mustermann (2.0.2)
15
- ruby2_keywords (~> 0.0.1)
16
- nio4r (2.7.3)
17
- puma (6.4.2)
18
- nio4r (~> 2.0)
19
- racc (1.8.0)
20
- rack (2.2.9)
21
- rack-contrib (2.5.0)
22
- rack (< 4)
23
- rack-protection (2.2.4)
24
- rack
25
- ruby2_keywords (0.0.5)
26
- sinatra (2.2.4)
27
- mustermann (~> 2.0)
28
- rack (~> 2.2)
29
- rack-protection (= 2.2.4)
30
- tilt (~> 2.0)
31
- sinatra-contrib (2.2.4)
32
- multi_json
33
- mustermann (~> 2.0)
34
- rack-protection (= 2.2.4)
35
- sinatra (= 2.2.4)
36
- tilt (~> 2.0)
37
- tilt (2.4.0)
38
-
39
- PLATFORMS
40
- ruby
41
-
42
- DEPENDENCIES
43
- graphql (~> 2)
44
- graphql-hive!
45
- puma (~> 6)
46
- racc
47
- rack-contrib (~> 2)
48
- sinatra (~> 2)
49
- sinatra-contrib
50
-
51
- BUNDLED WITH
52
- 2.5.15