perfetto 0.1.15-x86_64-linux

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.
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Perfetto
4
+ # Global configuration
5
+ class Configure
6
+ extend Configurable
7
+
8
+ set :enable_tracing, false
9
+ set :enable_fiber, false
10
+ set :buffer_size_kb, 1024
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copy-pasted from https://github.com/midori-rb/midori.rb/blob/master/lib/midori/core_ext/configurable.rb
4
+ # rubocop:disable Style/OptionalBooleanParameter
5
+ # rubocop:disable Style/DocumentDynamicEvalDefinition
6
+ module Configurable
7
+ # Sets an option to the given value.
8
+ # @param [Symbol] option the name of config
9
+ # @param [Object] value value to the name
10
+ # @param [Boolean] read_only Generate option= method or not
11
+ # @return [nil] nil
12
+ def set(option, value = (not_set = true), read_only = false)
13
+ raise ArgumentError if not_set
14
+
15
+ setter = proc { |val| set option, val }
16
+ getter = proc { value }
17
+
18
+ define_singleton("#{option}=", setter) unless read_only
19
+ define_singleton(option, getter)
20
+ define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
21
+
22
+ self
23
+ end
24
+
25
+ private
26
+
27
+ # Dynamically defines a method on settings.
28
+ # @param [String] name method name
29
+ # @param [Proc] content method content
30
+ # @return [nil] nil
31
+ def define_singleton(name, content = Proc.new)
32
+ singleton_class.class_eval do
33
+ undef_method(name) if method_defined? name
34
+ if content.is_a?(String)
35
+ class_eval("def #{name}() #{content}; end", __FILE__,
36
+ __LINE__ - 1)
37
+ else
38
+ define_method(name, &content)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ # rubocop:enable Style/OptionalBooleanParameter
45
+ # rubocop:enable Style/DocumentDynamicEvalDefinition
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/AbcSize
4
+ # rubocop:disable Metrics/MethodLength
5
+
6
+ module Perfetto
7
+ # To intercept method calls in other classes
8
+ module Interceptor
9
+ def self.included(base)
10
+ if Perfetto::Configure.enable_tracing?
11
+ base.extend ImplMethods
12
+ else
13
+ base.extend StubMethods
14
+ end
15
+ end
16
+
17
+ # Stub methods
18
+ module StubMethods
19
+ def perfetto_trace_instance_method(_method_name); end
20
+ def perfetto_trace_class_method(_method_name); end
21
+ def perfetto_trace_all; end
22
+
23
+ def perfetto_traced_instance_method?(_method_name)
24
+ false
25
+ end
26
+
27
+ def perfetto_traced_class_method?(_method_name)
28
+ false
29
+ end
30
+
31
+ def perfetto_traced_instance_methods
32
+ []
33
+ end
34
+
35
+ def perfetto_traced_class_methods
36
+ []
37
+ end
38
+ end
39
+
40
+ # Real Implementation
41
+ module ImplMethods
42
+ def perfetto_trace_instance_method(method_name)
43
+ return if method_name.to_s.start_with? "_pfi_"
44
+
45
+ perfetto_traced_instance_methods << method_name
46
+
47
+ original_method = instance_method(method_name)
48
+ alias_method "_pfi_#{method_name}", method_name
49
+
50
+ define_method(method_name) do |*args, **kwargs, &block|
51
+ category = self.class.name
52
+ task_name = "#{self.class.name}##{method_name}"
53
+ Perfetto.trace_event_begin category, task_name
54
+ original_method.bind(self).call(*args, **kwargs, &block)
55
+ ensure
56
+ Perfetto.trace_event_end self.class.name
57
+ end
58
+ end
59
+
60
+ def perfetto_trace_class_method(method_name)
61
+ return if method_name.to_s.start_with? "_pfc_"
62
+
63
+ perfetto_traced_class_methods << method_name
64
+
65
+ original_method = singleton_class.instance_method(method_name)
66
+ singleton_class.send(:alias_method, "_pfc_#{method_name}", method_name)
67
+
68
+ define_singleton_method(method_name) do |*args, **kwargs, &block|
69
+ category = name
70
+ task_name = "#{name}::#{method_name}"
71
+ Perfetto.trace_event_begin category, task_name
72
+ original_method.bind(self).call(*args, **kwargs, &block)
73
+ ensure
74
+ Perfetto.trace_event_end name
75
+ end
76
+ end
77
+
78
+ def perfetto_trace_all
79
+ original_method_added = singleton_class.instance_method(:method_added)
80
+ define_singleton_method(:method_added) do |method_name|
81
+ original_method_added.bind(self).call(method_name)
82
+ return if perfetto_traced_instance_method?(method_name)
83
+
84
+ perfetto_trace_instance_method method_name
85
+ end
86
+
87
+ original_singleton_method_added = singleton_class.instance_method(:singleton_method_added)
88
+ define_singleton_method(:singleton_method_added) do |method_name|
89
+ original_singleton_method_added.bind(self).call(method_name)
90
+ return if perfetto_traced_class_method?(method_name)
91
+
92
+ perfetto_trace_class_method method_name
93
+ end
94
+ end
95
+
96
+ def perfetto_traced_instance_method?(method_name)
97
+ perfetto_traced_instance_methods.include? method_name
98
+ end
99
+
100
+ def perfetto_traced_class_method?(method_name)
101
+ perfetto_traced_class_methods.include? method_name
102
+ end
103
+
104
+ def perfetto_traced_instance_methods
105
+ @perfetto_traced_instance_methods ||= []
106
+ end
107
+
108
+ def perfetto_traced_class_methods
109
+ @perfetto_traced_class_methods ||= []
110
+ end
111
+ end
112
+ end
113
+ end
114
+ # rubocop:enable Metrics/AbcSize
115
+ # rubocop:enable Metrics/MethodLength
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Perfetto
4
+ # Rack middleware
5
+ class Middleware
6
+ def initialize(app, options = {})
7
+ @app = app
8
+ @options = options
9
+ @env_proc = options[:env_proc]
10
+ end
11
+
12
+ # rubocop:disable Metrics/MethodLength
13
+ def perfetto_traced_call(env)
14
+ category = "RackMiddleware"
15
+ method = env["REQUEST_METHOD"] || "UNKNOWN"
16
+ path = env["PATH_INFO"] || "UNKNOWN PATH"
17
+ task_name = "#{method} #{path}"
18
+ env_str = @env_proc&.call(env) || { env: "unknown" }.to_json
19
+
20
+ Perfetto.trace_event_begin_with_debug_info category, task_name, "env", env_str
21
+ begin
22
+ @app.call(env)
23
+ ensure
24
+ Perfetto.trace_event_end category
25
+ end
26
+ end
27
+ # rubocop:enable Metrics/MethodLength
28
+
29
+ def call(env)
30
+ if Perfetto::Configure.enable_tracing?
31
+ perfetto_traced_call(env)
32
+ else
33
+ @app.call(env)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby wrapper for native extension
4
+ module Perfetto
5
+ class << self
6
+ alias start_tracing_native start_tracing
7
+ alias stop_tracing_native stop_tracing
8
+ end
9
+
10
+ if Perfetto::Configure.enable_tracing?
11
+ if Perfetto::Configure.enable_fiber?
12
+ class << self
13
+ # Replace thread based methods with fiber based methods
14
+ alias thread_trace_event_begin trace_event_begin
15
+ alias thread_trace_event_end trace_event_end
16
+ alias thread_trace_event_instant trace_event_instant
17
+ alias thread_trace_event_begin_with_debug_info trace_event_begin_with_debug_info
18
+ alias thread_trace_event_instant_with_debug_info trace_event_instant_with_debug_info
19
+
20
+ alias trace_event_begin fiber_trace_event_begin
21
+ alias trace_event_end fiber_trace_event_end
22
+ alias trace_event_instant fiber_trace_event_instant
23
+ alias trace_event_begin_with_debug_info fiber_trace_event_begin_with_debug_info
24
+ alias trace_event_instant_with_debug_info fiber_trace_event_instant_with_debug_info
25
+ end
26
+ end
27
+
28
+ # Default arguments implemented in this wrapper
29
+ def self.start_tracing
30
+ start_tracing_native Configure.buffer_size_kb
31
+ end
32
+
33
+ def self.stop_tracing(trace_file_name = "#{Time.now.strftime("%Y%m%d-%H-%M-%S")}.pftrace")
34
+ stop_tracing_native trace_file_name
35
+ end
36
+ else
37
+ # Stub methods
38
+ def self.start_tracing; end
39
+ def self.stop_tracing(trace_file_name = nil); end
40
+ def self.trace_event_begin(_class_name, _method_name); end
41
+ def self.trace_event_end(_class_name); end
42
+ def self.trace_counter(_class_name, _counter_name, _counter_value); end
43
+ def self.trace_counter_i64(_class_name, _counter_name, _counter_value); end
44
+ def self.trace_counter_double(_class_name, _counter_name, _counter_value); end
45
+ def self.trace_event_instant(_class_name, _method_name); end
46
+ def self.trace_event_begin_with_debug_info(_class_name, _method_name, _debug_key, _debug_value); end
47
+ def self.trace_event_instant_with_debug_info(_class_name, _method_name, _debug_key, _debug_value); end
48
+ end
49
+ end
Binary file
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Perfetto
4
+ VERSION = "0.1.15"
5
+ end
data/lib/perfetto.rb ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require_relative "perfetto/version"
6
+
7
+ require_relative "perfetto/core_ext/configurable"
8
+ require_relative "perfetto/configure"
9
+
10
+ # Rack middleware
11
+ require_relative "perfetto/middleware"
12
+
13
+ # To minimize the overhead of tracing at runtime
14
+ # we determine whether to enable instrumentations
15
+ # at the first call to 'setup' method instead of
16
+ # every call to bussiness logics being traced.
17
+ module Perfetto
18
+ def self.setup(enable_tracing: nil, enable_fiber: nil, buffer_size_kb: nil)
19
+ Configure.enable_tracing = enable_tracing unless enable_tracing.nil?
20
+ Configure.enable_fiber = enable_fiber unless enable_fiber.nil?
21
+ Configure.buffer_size_kb = buffer_size_kb unless buffer_size_kb.nil?
22
+
23
+ # Native extension
24
+ require_relative "perfetto/perfetto_native"
25
+ # Ruby wrapper
26
+ require_relative "perfetto/perfetto"
27
+ # Instrumentation Helper
28
+ require_relative "perfetto/interceptor"
29
+ end
30
+ end
data/perfetto.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/perfetto/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "perfetto"
7
+ spec.version = Perfetto::VERSION
8
+ spec.authors = ["Kowalski Dark"]
9
+ spec.email = ["github@akenonet.com"]
10
+
11
+ spec.summary = "Yet another event tracing library for Ruby."
12
+ spec.description = "Yet another event tracing library for Ruby."
13
+ spec.homepage = "https://github.com/yet-another-ai/perfetto.rb"
14
+ spec.required_ruby_version = ">= 3.3.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(__dir__) do
21
+ `git ls-files -z`.split("\x0").reject do |f|
22
+ (File.expand_path(f) == __FILE__) ||
23
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
24
+ end
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
+ spec.require_paths = %w[lib ext]
29
+ spec.extensions = ["ext/perfetto/extconf.rb"]
30
+
31
+ # For more information and examples about making a new gem, check out our
32
+ # guide at: https://bundler.io/guides/creating_gem.html
33
+ spec.metadata["rubygems_mfa_required"] = "true"
34
+ end
data/sig/perfetto.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Perfetto
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perfetto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.15
5
+ platform: x86_64-linux
6
+ authors:
7
+ - Kowalski Dark
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-02-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Yet another event tracing library for Ruby.
14
+ email:
15
+ - github@akenonet.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rubocop.yml"
21
+ - README.md
22
+ - Rakefile
23
+ - example/example.png
24
+ - example/example.rb
25
+ - ext/perfetto/LICENSE
26
+ - ext/perfetto/README.md
27
+ - ext/perfetto/extconf.rb
28
+ - ext/perfetto/perfetto.c
29
+ - ext/perfetto/perfetto_internal.cc
30
+ - ext/perfetto/perfetto_internal.h
31
+ - ext/perfetto/sdk.cc
32
+ - ext/perfetto/sdk.h
33
+ - lib/perfetto.rb
34
+ - lib/perfetto/configure.rb
35
+ - lib/perfetto/core_ext/configurable.rb
36
+ - lib/perfetto/interceptor.rb
37
+ - lib/perfetto/middleware.rb
38
+ - lib/perfetto/perfetto.rb
39
+ - lib/perfetto/perfetto_native.so
40
+ - lib/perfetto/version.rb
41
+ - perfetto.gemspec
42
+ - sig/perfetto.rbs
43
+ homepage: https://github.com/yet-another-ai/perfetto.rb
44
+ licenses: []
45
+ metadata:
46
+ homepage_uri: https://github.com/yet-another-ai/perfetto.rb
47
+ rubygems_mfa_required: 'true'
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ - ext
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '3.3'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: 3.4.dev
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubygems_version: 3.5.3
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Yet another event tracing library for Ruby.
71
+ test_files: []