perfetto 0.1.15-x86_64-linux

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