type_fusion 0.0.3 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7fd6c97b4b4bb6eeecea4ff23e108c24a7564ac3d85e2231352824cd27bf160e
4
- data.tar.gz: a438ca7330e335d8d1922c967a24ef46a23403d6825e0e7a4740aafa6e93dcf6
3
+ metadata.gz: 7eaa132f18093b5b57b9db4e49130adb2f9ff41ae03559848e1334ee4f863bfe
4
+ data.tar.gz: 4bc9dcc31808f3f39707516436f28a3e73de19054f80c2d143da66dc365ae106
5
5
  SHA512:
6
- metadata.gz: 48d5ea9c6b6c52e8fe44bd8b1ea295f96ff5e48e737985b7c75d21b5c8379d2934b8dfe6e0fa41acfc85aa4104427a7e86354ebed07823d81e37c85a5060d7e3
7
- data.tar.gz: 54d0eae75e1b154a249ddf5eecf6facf7694d3fc43d0ea3e3c022e7225a0510f7e2d58758fbbba885f6b45c16f35236653054e3e1d9ea199b6dfb16696b88fa3
6
+ metadata.gz: '086356eb24932d3fbce347967869de8ba31672ebde52eaed096a640713ca8cb69e151ebe2a6dd71ebdb596a07cd6ea971bcf7f0147887059a344901d08e2be90'
7
+ data.tar.gz: 35dbb641e2ffc414aa0c42af6f2a61538f3a24f37e5bd35daf623bc7824b853fe8963711c10fd741e2e6155be6b73cf26fd7718f530b36e238c912f2ce372f7b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.0.4] - 2023-08-16
4
+
5
+ - Implement sample collection by sending samples to gem.sh endpoint
6
+ - Introduce Litejob to enqueue samples to be collected async
7
+ - Updates to `SampleCall`
8
+ - Split up `gem_and_version` to `gem` and `version` in `SampleCall`
9
+ - Also collect `application_name` and `type_fusion_version` with `SampleCall`
10
+ - Change `Tracepoint` API from `:call` to `:return` to also collect `return_value` in `SampleCall`
11
+ - Introduce `endpoint` and `application_name` configs
12
+
3
13
  ## [0.0.3] - 2023-08-13
4
14
 
5
15
  - Introduce `TypeFusion::Middleware` to allow type-sampling in Rack-powered apps
data/Gemfile CHANGED
@@ -6,6 +6,4 @@ gemspec
6
6
 
7
7
  gem "minitest", "~> 5.0"
8
8
  gem "rake", "~> 13.0"
9
- gem "rubocop", "~> 1.21"
10
-
11
- gem "litestack", github: "marcoroth/litestack"
9
+ gem "rubocop", "~> 1.56"
data/Gemfile.lock CHANGED
@@ -1,54 +1,69 @@
1
- GIT
2
- remote: https://github.com/marcoroth/litestack.git
3
- revision: 1911d5ef35f474425fb4e17a11a7d40deb4008a8
4
- specs:
5
- litestack (0.2.6)
6
- erubi
7
- hanami-router
8
- oj
9
- rack
10
- sqlite3
11
- tilt
12
-
13
1
  PATH
14
2
  remote: .
15
3
  specs:
16
- type_fusion (0.0.3)
17
- litestack
4
+ type_fusion (0.0.4)
5
+ lhc (~> 15.2)
6
+ litejob (~> 0.2.3)
18
7
 
19
8
  GEM
20
9
  remote: https://rubygems.org/
21
10
  specs:
11
+ activesupport (7.0.7)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 1.6, < 2)
14
+ minitest (>= 5.1)
15
+ tzinfo (~> 2.0)
16
+ addressable (2.8.5)
17
+ public_suffix (>= 2.0.2, < 6.0)
22
18
  ast (2.4.2)
23
- erubi (1.12.0)
24
- hanami-router (0.6.2)
25
- hanami-utils (~> 0.7)
26
- http_router (~> 0.11)
27
- hanami-utils (0.9.2)
28
- http_router (0.11.2)
29
- rack (>= 1.0.0)
30
- url_mount (~> 0.2.1)
19
+ base64 (0.1.1)
20
+ concurrent-ruby (1.2.2)
21
+ ethon (0.16.0)
22
+ ffi (>= 1.15.0)
23
+ ffi (1.15.5)
24
+ i18n (1.14.1)
25
+ concurrent-ruby (~> 1.0)
31
26
  json (2.6.3)
