skylight 0.3.10 → 0.3.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c2808cf85e0a48a911372e657dcfe99a191bf6e
4
- data.tar.gz: bda10993e74865cc28f05f5db97a244ddf1af972
3
+ metadata.gz: ba7ee3852dc0f4d87a9d974aeade1100cde21613
4
+ data.tar.gz: 4101c8d467fbbd2c5fccb0124a02b2cf0634232d
5
5
  SHA512:
6
- metadata.gz: c247a8b0b9cde850ff0aa98cfb4a867fc73ef05539ab5f7fbdfc478e820a160bf0f4a8b22e94a94d2de731cf715fcefc623fc2dba64f1979738ffdb08c0620a0
7
- data.tar.gz: 7f7893da15b537872e33abe3b670c69ce2ae5b0c62806300dafbed5242fea08edcea068514ed390c4bce5f39da1bdb85641556f115fce7ffcdb39d6e7633fc8c
6
+ metadata.gz: df39f86e95a05dc50973fc6a0ceda455eec6ffb9ca77bc19a3a8726e9099349303905eb282e845886aa220ff88da413d516754215234cb5194b274b60a4f5bb9
7
+ data.tar.gz: c54def8443d4ebc20d576ad38891acf1b58252fd62d34534e3c905385474bd1b759794f4fc55097c60be47e5b8397fb319808618d7ad091014a7aeea0a10a1bf
@@ -1,3 +1,12 @@
1
+ ## 0.3.11 (April 11, 2014)
2
+
3
+ * Improved error handling and internal metrics
4
+ * Improved missing native agent message
5
+ * Improved install logging
6
+ * Added initial inline docs
7
+ * Respects HTTP_PROXY env var during installation
8
+ * Don't overwrite sockfile_path if set explicitly
9
+
1
10
  ## 0.3.10 (April 8, 2014)
2
11
 
3
12
  * Don't raise on missing native agent path
data/README.md CHANGED
@@ -2,3 +2,5 @@
2
2
 
3
3
  Instrument your ruby application and send the data to the Skylight
4
4
  servers.
5
+
6
+ {render:Skylight}
@@ -2,7 +2,27 @@ require 'mkmf'
2
2
  require 'yaml'
3
3
  require 'logger'
4
4
 
5
- LOG = Logger.new(STDOUT)
5
+ # Must require 'rubygems/platform' vs. just requiring 'rubygems' to avoid a
6
+ # stack overflow bug on ruby 1.9.2.
7
+ require 'rubygems/platform'
8
+
9
+ class MultiIO
10
+ def initialize(*targets)
11
+ @targets = targets
12
+ end
13
+
14
+ def write(*args)
15
+ @targets.each {|t| t.write(*args)}
16
+ end
17
+
18
+ def close
19
+ @targets.each(&:close)
20
+ end
21
+ end
22
+
23
+ log_file = File.open(File.expand_path("../install.log", __FILE__), "a")
24
+ LOG = Logger.new(MultiIO.new(STDOUT, log_file))
25
+
6
26
  SKYLIGHT_REQUIRED = ENV.key?("SKYLIGHT_REQUIRED") && ENV['SKYLIGHT_REQUIRED'] !~ /^false$/i
7
27
 
8
28
  require_relative '../lib/skylight/version'
@@ -14,8 +34,8 @@ include Skylight::Util
14
34
  # want to break our customer's deploy, but extconf.rb requires a Makefile to be
15
35
  # present upon a successful exit. To satisfy this requirement, we create a
16
36
  # dummy Makefile.
17
- def fail(msg)
18
- LOG.error msg
37
+ def fail(msg, type=:error)
38
+ LOG.send type, msg
19
39
 
20
40
  if SKYLIGHT_REQUIRED
21
41
  exit 1
@@ -50,11 +70,21 @@ unless File.exist?(libskylight_a)
50
70
  fail "libskylight checksums missing from `#{libskylight_yml}`"
51
71
  end
52
72
 
73
+ platform = Gem::Platform.local
74
+ arch = "#{platform.os}-#{platform.cpu}"
75
+
76
+ unless checksum = checksums[arch]
77
+ fail "no checksum entry for requested architecture -- " \
78
+ "this probably means the requested architecture is not supported; " \
79
+ "arch=#{arch}; available=#{checksums.keys}", :info
80
+ end
81
+
53
82
  begin
54
83
  res = NativeExtFetcher.fetch(
55
84
  version: version,
56
85
  target: libskylight_a,
57
- checksums: checksums,
86
+ checksum: checksum,
87
+ arch: arch,
58
88
  required: SKYLIGHT_REQUIRED,
59
89
  logger: LOG)
