ruby-static-tracing 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ruby-static-tracing/darwin/provider.c +40 -52
  3. data/ext/ruby-static-tracing/darwin/provider.h +2 -3
  4. data/ext/ruby-static-tracing/darwin/ruby_static_tracing.c +4 -5
  5. data/ext/ruby-static-tracing/darwin/tracepoint.c +66 -91
  6. data/ext/ruby-static-tracing/darwin/tracepoint.h +4 -4
  7. data/ext/ruby-static-tracing/extconf.rb +40 -36
  8. data/ext/ruby-static-tracing/include/ruby_static_tracing.h +2 -1
  9. data/ext/ruby-static-tracing/lib/deps-extconf.rb +30 -28
  10. data/ext/ruby-static-tracing/lib/post-extconf.rb +23 -21
  11. data/ext/ruby-static-tracing/linux/provider.c +87 -61
  12. data/ext/ruby-static-tracing/linux/provider.h +16 -4
  13. data/ext/ruby-static-tracing/linux/ruby_static_tracing.c +7 -7
  14. data/ext/ruby-static-tracing/linux/tracepoint.c +86 -96
  15. data/ext/ruby-static-tracing/linux/tracepoint.h +2 -2
  16. data/ext/ruby-static-tracing/linux/types.h +2 -2
  17. data/lib/ruby-static-tracing.rb +11 -3
  18. data/lib/ruby-static-tracing/configuration.rb +11 -0
  19. data/lib/ruby-static-tracing/platform.rb +5 -1
  20. data/lib/ruby-static-tracing/provider.rb +50 -26
  21. data/lib/ruby-static-tracing/tracepoint.rb +19 -9
  22. data/lib/ruby-static-tracing/tracepoints.rb +2 -0
  23. data/lib/ruby-static-tracing/tracer/base.rb +2 -0
  24. data/lib/ruby-static-tracing/tracer/concerns/latency_tracer.rb +2 -0
  25. data/lib/ruby-static-tracing/tracer/helpers.rb +8 -8
  26. data/lib/ruby-static-tracing/tracer/latency.rb +1 -1
  27. data/lib/ruby-static-tracing/tracer/stack.rb +4 -2
  28. data/lib/ruby-static-tracing/tracers.rb +9 -0
  29. data/lib/ruby-static-tracing/version.rb +2 -1
  30. metadata +42 -14
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StaticTracing
4
+ # Platform detection for ruby-static-tracing
4
5
  module Platform
5
- extend self
6
+ module_function
6
7
 
8
+ # Returns true if platform is linux
7
9
  def linux?
8
10
  /linux/.match(RUBY_PLATFORM)
9
11
  end
10
12
 
13
+ # Returns true if platform is darwin
11
14
  def darwin?
12
15
  /darwin/.match(RUBY_PLATFORM)
13
16
  end
14
17
 
18
+ # Returns true if platform is known to be supported
15
19
  def supported_platform?
16
20
  linux? || darwin?
17
21
  end
@@ -1,77 +1,101 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StaticTracing
4
- class Provider #:nodoc:
4
+ # A wrapper for a USDT tracepoint provider
5
+ # This corresponds to a namespace of tracepoints
6
+ # By convention, we will often create one per
7
+ # class or module.
8
+ class Provider
5
9
  attr_accessor :name
10
+
11
+ # Provider couldn't be found in collection
6
12
  class ProviderNotFound < StandardError; end
7
13
 
8
14
  class << self
15
+ # Gets a provider by name
16
+ # or creates one if not exists
9
17
  def register(namespace)
10
18
  providers[namespace] ||= new(namespace)
11
19
  end
12
20
 
21
+ # Gets a provider instance by name
13
22
  def fetch(namespace)
14
23
  providers.fetch(namespace) do
15
24
  raise ProviderNotFound
16
25
  end
17
26
  end
18
27
 
28
+ # Enables each provider, ensuring
29
+ # it is loaded into memeory
19
30
  def enable!
20
- providers.values.each do |provider|
21
- provider.enable
22
- end
31
+ providers.values.each(&:enable)
23
32
  end
24
33
 
34
+ # Forcefully disables all providers,
35
+ # unloading them from memory
25
36
  def disable!
26
- providers.values.each do |provider|
27
- provider.disable
28
- end
37
+ providers.values.each(&:disable)
29
38
  end
30
39
 
31
40
  def clean
41
+ # FIXME: this should free first
32
42
  @providers = {}
33
43
  end
34
44
 
35
45
  private
36
46
 
47
+ # A global collection of providers
37
48
  def providers
38
49
  @providers ||= {}
39
50
  end
40
51
  end
41
52
 
42
- attr_reader :namespace
53
+ attr_reader :namespace, :tracepoints
43
54
 
