Module: Instana::Util

Defined in:
lib/instana/util.rb

Constant Summary collapse

ID_RANGE =
-2**63..2**63-1

Class Method Summary collapse

Class Method Details

.collect_process_infoObject

Used in class initialization and after a fork, this method collects up process information



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/instana/util.rb', line 137

def collect_process_info
  process = {}
  cmdline_file = "/proc/#{Process.pid}/cmdline"

  # If there is a /proc filesystem, we read this manually so
  # we can split on embedded null bytes.  Otherwise (e.g. OSX, Windows)
  # use ProcTable.
  if File.exist?(cmdline_file)
    cmdline = IO.read(cmdline_file).split(?\x00)
  else
    cmdline = ProcTable.ps(:pid => Process.pid).cmdline.split(' ')
  end

  if RUBY_PLATFORM =~ /darwin/i
    cmdline.delete_if{ |e| e.include?('=') }
    process[:name] = cmdline.join(' ')
  else
    process[:name] = cmdline.shift
    process[:arguments] = cmdline
  end

  process[:pid] = Process.pid
  # This is usually Process.pid but in the case of containers, the host agent
  # will return to us the true host pid in which we use to report data.
  process[:report_pid] = nil
  process
end

.generate_idInteger

Generate a random 64bit ID

Returns:

  • (Integer)

    a random 64bit integer



204
205
206
207
# File 'lib/instana/util.rb', line 204

def generate_id
  # Max value is 9223372036854775807 (signed long in Java)
  rand(ID_RANGE)
end

.get_app_nameObject

Best effort to determine a name for the instrumented application on the dashboard.



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/instana/util.rb', line 168

def get_app_name
  name = File.basename($0)

  # Framework Detection
  if defined?(::RailsLts) || defined?(::Rails)
    name = Rails.application.class.to_s.split('::')[0]
  end

  return name
rescue Exception => e
  Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
  Instana.logger.debug e.backtrace.join("\r\n")
end

.get_rb_source(file) ⇒ Object

Retrieves and returns the source code for any ruby files requested by the UI via the host agent

Parameters:

  • file (String)

    The fully qualified path to a file



81
82
83
84
85
86
87
88
89
# File 'lib/instana/util.rb', line 81

def get_rb_source(file)
  if (file =~ /.rb$/).nil?
    { :error => "Only Ruby source files are allowed. (*.rb)" }
  else
    { :data => File.read(file) }
  end
rescue => e
  return { :error => e.inspect }
end

.header_to_id(header_id) ⇒ Integer

Convert a received header value into a valid ID

Parameters:

  • header_id (String)

    the header value to be converted

Returns:

  • (Integer)


232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/instana/util.rb', line 232

def header_to_id(header_id)
  if !header_id.is_a?(String)
    Instana.logger.debug "header_to_id received a #{header_id.class}: returning 0"
    return 0
  end
  if header_id.length < 16
    # The header is less than 16 chars.  Prepend
    # zeros so we can convert correctly
    missing = 16 - header_id.length
    header_id = ("0" * missing) + header_id
  end
  [header_id].pack("H*").unpack("q>")[0]
rescue => e
  Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
  Instana.logger.debug e.backtrace.join("\r\n")
end

.id_to_header(id) ⇒ String

Convert an ID to a value appropriate to pass in a header.

Parameters:

  • id (Integer)

    the id to be converted

Returns:

  • (String)


215
216
217
218
219
220
221
222
223
224
# File 'lib/instana/util.rb', line 215

def id_to_header(id)
  unless id.is_a?(Integer) || id.is_a?(String)
    Instana.logger.debug "id_to_header received a #{id.class}: returning empty string"
    return String.new
  end
  [id.to_i].pack('q>').unpack('H*')[0].gsub(/^0+/, '')
rescue => e
  Instana.logger.info "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
  Instana.logger.debug e.backtrace.join("\r\n")
end

.method_alias(klass, method) ⇒ Object

An agnostic approach to method aliasing.