60
90
 
@@ -3,10 +3,16 @@ require 'socket'
3
3
  require 'skylight/version'
4
4
 
5
5
  module Skylight
6
+ # @api private
6
7
  TRACE_ENV_KEY = 'SKYLIGHT_ENABLE_TRACE_LOGS'.freeze
8
+
9
+ # @api private
7
10
  STANDALONE_ENV_KEY = 'SKYLIGHT_STANDALONE'.freeze
11
+
12
+ # @api private
8
13
  STANDALONE_ENV_VAL = 'server'.freeze
9
14
 
15
+ # @api private
10
16
  # Whether or not the native extension is present
11
17
  @@has_native_ext = false
12
18
 
@@ -29,39 +35,41 @@ module Skylight
29
35
  raise if ENV.key?("SKYLIGHT_REQUIRED")
30
36
  end
31
37
 
32
- autoload :Api, 'skylight/api'
33
- autoload :CLI, 'skylight/cli'
34
- autoload :Config, 'skylight/config'
35
- autoload :Helpers, 'skylight/helpers'
36
-
37
- module Util
38
- autoload :Logging, 'skylight/util/logging'
39
- autoload :HTTP, 'skylight/util/http'
38
+ if defined?(Rails)
39
+ require 'skylight/railtie'
40
40
  end
41
41
 
42
- # ==== Exceptions ====
43
- class IpcProtoError < RuntimeError; end
44
- class WorkerStateError < RuntimeError; end
45
- class ConfigError < RuntimeError; end
46
- class TraceError < RuntimeError; end
47
- class SerializeError < RuntimeError; end
42
+ # @api private
43
+ def self.check_install_errors
44
+ # Note: An unsupported arch doesn't count as an error.
45
+ install_log = File.expand_path("../../ext/install.log", __FILE__)
48
46
 
49
- if defined?(Rails)
50
- require 'skylight/railtie'
47
+ if File.exist?(install_log) && File.read(install_log) =~ /ERROR/
48
+ puts "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension failed to install. " \
49
+ "Please check #{install_log} and notify support@skylight.io." \
50
+ "The missing extension will not affect the functioning of your application."
51
+ end
51
52
  end
52
53
 
54
+ # @api private
53
55
  def self.warn_skylight_native_missing
54
56
  # TODO: Dumping the error messages this way is pretty hacky
55
57
  is_rails = defined?(Rails)
56
58
  env_name = is_rails ? Rails.env : "development"
57
59
 
58
60
  if env_name == "development" || env_name == "test"
59
- puts "[SKYLIGHT] [#{Skylight::VERSION}] Running Skylight in #{env_name} mode. No data will be reported until you deploy your app."
61
+ puts "[SKYLIGHT] [#{Skylight::VERSION}] Running Skylight in #{env_name} mode. " \
62
+ "No data will be reported until you deploy your app."
60
63
  else
61
- puts "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension for your platform wasn't found. We currently support monitoring in 32- and 64-bit Linux only. If you are on a supported platform, please contact support at support@skylight.io. The missing extension will not affect the functioning of your application."
64
+ puts "[SKYLIGHT] [#{Skylight::VERSION}] The Skylight native extension for your platform wasn't found. " \
65
+ "The monitoring portion of Skylight is only supported on production servers running 32- or " \
66
+ "64-bit Linux. The missing extension will not affect the functioning of your application " \
67
+ "and you can continue local development without data being reported. If you are on a " \
68
+ "supported platform, please contact support at support@skylight.io."
62
69
  end
63
70
  end
64
71
 
72
+ # @api private
65
73
  def self.daemon?
66
74
  ENV[STANDALONE_ENV_KEY] == STANDALONE_ENV_VAL
67
75
  end
@@ -74,38 +82,41 @@ module Skylight
74
82
  require 'skylight/vm/gc'
75
83
  end
76
84
 
85
+ autoload :Api, 'skylight/api'
86
+ autoload :CLI, 'skylight/cli'
87
+ autoload :Config, 'skylight/config'
88
+ autoload :Helpers, 'skylight/helpers'
89
+ autoload :Formatters, 'skylight/formatters'
77
90
  autoload :GC, 'skylight/gc'
78
91
  autoload :Instrumenter, 'skylight/instrumenter'
79
92
  autoload :Messages, 'skylight/messages'
93
+ autoload :Metrics, 'skylight/metrics'
80
94
  autoload :Middleware, 'skylight/middleware'