44
- def initialize(namespace)
45
- if StaticTracing::Platform.supported_platform?
46
- provider_initialize(namespace)
47
- else
48
- StaticTracing.issue_disabled_tracepoints_warning
55
+ # Adds a new tracepoint to this provider
56
+ # FIXME - should this be a dictionary, or are duplicate names allowed?
57
+ def add_tracepoint(tracepoint, *args)
58
+ if tracepoint.is_a?(String)
59
+ tracepoint = Tracepoint.new(namespace, tracepoint, *args)
60
+ elsif tracepoint.is_a?(Tracepoint)
61
+ @tracepoints << tracepoint
49
62
  end
50
- @namespace = namespace
51
- end
52
-
53
- def add_tracepoint(method_name, *args)
54
- Tracepoint.new(namespace, method_name, *args)
63
+ tracepoint
55
64
  end
56
65
 
57
- # FIXME - how to store list of tracepoints on provider? Allocate map in C?
58
- # def tracepoints
59
- # []
60
- # end
66
+ # Enable the provider, loading it into memory
61
67
  def enable
68
+ @enabled = _enable_provider
62
69
  end
63
70
 
71
+ # Disables the provider, unloading it from memory
64
72
  def disable
73
+ @enabled = !_disable_provider
65
74
  end
66
75
 
67
- # FIXME add binding to check if enabled
76
+ # Returns true if the provider is enabled,
77
+ # meaning it is loaded into memory
68
78
  def enabled?
79
+ @enabled
69
80
  end
70
81
 
71
- def destroy
72
- end
82
+ # Only supported on systems (linux) where backed by file
83
+ def path; end
84
+
85
+ def destroy; end
86
+
87
+ private
73
88
 
74
- def provider_initialize(*)
89
+ # ALWAYS use register, never call .new dilectly
90
+ def initialize(namespace)
91
+ if StaticTracing::Platform.supported_platform?
92
+ provider_initialize(namespace)
93
+ @enabled = false
94
+ else
95
+ StaticTracing.issue_disabled_tracepoints_warning
96
+ end
97
+ @namespace = namespace
98
+ @tracepoints = []
75
99
  end
76
100
  end
77
101
  end
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StaticTracing
4
- class Tracepoint #:nodoc:
5
-
4
+ class Tracepoint
6
5
  class InvalidArgumentError < StandardError
7
6
  def initialize(argument, expected_type)
8
7
  error_message = <<~ERROR_MESSAGE
@@ -16,23 +15,29 @@ module StaticTracing
16
15
  end
17
16
  class InvalidArgType < StandardError; end
18
17
 
19
- VALID_ARGS_TYPES = [Integer, String]
18
+ VALID_ARGS_TYPES = [Integer, String].freeze
20
19
 
21
- attr_reader :provider, :name, :args
20
+ attr_reader :provider_name, :name, :args
22
21
 
23
- def initialize(provider, name, *args)
24
- @provider = provider
22
+ # Creates a new tracepoint.
23
+ # If a provider by the name specified doesn't exist already,
24
+ # one will be added implicitly.
25
+ def initialize(provider_name, name, *args)
26
+ @provider_name = provider_name
25
27
  @name = name
26
28
  validate_args(args)
27
29
  @args = args
28
30
 
29
31
  if StaticTracing::Platform.supported_platform?
30
- tracepoint_initialize(provider, name, args)
32
+ tracepoint_initialize(provider_name, name, args)
33
+ provider.add_tracepoint(self)
31
34
  else
32
35
  StaticTracing.issue_disabled_tracepoints_warning
33
36
  end
34
37
  end
35
38
 
39
+ # Fire a tracepoint, sending the data off to be received by
40
+ # a tracing program like dtrace
36
41
  def fire(*values)
37
42
  values.each_with_index do |arg, i|
38
43
  raise InvalidArgumentError.new(arg, args[i]) unless arg.is_a?(args[i])
@@ -40,13 +45,18 @@ module StaticTracing
40
45
  _fire_tracepoint(values)
41
46
  end
42
47
 
43
- def enabled?
48
+ def provider
49
+ Provider.fetch(@provider_name)
44
50
  end
45
51
 
52
+ # Returns true if a tracepoint is currently
53
+ # attached to, indicating we should fire it
54
+ def enabled?; end
55
+
46
56
  private
47
57
 
48
58
  def validate_args(values)
49
- raise InvalidArgType unless values.all? { |value| VALID_ARGS_TYPES.include?(value) }
59
+ raise InvalidArgType unless values.all? { |value| VALID_ARGS_TYPES.include?(value) }
50
60
  end
51
61
  end