27
+ language_server-protocol (3.17.0.3)
28
+ lhc (15.2.1)
29
+ activesupport (>= 5.2)
30
+ addressable
31
+ local_uri
32
+ typhoeus (>= 0.11)
33
+ litedb (0.2.1)
34
+ litescheduler (>= 0.2.0)
35
+ sqlite3 (>= 1.5.0)
36
+ litejob (0.2.3)
37
+ litequeue (>= 0.2.1)
38
+ litescheduler (>= 0.2.1)
39
+ litequeue (0.2.1)
40
+ litedb (>= 0.2.1)
41
+ litescheduler (0.2.1)
42
+ local_uri (1.2.0)
43
+ activesupport
44
+ rack
32
45
  minitest (5.19.0)
33
- oj (3.15.1)
34
46
  parallel (1.23.0)
35
47
  parser (3.2.2.3)
36
48
  ast (~> 2.4.1)
37
49
  racc
50
+ public_suffix (5.0.3)
38
51
  racc (1.7.1)
39
52
  rack (3.0.8)
40
53
  rainbow (3.1.1)
41
54
  rake (13.0.6)
42
55
  regexp_parser (2.8.1)
43
56
  rexml (3.2.6)
44
- rubocop (1.48.1)
57
+ rubocop (1.56.0)
58
+ base64 (~> 0.1.1)
45
59
  json (~> 2.3)
60
+ language_server-protocol (>= 3.17.0)
46
61
  parallel (~> 1.10)
47
- parser (>= 3.2.0.0)
62
+ parser (>= 3.2.2.3)
48
63
  rainbow (>= 2.2.2, < 4.0)
49
64
  regexp_parser (>= 1.8, < 3.0)
50
65
  rexml (>= 3.2.5, < 4.0)
51
- rubocop-ast (>= 1.26.0, < 2.0)
66
+ rubocop-ast (>= 1.28.1, < 2.0)
52
67
  ruby-progressbar (~> 1.7)
53
68
  unicode-display_width (>= 2.4.0, < 3.0)
54
69
  rubocop-ast (1.29.0)
@@ -56,20 +71,20 @@ GEM
56
71
  ruby-progressbar (1.13.0)
57
72
  sqlite3 (1.6.3-x86_64-darwin)
58
73
  sqlite3 (1.6.3-x86_64-linux)
59
- tilt (2.2.0)
74
+ typhoeus (1.4.0)
75
+ ethon (>= 0.9.0)
76
+ tzinfo (2.0.6)
77
+ concurrent-ruby (~> 1.0)
60
78
  unicode-display_width (2.4.2)
61
- url_mount (0.2.1)
62
- rack
63
79
 
64
80
  PLATFORMS
65
81
  x86_64-darwin-22
66
82
  x86_64-linux
67
83
 
68
84
  DEPENDENCIES
69
- litestack!
70
85
  minitest (~> 5.0)
71
86
  rake (~> 13.0)
72
- rubocop (~> 1.21)
87
+ rubocop (~> 1.56)
73
88
  type_fusion!
74
89
 
75
90
  BUNDLED WITH
data/README.md CHANGED
@@ -38,6 +38,27 @@ require "type_fusion"
38
38
 
39
39
  TypeFusion.config do |config|
40
40
 
41
+ # === application_name
42
+ #
43
+ # Set application_name to a string which is used to know where the samples
44
+ # came from. Set application_name to an empty string if you wish to not
45
+ # send the application name alongside the samples.
46
+ #
47
+ # Default: "TypeFusion"
48
+ # Default when using Rails: Rails.application.class.module_parent_name
49
+ #
50
+ # config.application_name = "YourApplication"
51
+
52
+
53
+ # === endpoint
54
+ #
55
+ # Set endpoint to an URL where TypeFusion should send the samples to.
56
+ #
57
+ # Default: "https://gem.sh/api/v1/types/samples"
58
+ #
59
+ # config.endpoint = "https://your-domain.com/api/v1/types/samples"
60
+
61
+
41
62
  # === type_sample_request
