Class: Singed::Flamegraph

Inherits:
Object
  • Object
show all
Defined in:
lib/singed/flamegraph.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(label: nil, ignore_gc: false, interval: 1000, filename: nil) ⇒ Flamegraph

Returns a new instance of Flamegraph.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/singed/flamegraph.rb', line 5

def initialize(label: nil, ignore_gc: false, interval: 1000, filename: nil)
  # it's been created elsewhere, ie rbspy
  if filename
    if ignore_gc
      raise ArgumentError, "ignore_gc not supported when given an existing file"
    end

    if label
      raise ArgumentError, "label not supported when given an existing file"
    end

    @filename = filename
  else
    @ignore_gc = ignore_gc
    @interval = interval
    @time = Time.now # rubocop:disable Rails/TimeZone
    @filename = self.class.generate_filename(label: label, time: @time)
  end
end

Instance Attribute Details

#filenameObject

Returns the value of attribute filename.



3
4
5
# File 'lib/singed/flamegraph.rb', line 3

def filename
  @filename
end

#profileObject

Returns the value of attribute profile.



3
4
5
# File 'lib/singed/flamegraph.rb', line 3

def profile
  @profile
end

Class Method Details

.generate_filename(label: nil, time: Time.now) ⇒ Object

rubocop:disable Rails/TimeZone



55
56
57
58
59
60
61
62
63
64
# File 'lib/singed/flamegraph.rb', line 55

def self.generate_filename(label: nil, time: Time.now) # rubocop:disable Rails/TimeZone
  formatted_time = time.strftime("%Y%m%d%H%M%S-%6N")
  basename_parts = ["speedscope", label, formatted_time].compact

  file = Singed.output_directory.join("#{basename_parts.join("-")}.json")
  # convert to relative directory if it's an absolute path and within the current
  pwd = Pathname.pwd
  file = file.relative_path_from(pwd) if file.absolute? && file.to_s.start_with?(pwd.to_s)
  file
end

Instance Method Details

#openObject



47
48
49
# File 'lib/singed/flamegraph.rb', line 47

def open
  system open_command
end

#open_commandObject



51
52
53
# File 'lib/singed/flamegraph.rb', line 51

def open_command
  @open_command ||= "npx speedscope #{@filename}"
end

#recordObject



25
26
27
28
29
30
31
32
33
34
# File 'lib/singed/flamegraph.rb', line 25

def record
  return yield unless Singed.enabled?
  return yield if filename.exist? # file existing means its been captured already

  result = nil
  @profile = StackProf.run(mode: :wall, raw: true, ignore_gc: @ignore_gc, interval: @interval) do
    result = yield
  end
  result
end

#saveObject



36
37
38
39
40
41
42
43
44
45
# File 'lib/singed/flamegraph.rb', line 36

def save
  if filename.exist?
    raise ArgumentError, "File #{filename} already exists"
  end

  report = Singed::Report.new(@profile)
  report.filter!
  filename.dirname.mkpath
  filename.open("w") { |f| report.print_json(f) }
end