52
62
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StaticTracing
4
+ # FIXME: - why do we need this class? We should store tracepoints
5
+ # on providers, and get the list of all tracepoints from the list of providers
4
6
  class Tracepoints
5
7
  class ProviderMissingError < StandardError; end
6
8
  class TracepointMissingError < StandardError; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'unmixer'
2
4
  using Unmixer
3
5
 
@@ -3,6 +3,8 @@
3
3
  module StaticTracing
4
4
  module Tracer
5
5
  module Concerns
6
+ # Including this module will cause the target
7
+ # to have latency tracers added around every method
6
8
  module Latency
7
9
  def self.included(base)
8
10
  methods = base.public_instance_methods(false)
@@ -1,17 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module StaticTracing
2
4
  module Tracer
3
5
  module Helpers
4
- extend self
6
+ module_function
5
7
 
6
8
  def underscore(class_name)
7
- class_name.gsub(/::/, '_').
8
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
9
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
10
- tr("-", "_").
11
- downcase
9
+ class_name.gsub(/::/, '_')
10
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
11
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
12
+ .tr('-', '_')
13
+ .downcase
12
14
  end
13
15
  end
14
16
  end
15
17
  end
16
-
17
-
@@ -3,7 +3,7 @@
3
3
  module StaticTracing
4
4
  module Tracer
5
5
  class Latency < Base
6
- set_wrapping_function -> (*args, &block) {
6
+ set_wrapping_function lambda { |*args, &block|
7
7
  start_time = StaticTracing.nsec
8
8
  result = super(*args, &block)
9
9
  duration = StaticTracing.nsec - start_time
@@ -2,9 +2,11 @@
2
2
 
3
3
  module StaticTracing
4
4
  module Tracer
5
+ # A stack tracer gets the stack trace at point when
6
+ # the tracer is executed
5
7
  class Stack < Base
6
- set_wrapping_function -> (*args, &block) {
7
- current_stack = self.send(:caller).join("\n")
8
+ set_wrapping_function lambda { |*args, &block|
9
+ current_stack = send(:caller).join("\n")
8
10
  method_name = __method__.to_s
9
11
  provider = Tracer::Helpers.underscore(self.class.name)
10
12
  Tracepoints.get(provider, method_name).fire(method_name, current_stack)
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StaticTracing
4
+ # Tracers are a layer of abstraction above tracepoints. They are opinionated
5
+ # and contextual ways of applying tracepoints to an application.
4
6
  class Tracers
7
+ # Error for an invalid tracer
5
8
  class InvalidTracerError < StandardError
6
9
  def initialize
7
10
  msg = <<~MSG
@@ -17,18 +20,24 @@ module StaticTracing
17
20
  class << self
18
21
  def add(tracer)
19
22
  raise InvalidTracerError unless tracer < StaticTracing::Tracer::Base
23
+
20
24
  tracers << tracer
21
25
  end
22
26
 
27
+ # Enables each tracer, overriding original
28
+ # method definition with traced one
23
29
  def enable!
24
30
  tracers.each(&:enable!)
25
31
  end
26
32
 
33
+ # Disables each tracer, replacing the method definition
27
34
  def disable!
28
35
  tracers.each(&:disable!)
29
36
  end
30
37
 
38
+ # Clears all tracers
31
39
  def clean
40
+ # FIXME: - actuallly ensure destroyed to avoid memory leaks
32
41
  @tracers = []
33
42
  end
34
43
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StaticTracing
4
- VERSION = '0.0.13'
4
+ # The current version of this gem
5
+ VERSION = '0.0.14'
5
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-static-tracing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Hamel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-20 00:00:00.000000000 Z
11
+ date: 2019-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: unmixer
@@ -25,19 +25,47 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake-compiler
28
+ name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0.9'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0.9'
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -53,21 +81,21 @@ dependencies:
53
81
  - !ruby/object:Gem::Version
54
82
  version: '11.0'
55
83
  - !ruby/object:Gem::Dependency
56
- name: minitest
84
+ name: rake-compiler
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
- - - ">="
87
+ - - "~>"
60
88
  - !ruby/object:Gem::Version
61
- version: '0'
89
+ version: '0.9'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
- - - ">="
94
+ - - "~>"
67
95
  - !ruby/object:Gem::Version
68
- version: '0'
96
+ version: '0.9'
69
97
  - !ruby/object:Gem::Dependency
70
- name: mocha
98
+ name: rubocop
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
101
  - - ">="
@@ -81,7 +109,7 @@ dependencies:
81
109
  - !ruby/object:Gem::Version
82
110
  version: '0'
83
111
  - !ruby/object:Gem::Dependency
84
- name: pry-byebug
112
+ name: simplecov
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
115
  - - ">="