42
63
  #
43
64
  # Set type_sample_request to a lambda which resolves to true/false
@@ -54,13 +75,16 @@ TypeFusion.config do |config|
54
75
  # to true/false to check if a tracepoint_path should be sampled
55
76
  # or not.
56
77
  #
57
- # This can be useful when you only want to sample method calls for
78
+ # This can be useful when you want to only sample method calls for
58
79
  # certain gems or want to exclude a gem from being sampled.
59
80
  #
60
81
  # Example:
61
82
  # config.type_sample_tracepoint_path = ->(tracepoint_path) {
62
- # # only sample calls for the Nokogiri gem
63
- # tracepoint_path.include?("nokogiri")
83
+ # return false if tracepoint_path.include?("activerecord")
84
+ # return false if tracepoint_path.include?("sprockets")
85
+ # return false if tracepoint_path.include?("some-private-gem")
86
+ #
87
+ # true
64
88
  # }
65
89
  #
66
90
  # Default: ->(tracepoint_path) { true }
@@ -11,17 +11,20 @@ module TypeFusion
11
11
 
12
12
  @config
13
13
  end
14
+ alias configure config
14
15
  end
15
16
 
16
17
  class Config
17
18
  include Singleton
18
19
 
19
- attr_accessor :type_sample_call_rate, :type_sample_request, :type_sample_tracepoint_path
20
+ attr_accessor :type_sample_call_rate, :type_sample_request, :type_sample_tracepoint_path, :endpoint, :application_name
20
21
 
21
22
  def initialize
22
23
  @type_sample_call_rate = 0.001
23
24
  @type_sample_request = ->(_env) { [true, false, false, false].sample }
24
25
  @type_sample_tracepoint_path = ->(_tracepoint_path) { true }
26
+ @endpoint = "http://localhost:3000/api/v1/types/samples"
27
+ @application_name = "TypeFusion"
25
28
  end
26
29
 
27
30
  def type_sample_request?(env)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "litejob"
4
+
5
+ # Litequeue.configure do |config|
6
+ # config.path = "db/type_fusion/queue.sqlite3"
7
+ # end
@@ -5,6 +5,8 @@ module TypeFusion
5
5
  initializer "type_fusion.middleware" do |app|
6
6
  require "type_fusion/rack/middleware"
7
7
 
8
+ TypeFusion.config.application_name = app.class.module_parent_name
9
+
8
10
  app.config.middleware.use TypeFusion::Middleware
9
11
  end
10
12
  end
@@ -3,9 +3,13 @@
3
3
  require "json"
4
4
 
5
5
  module TypeFusion
6
- SampleCall = Struct.new(:gem_and_version, :receiver, :method_name, :location, :parameters) do
6
+ SampleCall = Struct.new(:gem_name, :gem_version, :receiver, :method_name, :application_name, :location, :type_fusion_version, :parameters, :return_value) do
7
7
  def to_s
8
8
  JSON.pretty_generate(to_h)
9
9
  end
10
+
11
+ def inspect
12
+ "#<TypeFusion::SampleCall receiver=#{receiver.inspect} method_name=#{method_name.inspect} gem_name=#{gem_name.inspect}>"
13
+ end
10
14
  end
11
15
  end
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "litestack"
3
+ require "lhc"
4
4
 
5
5
  module TypeFusion
6
6
  class SampleJob
7
7
  include Litejob
8
8
 
9
- self.queue = :default
9
+ queue_as :default
10
10
 
11
11
  def perform(sample)
12
- puts sample.inspect
12
+ LHC.json.post(TypeFusion.config.endpoint, body: { sample: JSON.parse(sample) })
13
+ rescue StandardError => e
14
+ puts e.inspect
13
15
  end
14
16
  end
15
17
  end
@@ -10,6 +10,7 @@ module TypeFusion
10
10
 
11
11
  def initialize
12
12
  @samples = []
13
+ @litejob_server ||= Litejob::Server.new([["default", 1]])
13
14
  end
