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.
- checksums.yaml +7 -0
- data/.rubocop.yml +18 -0
- data/README.md +109 -0
- data/Rakefile +18 -0
- data/example/example.png +0 -0
- data/example/example.rb +88 -0
- data/ext/perfetto/LICENSE +189 -0
- data/ext/perfetto/README.md +11 -0
- data/ext/perfetto/extconf.rb +11 -0
- data/ext/perfetto/perfetto.c +139 -0
- data/ext/perfetto/perfetto_internal.cc +200 -0
- data/ext/perfetto/perfetto_internal.h +48 -0
- data/ext/perfetto/sdk.cc +62532 -0
- data/ext/perfetto/sdk.h +154360 -0
- data/lib/perfetto/configure.rb +12 -0
- data/lib/perfetto/core_ext/configurable.rb +45 -0
- data/lib/perfetto/interceptor.rb +115 -0
- data/lib/perfetto/middleware.rb +37 -0
- data/lib/perfetto/perfetto.rb +49 -0
- data/lib/perfetto/perfetto_native.so +0 -0
- data/lib/perfetto/version.rb +5 -0
- data/lib/perfetto.rb +30 -0
- data/perfetto.gemspec +34 -0
- data/sig/perfetto.rbs +4 -0
- metadata +71 -0
@@ -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
|
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
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: []
|