skylight 0.3.10 → 0.3.11

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 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.