14
15
 
15
16
  def with_sampling
@@ -21,7 +22,7 @@ module TypeFusion
21
22
  end
22
23
 
23
24
  def trace
24
- @trace ||= TracePoint.trace(:call) do |tracepoint|
25
+ @trace ||= TracePoint.trace(:return) do |tracepoint|
25
26
  if sample?(tracepoint.path)
26
27
  receiver = begin
27
28
  tracepoint.binding.receiver.name
@@ -30,17 +31,23 @@ module TypeFusion
30
31
  end
31
32
 
32
33
  method_name = tracepoint.method_id
33
- location = tracepoint.binding.source_location
34
- gem_and_version = location.first.gsub(gem_path, "").split("/").first
35
- args = tracepoint.parameters.map(&:reverse).to_h
34
+ location = tracepoint.binding.source_location.join(":")
35
+ gem_and_version = location.gsub(gem_path, "").split("/").first
36
+ gem, version = gem_and_version_from(gem_and_version)
37
+ args = tracepoint.parameters.to_h(&:reverse)
36
38
  parameters = extract_parameters(args, tracepoint.binding)
39
+ return_value = type_for_object(tracepoint.return_value)
37
40
 
38
41
  sample = SampleCall.new(
39
- gem_and_version: gem_and_version,
42
+ gem_name: gem,
43
+ gem_version: version,
40
44
  receiver: receiver,
41
45
  method_name: method_name,
42
46
  location: location,
47
+ type_fusion_version: VERSION,
43
48
  parameters: parameters,
49
+ application_name: TypeFusion.config.application_name,
50
+ return_value: return_value,
44
51
  )
45
52
 
46
53
  samples << sample
@@ -81,6 +88,31 @@ module TypeFusion
81
88
  end
82
89
  end
83
90
 
91
+ def gem_and_version_from(gem_and_version)
92
+ return [] if gem_and_version.nil?
93
+
94
+ splits = gem_and_version.split("-")
95
+
96
+ if splits.length == 1
97
+ [splits.first, nil]
98
+ elsif splits.length == 2
99
+ splits
100
+ else
101
+ *name, version = splits
102
+
103
+ # TODO: there must be a better way to do this
104
+ if ["darwin", "java", "linux", "ucrt", "mingw32"].include?(version)
105
+ amount = (version == "ucrt") ? 3 : 2
106
+
107
+ version = [*name.pop(amount), version].join("-")
108
+ end
109
+
110
+ gem = name.join("-")
111
+
112
+ [gem, version]
113
+ end
114
+ end
115
+
84
116
  def extract_parameters(args, binding)
85
117
  args.map do |name, kind|
86
118
  variable = name.to_s.gsub("*", "").gsub("&", "").to_sym
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TypeFusion
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
data/lib/type_fusion.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "type_fusion/version"
4
4
  require_relative "type_fusion/config"
5
+ require_relative "type_fusion/litejob"
5
6
  require_relative "type_fusion/sample_call"
6
7
  require_relative "type_fusion/sample_job"
7
8
  require_relative "type_fusion/sampler"
data/test.rb CHANGED
@@ -16,4 +16,4 @@ TypeFusion.with_sampling do
16
16
  end
17
17
 
18
18
  puts TypeFusion::Sampler.instance.samples
19
- puts TypeFusion::Sampler.instance.to_s
19
+ puts TypeFusion::Sampler.instance
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: type_fusion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Roth
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-13 00:00:00.000000000 Z
11
+ date: 2023-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: litestack
14
+ name: lhc
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '15.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '15.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: litejob
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.3
27
41
  description: Community-contributed sample data for Ruby types
28
42
  email:
29
43
  - marco.roth@intergga.ch
@@ -41,6 +55,7 @@ files:
41
55
  - Rakefile
42
56
  - lib/type_fusion.rb
43
57
  - lib/type_fusion/config.rb
58
+ - lib/type_fusion/litejob.rb
44
59
  - lib/type_fusion/rack/middleware.rb
45
60
  - lib/type_fusion/rails/railtie.rb
46
61
  - lib/type_fusion/sample_call.rb