Parameters:

  • klass (Object)

    The class or module that holds the method to be alias’d.

  • method (Symbol)

    The name of the method to be aliased.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/instana/util.rb', line 11

def method_alias(klass, method)
  if klass.method_defined?(method.to_sym) ||
      klass.private_method_defined?(method.to_sym)

    with = "#{method}_with_instana"
    without = "#{method}_without_instana"

    klass.class_eval do
      alias_method without, method.to_s
      alias_method method.to_s, with
    end
  else
    ::Instana.logger.debug "No such method (#{method}) to alias on #{klass}"
  end
end

.now_in_msInteger Also known as: ts_now

Get the current time in milliseconds from the epoch

Returns:

  • (Integer)

    the current time in milliseconds



186
187
188
# File 'lib/instana/util.rb', line 186

def now_in_ms
  Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
end

.pry!Object

Debugging helper method



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
# File 'lib/instana/util.rb', line 47

def pry!
  # Only valid for development or test environments
  #env = ENV['RACK_ENV'] || ENV['RAILS_ENV']
  #return unless %w(development, test).include? env

  if RUBY_VERSION > '1.8.7'
    begin
      require 'pry-byebug'

      if defined?(PryByebug)
        Pry.commands.alias_command 'c', 'continue'
        Pry.commands.alias_command 's', 'step'
        Pry.commands.alias_command 'n', 'next'
        Pry.commands.alias_command 'f', 'finish'

        Pry::Commands.command(/^$/, 'repeat last command') do
          _pry_.run_command Pry.history.to_a.last
        end
      end

      binding.pry
    rescue LoadError
      ::Instana.logger.warn("No debugger in bundle.  Couldn't load pry-byebug.")
    end
  else
    require 'ruby-debug'; debugger
  end
end

.send_extend(target_cls, cls) ⇒ Object

Calls on target_class to ‘extend’ cls

Parameters:

  • target_cls (Object)

    the class/module to do the ‘extending’

  • cls (Object)

    the class/module to be ‘extended’



32
33
34
# File 'lib/instana/util.rb', line 32

def send_extend(target_cls, cls)
  target_cls.send(:extend, cls) if defined?(target_cls)
end

.send_include(target_cls, cls) ⇒ Object

Calls on <target_cls> to include <cls> into itself.

Parameters:

  • target_cls (Object)

    the class/module to do the ‘including’

  • cls (Object)

    the class/module to be ‘included’



41
42
43
# File 'lib/instana/util.rb', line 41

def send_include(target_cls, cls)
  target_cls.send(:include, cls) if defined?(target_cls)
end

.take_snapshotObject

Method to collect up process info for snapshots. This is generally used once per process.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/instana/util.rb', line 94

def take_snapshot
  data = {}

  data[:sensorVersion] = ::Instana::VERSION
  data[:ruby_version] = RUBY_VERSION
  data[:rpl] = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)

  # Framework Detection
  if defined?(::RailsLts::VERSION)
    data[:framework] = "Rails on Rails LTS-#{::RailsLts::VERSION}"

  elsif defined?(::Rails.version)
    data[:framework] = "Ruby on Rails #{::Rails.version}"

  elsif defined?(::Grape::VERSION)
    data[:framework] = "Grape #{::Grape::VERSION}"

  elsif defined?(::Padrino::VERSION)
    data[:framework] = "Padrino #{::Padrino::VERSION}"

  elsif defined?(::Sinatra::VERSION)
    data[:framework] = "Sinatra #{::Sinatra::VERSION}"
  end

  # Report Bundle
  if defined?(::Gem) && Gem.respond_to?(:loaded_specs)
    data[:versions] = {}

    Gem.loaded_specs.each do |k, v|
      data[:versions][k] = v.version.to_s
    end
  end

  data
rescue => e
  ::Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
  ::Instana.logger.debug e.backtrace.join("\r\n")
  return data
end

.time_to_ms(time) ⇒ Object

Convert a Time value to milliseconds

Parameters:

  • time (Time)


196
197
198
# File 'lib/instana/util.rb', line 196

def time_to_ms(time)
  (time.to_f * 1000).floor
end