File: output.rb

package info (click to toggle)
ruby-sentry-ruby 5.28.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 672 kB
  • sloc: ruby: 6,118; makefile: 8; sh: 4
file content (89 lines) | stat: -rw-r--r-- 2,302 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# frozen_string_literal: true

require "json"
require "rbconfig"

module Sentry
  module Vernier
    class Output
      include Profiler::Helpers

      attr_reader :profile

      def initialize(profile, project_root:, in_app_pattern:, app_dirs_pattern:)
        @profile = profile
        @project_root = project_root
        @in_app_pattern = in_app_pattern
        @app_dirs_pattern = app_dirs_pattern
      end

      def to_h
        @to_h ||= {
          frames: frames,
          stacks: stacks,
          samples: samples,
          thread_metadata: thread_metadata
        }
      end

      private

      def thread_metadata
        profile.threads.map { |thread_id, thread_info|
          [thread_id, { name: thread_info[:name] }]
        }.to_h
      end

      def samples
        profile.threads.flat_map { |thread_id, thread_info|
          started_at = thread_info[:started_at]
          samples, timestamps = thread_info.values_at(:samples, :timestamps)

          samples.zip(timestamps).map { |stack_id, timestamp|
            elapsed_since_start_ns = timestamp - started_at

            next if elapsed_since_start_ns < 0

            {
              thread_id: thread_id.to_s,
              stack_id: stack_id,
              elapsed_since_start_ns: elapsed_since_start_ns.to_s
            }
          }.compact
        }
      end

      def frames
        funcs = stack_table_hash[:frame_table].fetch(:func)
        lines = stack_table_hash[:func_table].fetch(:first_line)

        funcs.map do |idx|
          function, mod = split_module(stack_table_hash[:func_table][:name][idx])

          abs_path = stack_table_hash[:func_table][:filename][idx]
          in_app = in_app?(abs_path)
          filename = compute_filename(abs_path, in_app)

          {
            function: function,
            module: mod,
            filename: filename,
            abs_path: abs_path,
            lineno: (lineno = lines[idx]) > 0 ? lineno : nil,
            in_app: in_app
          }.compact
        end
      end

      def stacks
        profile._stack_table.stack_count.times.map do |stack_id|
          profile.stack(stack_id).frames.map(&:idx)
        end
      end

      def stack_table_hash
        @stack_table_hash ||= profile._stack_table.to_h
      end
    end
  end
end