81
95
  autoload :Normalizers, 'skylight/normalizers'
82
96
  autoload :Subscriber, 'skylight/subscriber'
83
97
  autoload :Worker, 'skylight/worker'
84
98
 
85
- module Metrics
86
- autoload :Meter, 'skylight/metrics/meter'
87
- autoload :EWMA, 'skylight/metrics/ewma'
88
- autoload :ProcessMemGauge, 'skylight/metrics/process_mem_gauge'
89
- autoload :ProcessCpuGauge, 'skylight/metrics/process_cpu_gauge'
90
- end
99
+ # Skylight::Util is defined by the native ext so we can't autoload
100
+ require 'skylight/util'
91
101
 
92
- module Util
93
- require 'skylight/util/clock'
94
-
95
- autoload :Conversions, 'skylight/util/conversions'
96
- autoload :Gzip, 'skylight/util/gzip'
97
- autoload :HTTP, 'skylight/util/http'
98
- autoload :Inflector, 'skylight/util/inflector'
99
- autoload :Logging, 'skylight/util/logging'
100
- autoload :Queue, 'skylight/util/queue'
101
- autoload :Task, 'skylight/util/task'
102
- autoload :UniformSample, 'skylight/util/uniform_sample'
103
- end
102
+ # ==== Exceptions ====
104
103
 
105
- module Formatters
106
- autoload :HTTP, 'skylight/formatters/http'
107
- end
104
+ # @api private
105
+ class IpcProtoError < RuntimeError; end
106
+
107
+ # @api private
108
+ class WorkerStateError < RuntimeError; end
109
+
110
+ # @api private
111
+ class ConfigError < RuntimeError; end
112
+
113
+ # @api private
114
+ class TraceError < RuntimeError; end
115
+
116
+ # @api private
117
+ class SerializeError < RuntimeError; end
108
118
 
119
+ # @api private
109
120
  TIERS = %w(
110
121
  api
111
122
  app
@@ -114,25 +125,29 @@ module Skylight
114
125
  noise
115
126
  other)
116
127
 
128
+ # @api private
117
129
  TIER_REGEX = /^(?:#{TIERS.join('|')})(?:\.|$)/u
130
+
131
+ # @api private
118
132
  CATEGORY_REGEX = /^[a-z0-9_-]+(?:\.[a-z0-9_-]+)*$/iu
133
+
134
+ # @api private
119
135
  DEFAULT_CATEGORY = "app.block".freeze
120
- DEFAULT_OPTIONS = { category: DEFAULT_CATEGORY }
121
136
 
122
- #
123
- #
124
- # ===== Public API =====
125
- #
126
- #
137
+ # @api private
138
+ DEFAULT_OPTIONS = { category: DEFAULT_CATEGORY }
127
139
 
140
+ # Start instrumenting
128
141
  def self.start!(*args)
129
142
  Instrumenter.start!(*args)
130
143
  end
131
144
 
145
+ # Stop instrumenting
132
146
  def self.stop!(*args)
133
147
  Instrumenter.stop!(*args)
134
148
  end
135
149
 
150
+ # Start a trace
136
151
  def self.trace(endpoint=nil, cat=nil, title=nil)
137
152
  unless inst = Instrumenter.instance
138
153
  return yield if block_given?
@@ -146,11 +161,13 @@ module Skylight
146
161
  end
147
162
  end
148
163
 
164
+ # End a trace
149
165
  def self.done(span)
150
166
  return unless inst = Instrumenter.instance
151
167
  inst.done(span)
152
168
  end
153
169
 
170
+ # Instrument
154
171
  def self.instrument(opts = DEFAULT_OPTIONS)
155
172
  unless inst = Instrumenter.instance
156
173
  return yield if block_given?
@@ -176,6 +193,7 @@ module Skylight
176
193
  end
177
194
  end
178
195
 
196
+ # Temporarily disable
179
197
  def self.disable
180
198
  unless inst = Instrumenter.instance
181
199
  return yield if block_given?
@@ -185,6 +203,7 @@ module Skylight
185
203
  inst.disable { yield }
186
204
  end
187
205
 
206
+ # @api private
188
207
  RUBYBIN = File.join(
189
208
  RbConfig::CONFIG['bindir'],
190
209
  "#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}")
@@ -194,3 +213,7 @@ module Skylight
194
213
 
195
214
  require 'skylight/probes'
196
215
  end
216
+
217
+ # Warn as soon as possible if there was an error installing Skylight.
218
+ # We do this here since we can't report these issues via Gem install without stopping install entirely.
219
+ Skylight.check_install_errors
@@ -1,4 +1,5 @@
1
1
  module Skylight
2
+ # @api private
2
3
  class Api
3
4
  attr_reader :config, :http
4
5
 
@@ -7,6 +7,7 @@ require 'highline'
7
7
  require 'active_support/inflector'
8
8
 
9
9
  module Skylight
10
+ # @api private
10
11
  class CLI < Thor
11
12
 
12
13
  desc "setup", "Sets up a new app"
@@ -34,6 +34,7 @@ end
34
34
 
35
35
  if defined?(ActiveSupport::Notifications::Fanout::Subscribers::Evented)
36
36
  # Handle early RCs of rails 4.0
37
+ # @api private
37
38
  class ActiveSupport::Notifications::Fanout::Subscribers::Evented
38
39
  unless method_defined?(:publish)
39
40
  def publish(name, *args)
@@ -6,6 +6,7 @@ require 'socket'
6
6
 
7
7
  module Skylight
8
8
  class Config
9
+ # @api private
9
10
  MUTEX = Mutex.new
10
11
 
11
12
  def self.default_hostname
@@ -102,6 +103,7 @@ module Skylight
102
103
  self.load(nil, nil, env)
103
104
  end
104
105
 
106
+ # @api private
105
107
  def self.remap_env(env)
106
108
  ret = {}
107
109
 
@@ -125,8 +127,10 @@ module Skylight
125
127
  ret
126
128
  end
127
129
 
130
+ # @api private
128
131
  attr_reader :environment
129
132
 
133
+ # @api private
130
134
  def initialize(*args)
131
135
  attrs = {}
132
136
 
@@ -155,10 +159,12 @@ module Skylight
155
159
  end
156
160
  end
157
161
 
162
+ # @api private
158
163
  def skip_validation?
159
164
  !!get(:skip_validation)
160
165
  end
161
166
 
167
+ # @api private
162
168
  def validate!
163
169
  return true if skip_validation?
164
170
 
@@ -171,6 +177,7 @@ module Skylight
171
177
  true
172
178
  end
173
179
 
180
+ # @api private
174
181
  def validate_token
175
182
  return :ok if skip_validation?
176
183
 
@@ -255,12 +262,6 @@ module Skylight
255
262
  ret
256
263
  end
257
264
 
258
- #
259
- #
260
- # ===== Writing =====
261
- #
262
- #
263
-
264
265
  def write(path)
265
266
  FileUtils.mkdir_p(File.dirname(path))
266
267
 
@@ -282,18 +283,22 @@ authentication: #{self[:authentication]}
282
283
  #
283
284
  #
284
285
 
286
+ # @api private
285
287
  def worker
286
288
  Worker::Builder.new(self)
287
289
  end
288
290
 
291
+ # @api private
289
292
  def gc
290
293
  @gc ||= GC.new(self, get('gc.profiler', VM::GC.new))
291
294
  end
292
295
 
296
+ # @api private
293
297
  def constant_flush?
294
298
  get('test.constant_flush')
295
299
  end
296
300
 
301
+ # @api private
297
302
  def ignore_token?
298
303
  get('test.ignore_token')
299
304
  end
@@ -0,0 +1,6 @@
1
+ module Skylight
2
+ # @api private
3
+ module Formatters
4
+ autoload :HTTP, 'skylight/formatters/http'
5
+ end
6
+ end
@@ -1,6 +1,7 @@
1
1
  require 'thread'
2
2
 
3
3
  module Skylight
4
+ # @api private
4
5
  class GC
5
6
  METHODS = [ :enable, :total_time ]
6
7
  TH_KEY = :SK_GC_CURR_WINDOW
@@ -1,6 +1,15 @@
1
1
  module Skylight
2
+ # Instrumenting a specific method will cause an event to be created every time that method is called.
3
+ # The event will be inserted at the appropriate place in the Skylight trace.
4
+ #
5
+ # To instrument a method, the first thing to do is include {Skylight::Helpers Skylight::Helpers}
6
+ # into the class that you will be instrumenting. Then, annotate each method that
7
+ # you wish to instrument with {Skylight::Helpers::ClassMethods#instrument_method instrument_method}.
2
8
  module Helpers
9
+
10
+ # @see Skylight::Helpers
3
11
  module ClassMethods
12
+ # @api private
4
13
  def method_added(name)
5
14
  super
6
15
 
@@ -11,6 +20,7 @@ module Skylight
11
20
  end
12
21
  end
13
22
 
23
+ # @api private
14
24
  def singleton_method_added(name)
15
25
  super
16
26
 
@@ -21,6 +31,55 @@ module Skylight
21
31
  end
22
32
  end
23
33
 
34
+ # @overload instrument_method
35
+ # Instruments the following method
36
+ #
37
+ # @example
38
+ # class MyClass
39
+ # include Skylight::Helpers
40
+ #
41
+ # instrument_method
42
+ # def my_method
43
+ # do_expensive_stuff
44
+ # end
45
+ #
46
+ # end
47
+ #
48
+ # @overload instrument_method([name], opts={})
49
+ # @param [Symbol|String] [name]
50
+ # @param [Hash] opts
51
+ # @option opts [String] :category ('app.method')
52
+ # @option opts [String] :title (ClassName#method_name)
53
+ # @option opts [String] :description
54
+ #
55
+ # You may also declare the methods to instrument at any time by passing the name
56
+ # of the method as the first argument to `instrument_method`.
57
+ #
58
+ # @example With name
59
+ # class MyClass
60
+ # include Skylight::Helpers
61
+ #
62
+ # def my_method
63
+ # do_expensive_stuff
64
+ # end
65
+ #
66
+ # instrument_method :my_method
67
+ #
68
+ # end
69
+ #
70
+ # By default, the event will be titled using the name of the class and the
71
+ # method. For example, in our previous example, the event name will be:
72
+ # +MyClass#my_method+. You can customize this by passing using the *:title* option.
73
+ #
74
+ # @example Without name
75
+ # class MyClass
76
+ # include Skylight::Helpers
77
+ #
78
+ # instrument_method title: 'Expensive work'
79
+ # def my_method
80
+ # do_expensive_stuff
81
+ # end
82
+ # end
24
83
  def instrument_method(*args)
25
84
  opts = args.pop if Hash === args.last
26
85
 
@@ -66,6 +125,7 @@ module Skylight
66
125
  end
67
126
  end
68
127
 
128
+ # @api private
69
129
  def self.included(base)
70
130
  base.class_eval do
71
131
  @__sk_instrument_next_method = nil
@@ -4,6 +4,7 @@ require 'base64'
4
4
  require 'strscan'
5
5
 
6
6
  module Skylight
7
+ # @api private
7
8
  class Instrumenter
8
9
  KEY = :__skylight_current_trace
9
10
  LOCK = Mutex.new
@@ -27,6 +28,8 @@ module Skylight
27
28
  @instance
28
29
  end
29
30
 
31
+ # Do start
32
+ # @param [Config] config The config
30
33
  def self.start!(config = Config.new)
31
34
  return @instance if @instance
32
35
 
@@ -1,4 +1,5 @@
1
1
  module Skylight
2
+ # @api private
2
3
  module Messages
3
4
  require 'skylight/messages/trace'
4
5
  require 'skylight/messages/hello'
@@ -1,4 +1,5 @@
1
1
  module Skylight
2
+ # @api private
2
3
  module Messages
3
4
  class Hello
4
5
  def self.build(version, cmd=[])
@@ -0,0 +1,9 @@
1
+ module Skylight
2
+ # @api private
3
+ module Metrics
4
+ autoload :Meter, 'skylight/metrics/meter'
5
+ autoload :EWMA, 'skylight/metrics/ewma'
6
+ autoload :ProcessMemGauge, 'skylight/metrics/process_mem_gauge'
7
+ autoload :ProcessCpuGauge, 'skylight/metrics/process_cpu_gauge'
8
+ end
9
+ end
@@ -1,4 +1,5 @@
1
1
  module Skylight
2
+ # @api private
2
3
  class Middleware
3
4
 
4
5
  class BodyProxy
@@ -1,6 +1,8 @@
1
1
  module Skylight
2
2
 
3
3
  if native?
4
+
5
+ # @api private
4
6
  class Hello
5
7
  DIGITS = /^\s*\d+\s*$/
6
8
 
@@ -57,6 +59,7 @@ module Skylight
57
59
 
58
60
  end
59
61
 
62
+ # @api private
60
63
  class Error
61
64
  alias serialize native_serialize
62
65
  alias type native_get_group
@@ -68,12 +71,20 @@ module Skylight
68
71
  end
69
72
  end
70
73
 
74
+ # @api private
71
75
  class Trace
72
76
  alias serialize native_serialize
73
77
  end
74
78
 
79
+ # @api private
75
80
  class Batch
76
81
  alias serialize native_serialize
77
82
  end
78
83
  end
84
+
85
+ # @api private
86
+ # We have to declare this again due to a YARD bug
87
+ # https://github.com/lsegal/yard/issues/761
88
+ class Hello; end
89
+
79
90
  end
@@ -1,7 +1,7 @@
1
1
  require 'skylight/normalizers/default'
2
- require 'skylight/util/allocation_free'
3
2
 
4
3
  module Skylight
4
+ # @api private
5
5
  # Convert AS::N events to Skylight events
6
6
  module Normalizers
7
7
 
@@ -41,7 +41,7 @@ module Skylight
41
41
  end
42
42
 
43
43
  class RenderNormalizer < Normalizer
44
- include AllocationFree
44
+ include Util::AllocationFree
45
45
 
46
46
  def setup
47
47
  @paths = config['normalizers.render.view_paths'] || []
@@ -1,6 +1,6 @@
1
1
  module Skylight
2
+ # @api private
2
3
  module Probes
3
-
4
4
  class ProbeRegistration
5
5
  attr_reader :klass_name, :require_paths, :probe
6
6
 
@@ -73,6 +73,7 @@ module Skylight
73
73
  end
74
74
 
75
75
  # Allow hooking require
76
+ # @api private
76
77
  module ::Kernel
77
78
  alias require_without_sk require
78
79
 
@@ -2,6 +2,7 @@ require 'skylight'
2
2
  require 'rails'
3
3
 
4
4
  module Skylight
5
+ # @api private
5
6
  class Railtie < Rails::Railtie
6
7
  config.skylight = ActiveSupport::OrderedOptions.new
7
8
 
@@ -51,7 +52,7 @@ module Skylight
51
52
 
52
53
  configure_logging(config, app)
53
54
 
54
- config['agent.sockfile_path'] = tmp
55
+ config['agent.sockfile_path'] ||= tmp
55
56
  config['normalizers.render.view_paths'] = existent_paths(app.config.paths["app/views"]) + [Rails.root.to_s]
56
57
  config.validate!
57
58
  config
@@ -1,4 +1,5 @@
1
1
  module Skylight
2
+ # @api private
2
3
  class Subscriber
3
4
  include Util::Logging
4
5
 
@@ -0,0 +1,18 @@
1
+ module Skylight
2
+ # @api private
3
+ module Util
4
+ # Already defined by the native extension so we can't autoload
5
+ require 'skylight/util/clock'
6
+
7
+ autoload :AllocationFree, 'skylight/util/allocation_free'
8
+ autoload :Conversions, 'skylight/util/conversions'
9
+ autoload :Gzip, 'skylight/util/gzip'
10
+ autoload :HTTP, 'skylight/util/http'
11
+ autoload :Inflector, 'skylight/util/inflector'
12
+ autoload :Logging, 'skylight/util/logging'
13
+ autoload :Queue, 'skylight/util/queue'
14
+ autoload :Task, 'skylight/util/task'
15
+ autoload :UniformSample, 'skylight/util/uniform_sample'
16
+ autoload :NativeExtFetcher, 'skylight/util/native_ext_fetcher'
17
+ end
18
+ end
@@ -1,15 +1,17 @@
1
1
  module Skylight
2
- module AllocationFree
3
- def array_find(array)
4
- i = 0
2
+ module Util
3
+ module AllocationFree
4
+ def array_find(array)
5
+ i = 0
5
6
 
6
- while i < array.size
7
- item = array[i]
8
- return item if yield item
9
- i += 1
10
- end
7
+ while i < array.size
8
+ item = array[i]
9
+ return item if yield item
10
+ i += 1
11
+ end
11
12
 
12
- nil
13
+ nil
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -22,6 +22,9 @@ module Skylight
22
22
  attr_accessor :authentication, :config
23
23
  attr_reader :host, :port
24
24
 
25
+ class StartError < StandardError; end
26
+ class ReadResponseError < StandardError; end
27
+
25
28
  def initialize(config, service = :report)
26
29
  @config = config
27
30
  @ssl = config["#{service}.ssl"]
@@ -83,6 +86,25 @@ module Skylight
83
86
  type.new(endpoint, headers)
84
87
  end
85
88
 
89
+ def start(http)
90
+ begin
91
+ client = http.start
92
+ rescue => e
93
+ # TODO: Retry here
94
+ raise StartError, e.inspect
95
+ end
96
+
97
+ yield client
98
+ ensure
99
+ client.finish if client
100
+ end
101
+
102
+ def read_code_and_body(res)
103
+ code, body = res.code, res.body
104
+ rescue Net::ReadTimeout, Timeout::Error, EOFError => e
105
+ raise ReadResponseError, e.inspect
106
+ end
107
+
86
108
  def execute(req, body=nil)
87
109
  t { fmt "executing HTTP request; host=%s; port=%s; path=%s, body=%s",
88
110
  @host, @port, req.path, body && body.bytesize }
@@ -104,15 +126,16 @@ module Skylight
104
126
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
105
127
  end
106
128
 
107
- http.start do |client|
129
+ start(http) do |client|
108
130
  res = client.request(req)
131
+ code, body = read_code_and_body(res)
109
132
 
110
- unless res.code =~ /2\d\d/
111
- debug "server responded with #{res.code}"
112
- t { fmt "body=%s", res.body }
133
+ unless code =~ /2\d\d/
134
+ debug "server responded with #{code}"
135
+ t { fmt "body=%s", body }
113
136
  end
114
137
 
115
- Response.new(res.code.to_i, res, res.body)
138
+ Response.new(code.to_i, res, body)
116
139
  end
117
140
  rescue Exception => e
118
141
  error "http %s %s failed; error=%s; msg=%s", req.method, req.path, e.class, e.message
@@ -18,45 +18,33 @@ module Skylight
18
18
  class FetchError < StandardError; end
19
19
 
20
20
  def self.fetch(opts = {})
21
- platform = Gem::Platform.local
22
-
23
21
  fetcher = new(
24
22
  BASE_URL,
25
23
  opts[:target],
26
24
  opts[:version],
27
- opts[:checksums],
28
- opts[:cpu] || platform.cpu,
29
- opts[:os] || platform.os,
25
+ opts[:checksum],
26
+ opts[:arch],
30
27
  opts[:required],
31
28
  opts[:logger] || Logger.new(STDOUT))
32
29
 
33
30
  fetcher.fetch
34
31
  end
35
32
 
36
- def initialize(source, target, version, checksums, cpu, os, required, log)
33
+ def initialize(source, target, version, checksum, arch, required, log)
37
34
  raise "source required" unless source
38
- raise "checksums required" unless checksums
39
- raise "cpu required" unless cpu
40
- raise "os required" unless os
35
+ raise "checksum required" unless checksum
36
+ raise "arch required" unless arch
41
37
 
42
38
  @source = source
43
39
  @target = target
44
40
  @version = version
45
- @checksums = checksums
41
+ @checksum = checksum
46
42
  @required = required
47
- @arch = "#{os}-#{cpu}"
43
+ @arch = arch
48
44
  @log = log
49
45
  end
50
46
 
51
47
  def fetch
52
- # Ensure that the requested arch is valid
53
- unless @checksums[@arch]
54
- maybe_raise "no checksum entry for requested architecture -- " \
55
- "this probably means the requested architecture is not supported; " \
56
- "arch=#{@arch}; available=#{@checksums.keys}"
57
- return
58
- end
59
-
60
48
  log "fetching native ext; curr-platform=#{Gem::Platform.local.to_s}; " \
61
49
  "requested-arch=#{@arch}; version=#{@version}"
62
50
 
@@ -81,8 +69,15 @@ module Skylight
81
69
  archive
82
70
  end
83
71
 
84
- def self.http_get(host, port, use_ssl, path)
85
- Net::HTTP.start(host, port, use_ssl: use_ssl) do |http|
72
+ def http_get(host, port, use_ssl, path)
73
+ if http_proxy = ENV['HTTP_PROXY'] || ENV['http_proxy']
74
+ log "connecting with proxy: #{http_proxy}"
75
+ uri = URI.parse(http_proxy)
76
+ p_host, p_port = uri.host, uri.port
77
+ p_user, p_pass = uri.userinfo.split(/:/) if uri.userinfo
78
+ end
79
+
80
+ Net::HTTP.start(host, port, p_host, p_port, p_user, p_pass, use_ssl: use_ssl) do |http|
86
81
  case response = http.get(path)
87
82
  when Net::HTTPSuccess
88
83
  return [ :success, response.body ]
@@ -107,7 +102,7 @@ module Skylight
107
102
  begin
108
103
  host, port, use_ssl, path = deconstruct_uri(uri)
109
104
 
110
- status, body = NativeExtFetcher.http_get(host, port, use_ssl, path)
105
+ status, body = http_get(host, port, use_ssl, path)
111
106
 
112
107
  case status
113
108
  when :success
@@ -130,7 +125,7 @@ module Skylight
130
125
  rescue => e
131
126
  remaining_attempts -= 1
132
127
 
133
- log "failed to fetch native extension; uri=#{uri}; msg=#{e.message}; remaining-attempts=#{remaining_attempts}", e
128
+ error "failed to fetch native extension; uri=#{uri}; msg=#{e.message}; remaining-attempts=#{remaining_attempts}", e
134
129
 
135
130
  if remaining_attempts > 0
136
131
  sleep 2
@@ -146,11 +141,7 @@ module Skylight
146
141
  end
147
142
 
148
143
  def verify_checksum(archive)
149
- unless expected = @checksums[@arch]
150
- log "no checksum provided; arch=#{@arch}"
151
- return false
152
- end
153
-
144
+ expected = @checksum
154
145
  actual = Digest::SHA2.hexdigest(archive)
155
146
 
156
147
  unless expected == actual
@@ -178,18 +169,23 @@ module Skylight
178
169
  end
179
170
 
180
171
  def maybe_raise(err)
181
- log err
172
+ error err
182
173
 
183
174
  if @required
184
175
  raise err
185
176
  end
186
177
  end
187
178
 
188
- def log(msg, e = nil)
179
+ def log(msg)
189
180
  msg = "[SKYLIGHT] #{msg}"
190
- msg << "\n#{e.backtrace.join("\n")}" if e
191
181
  @log.info msg
192
182
  end
183
+
184
+ def error(msg, e=nil)
185
+ msg = "[SKYLIGHT] #{msg}"
186
+ msg << "\n#{e.backtrace.join("\n")}" if e
187
+ @log.error msg
188
+ end
193
189
  end
194
190
  end
195
191
  end
@@ -1,4 +1,4 @@
1
1
  module Skylight
2
- VERSION = '0.3.10'
2
+ VERSION = '0.3.11'
3
3
  end
4
4
 
@@ -1,5 +1,6 @@
1
1
 
2
2
  module Skylight
3
+ # @api private
3
4
  module VM
4
5
  if defined?(JRUBY_VERSION)
5
6
 
@@ -1,4 +1,5 @@
1
1
  module Skylight
2
+ # @api private
2
3
  module Worker
3
4
 
4
5
  # === Constants
@@ -52,7 +52,7 @@ module Skylight
52
52
  report = {
53
53
  "hostname" => config[:'hostname'],
54
54
  "host.info" => RbConfig::CONFIG['arch'],
55
- "ruby.version" => RUBY_VERSION,
55
+ "ruby.version" => "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}",
56
56
  "ruby.engine" => RUBY_ENGINE,
57
57
  "skylight.version" => Skylight::VERSION
58
58
  }
@@ -204,7 +204,8 @@ module Skylight
204
204
  sanity_check
205
205
  end
206
206
 
207
- if @process_mem_gauge.call > max_memory
207
+ memory_usage = @process_mem_gauge.call
208
+ if memory_usage > max_memory
208
209
  raise WorkerStateError, "Memory limit exceeded: #{memory_usage} (max: #{max_memory})"
209
210
  end
210
211
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.10
4
+ version: 0.3.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilde, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-08 00:00:00.000000000 Z
11
+ date: 2014-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -47,6 +47,7 @@ files:
47
47
  - lib/skylight/compat.rb
48
48
  - lib/skylight/config.rb
49
49
  - lib/skylight/data/cacert.pem
50
+ - lib/skylight/formatters.rb
50
51
  - lib/skylight/formatters/http.rb
51
52
  - lib/skylight/gc.rb
52
53
  - lib/skylight/helpers.rb
@@ -56,6 +57,7 @@ files:
56
57
  - lib/skylight/messages/hello.rb
57
58
  - lib/skylight/messages/trace.rb
58
59
  - lib/skylight/messages/trace_envelope.rb
60
+ - lib/skylight/metrics.rb
59
61
  - lib/skylight/metrics/ewma.rb
60
62
  - lib/skylight/metrics/meter.rb
61
63
  - lib/skylight/metrics/process_cpu_gauge.rb
@@ -77,6 +79,7 @@ files:
77
79
  - lib/skylight/probes/net_http.rb
78
80
  - lib/skylight/railtie.rb
79
81
  - lib/skylight/subscriber.rb
82
+ - lib/skylight/util.rb
80
83
  - lib/skylight/util/allocation_free.rb
81
84
  - lib/skylight/util/clock.rb
82
85
  - lib/skylight/util/conversions.rb
@@ -167,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
170
  version: '0'
168
171
  requirements: []
169
172
  rubyforge_project:
170
- rubygems_version: 2.2.1
173
+ rubygems_version: 2.2.2
171
174
  signing_key:
172
175
  specification_version: 4
173
176
  summary: Skylight is a ruby application monitoring tool. Currently in closed beta.