skylight 0.3.7 → 0.3.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/ext/libskylight.yml +3 -3
- data/ext/skylight_native.c +0 -41
- data/lib/skylight.rb +8 -0
- data/lib/skylight/config.rb +44 -41
- data/lib/skylight/metrics/ewma.rb +69 -0
- data/lib/skylight/metrics/meter.rb +58 -0
- data/lib/skylight/metrics/process_cpu_gauge.rb +65 -0
- data/lib/skylight/metrics/process_mem_gauge.rb +34 -0
- data/lib/skylight/util/clock.rb +13 -7
- data/lib/skylight/util/conversions.rb +9 -0
- data/lib/skylight/util/http.rb +6 -4
- data/lib/skylight/util/native_ext_fetcher.rb +1 -1
- data/lib/skylight/util/task.rb +21 -5
- data/lib/skylight/vendor/cli/highline.rb +42 -20
- data/lib/skylight/vendor/cli/highline/menu.rb +6 -23
- data/lib/skylight/vendor/cli/highline/question.rb +20 -14
- data/lib/skylight/vendor/cli/highline/string_extensions.rb +19 -39
- data/lib/skylight/vendor/cli/highline/system_extensions.rb +28 -4
- data/lib/skylight/version.rb +1 -1
- data/lib/skylight/worker.rb +8 -6
- data/lib/skylight/worker/builder.rb +1 -1
- data/lib/skylight/worker/collector.rb +57 -16
- data/lib/skylight/worker/connection.rb +14 -2
- data/lib/skylight/worker/connection_set.rb +56 -0
- data/lib/skylight/worker/metrics_reporter.rb +103 -0
- data/lib/skylight/worker/server.rb +35 -36
- metadata +23 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21e17f0c6b492a15fe9be1823c16121ffa55ffbb
|
4
|
+
data.tar.gz: 000df33e16f6d5cd9c8e007e96f20d0a7fac89cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bc55e53b477093f2239a954aa2892a14b34cf7a49d85d48c83c77a04348b09be58f6529fd6ce0e58a09dc9662f801ba890388390498ddf7045dfd83cb8250aa
|
7
|
+
data.tar.gz: 8635a462ded00edf9e8cdf8c05919a64201a7f9d7e5b39a4cb107b89454635602cd1ef2a655fe3b2a989c403f90d782423d01cbbed6af202c2c84e72dbfe241a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.3.8 (April 3, 2014)
|
2
|
+
|
3
|
+
* Update vendored highline to 1.6.21
|
4
|
+
* Send more information with exceptions for easier debugging
|
5
|
+
* Instrument and report internal agent metrics for easier debugging
|
6
|
+
* Fix bug with tracking request counts per endpoint
|
7
|
+
|
8
|
+
## 0.3.7 (March 31, 2014)
|
9
|
+
|
10
|
+
* Use a default event category if none passed to Skylight.instrument
|
11
|
+
* Fix bugs around disabling the agent
|
12
|
+
* Fix native extension compilation bugs
|
13
|
+
|
1
14
|
## 0.3.6 (March 27, 2014)
|
2
15
|
|
3
16
|
* Shorter token validation timeout
|
data/ext/libskylight.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
---
|
2
|
-
version: "
|
2
|
+
version: "f2a0e15"
|
3
3
|
checksums:
|
4
|
-
linux-x86_64: "
|
5
|
-
linux-x86: "
|
4
|
+
linux-x86_64: "a99d5542893418b0a5b6b53a599b2c2a07dc8186491181f6dbe0ccfab03dbed4"
|
5
|
+
linux-x86: "a4db4dfbaaa1181e74e6756f4d56ba00fdf4b88e54476294086e7e27bf0c3cdc"
|
6
6
|
|
data/ext/skylight_native.c
CHANGED
@@ -428,46 +428,6 @@ static VALUE trace_serialize(VALUE self) {
|
|
428
428
|
return rb_string;
|
429
429
|
}
|
430
430
|
|
431
|
-
static VALUE trace_span_add_annotation(VALUE self, VALUE rb_span_id, VALUE parent, VALUE rb_key, VALUE value) {
|
432
|
-
uint32_t *parent_id = NULL;
|
433
|
-
RustSlice rs_key;
|
434
|
-
RustSlice *key = NULL;
|
435
|
-
uint32_t new_id, parent_int;
|
436
|
-
|
437
|
-
My_Struct(trace, RustTrace, freedTrace);
|
438
|
-
|
439
|
-
CHECK_TYPE(rb_span_id, T_FIXNUM);
|
440
|
-
uint32_t span_id = FIX2UINT(rb_span_id);
|
441
|
-
|
442
|
-
if (parent != Qnil) {
|
443
|
-
CHECK_TYPE(parent, T_FIXNUM);
|
444
|
-
parent_int = FIX2UINT(parent);
|
445
|
-
parent_id = &parent_int;
|
446
|
-
}
|
447
|
-
|
448
|
-
if (rb_key != Qnil) {
|
449
|
-
CHECK_TYPE(rb_key, T_STRING);
|
450
|
-
|
451
|
-
rs_key = STR2SLICE(rb_key);
|
452
|
-
key = &rs_key;
|
453
|
-
}
|
454
|
-
|
455
|
-
if (TYPE(value) == T_FIXNUM) {
|
456
|
-
CHECK_FFI(skylight_trace_add_annotation_int(trace, span_id, parent_id, key, NUM2LL(value)), "Could not add int annotation");
|
457
|
-
} else if (TYPE(value) == T_FLOAT) {
|
458
|
-
CHECK_FFI(skylight_trace_add_annotation_double(trace, span_id, parent_id, key, NUM2DBL(value)), "Could not add double annotation");
|
459
|
-
} else if (TYPE(value) == T_STRING) {
|
460
|
-
CHECK_FFI(skylight_trace_add_annotation_string(trace, span_id, parent_id, key, STR2SLICE(value)), "Could not add string annotation");
|
461
|
-
} else if (TYPE(value) == T_SYMBOL && value == ID2SYM(rb_intern("nested"))) {
|
462
|
-
CHECK_FFI(skylight_trace_add_annotation_nested(trace, span_id, parent_id, key, &new_id), "Could not add nested annotation");
|
463
|
-
return ULL2NUM(new_id);
|
464
|
-
} else {
|
465
|
-
rb_raise(rb_eArgError, "You must pass an integer, string or :nested to native_span_add_annotation");
|
466
|
-
}
|
467
|
-
|
468
|
-
return Qnil;
|
469
|
-
}
|
470
|
-
|
471
431
|
/**
|
472
432
|
* class Skylight::Batch
|
473
433
|
*/
|
@@ -564,7 +524,6 @@ void Init_skylight_native() {
|
|
564
524
|
rb_define_method(rb_cTrace, "native_stop_span", trace_stop_span, 2);
|
565
525
|
rb_define_method(rb_cTrace, "native_span_set_title", trace_span_set_title, 2);
|
566
526
|
rb_define_method(rb_cTrace, "native_span_set_description", trace_span_set_description, 2);
|
567
|
-
rb_define_method(rb_cTrace, "native_span_add_annotation", trace_span_add_annotation, 4);
|
568
527
|
|
569
528
|
rb_cBatch = rb_define_class_under(rb_mSkylight, "Batch", rb_cObject);
|
570
529
|
rb_define_singleton_method(rb_cBatch, "native_new", batch_new, 2);
|
data/lib/skylight.rb
CHANGED
@@ -81,9 +81,17 @@ module Skylight
|
|
81
81
|
autoload :Subscriber, 'skylight/subscriber'
|
82
82
|
autoload :Worker, 'skylight/worker'
|
83
83
|
|
84
|
+
module Metrics
|
85
|
+
autoload :Meter, 'skylight/metrics/meter'
|
86
|
+
autoload :EWMA, 'skylight/metrics/ewma'
|
87
|
+
autoload :ProcessMemGauge, 'skylight/metrics/process_mem_gauge'
|
88
|
+
autoload :ProcessCpuGauge, 'skylight/metrics/process_cpu_gauge'
|
89
|
+
end
|
90
|
+
|
84
91
|
module Util
|
85
92
|
require 'skylight/util/clock'
|
86
93
|
|
94
|
+
autoload :Conversions, 'skylight/util/conversions'
|
87
95
|
autoload :Gzip, 'skylight/util/gzip'
|
88
96
|
autoload :HTTP, 'skylight/util/http'
|
89
97
|
autoload :Inflector, 'skylight/util/inflector'
|
data/lib/skylight/config.rb
CHANGED
@@ -19,50 +19,53 @@ module Skylight
|
|
19
19
|
|
20
20
|
# Map environment variable keys with Skylight configuration keys
|
21
21
|
ENV_TO_KEY = {
|
22
|
-
'ROOT'
|
23
|
-
'LOG_FILE'
|
24
|
-
'LOG_LEVEL'
|
25
|
-
'APPLICATION'
|
26
|
-
'AUTHENTICATION'
|
27
|
-
'HOSTNAME'
|
28
|
-
'SKIP_VALIDATION'
|
29
|
-
'AGENT_INTERVAL'
|
30
|
-
'AGENT_KEEPALIVE'
|
31
|
-
'AGENT_SAMPLE_SIZE'
|
32
|
-
'AGENT_SOCKFILE_PATH'
|
33
|
-
'AGENT_STRATEGY'
|
34
|
-
'AGENT_MAX_MEMORY'
|
35
|
-
'REPORT_HOST'
|
36
|
-
'REPORT_PORT'
|
37
|
-
'REPORT_SSL'
|
38
|
-
'REPORT_DEFLATE'
|
39
|
-
'ACCOUNTS_HOST'
|
40
|
-
'ACCOUNTS_PORT'
|
41
|
-
'ACCOUNTS_SSL'
|
42
|
-
'ACCOUNTS_DEFLATE'
|
43
|
-
'ME_AUTHENTICATION'
|
44
|
-
'ME_CREDENTIALS_PATH'
|
45
|
-
'
|
46
|
-
'
|
22
|
+
'ROOT' => :'root',
|
23
|
+
'LOG_FILE' => :'log_file',
|
24
|
+
'LOG_LEVEL' => :'log_level',
|
25
|
+
'APPLICATION' => :'application',
|
26
|
+
'AUTHENTICATION' => :'authentication',
|
27
|
+
'HOSTNAME' => :'hostname',
|
28
|
+
'SKIP_VALIDATION' => :'skip_validation',
|
29
|
+
'AGENT_INTERVAL' => :'agent.interval',
|
30
|
+
'AGENT_KEEPALIVE' => :'agent.keepalive',
|
31
|
+
'AGENT_SAMPLE_SIZE' => :'agent.sample',
|
32
|
+
'AGENT_SOCKFILE_PATH' => :'agent.sockfile_path',
|
33
|
+
'AGENT_STRATEGY' => :'agent.strategy',
|
34
|
+
'AGENT_MAX_MEMORY' => :'agent.max_memory',
|
35
|
+
'REPORT_HOST' => :'report.host',
|
36
|
+
'REPORT_PORT' => :'report.port',
|
37
|
+
'REPORT_SSL' => :'report.ssl',
|
38
|
+
'REPORT_DEFLATE' => :'report.deflate',
|
39
|
+
'ACCOUNTS_HOST' => :'accounts.host',
|
40
|
+
'ACCOUNTS_PORT' => :'accounts.port',
|
41
|
+
'ACCOUNTS_SSL' => :'accounts.ssl',
|
42
|
+
'ACCOUNTS_DEFLATE' => :'accounts.deflate',
|
43
|
+
'ME_AUTHENTICATION' => :'me.authentication',
|
44
|
+
'ME_CREDENTIALS_PATH' => :'me.credentials_path',
|
45
|
+
'METRICS_REPORT_INTERVAL' => :'metrics.report_interval',
|
46
|
+
'TEST_CONSTANT_FLUSH' => :'test.constant_flush',
|
47
|
+
'TEST_IGNORE_TOKEN' => :'test.ignore_token' }
|
47
48
|
|
48
49
|
# Default values for Skylight configuration keys
|
49
50
|
DEFAULTS = {
|
50
|
-
:'log_file'
|
51
|
-
:'log_level'
|
52
|
-
:'hostname'
|
53
|
-
:'agent.keepalive'
|
54
|
-
:'agent.interval'
|
55
|
-
:'agent.sample'
|
56
|
-
:'agent.max_memory'
|
57
|
-
:'report.host'
|
58
|
-
:'report.port'
|
59
|
-
:'report.ssl'
|
60
|
-
:'report.deflate'
|
61
|
-
:'accounts.host'
|
62
|
-
:'accounts.port'
|
63
|
-
:'accounts.ssl'
|
64
|
-
:'accounts.deflate'
|
65
|
-
:'me.credentials_path'
|
51
|
+
:'log_file' => '-'.freeze,
|
52
|
+
:'log_level' => 'INFO'.freeze,
|
53
|
+
:'hostname' => default_hostname,
|
54
|
+
:'agent.keepalive' => 60,
|
55
|
+
:'agent.interval' => 5,
|
56
|
+
:'agent.sample' => 200,
|
57
|
+
:'agent.max_memory' => 256, # MB
|
58
|
+
:'report.host' => 'agent.skylight.io'.freeze,
|
59
|
+
:'report.port' => 443,
|
60
|
+
:'report.ssl' => true,
|
61
|
+
:'report.deflate' => true,
|
62
|
+
:'accounts.host' => 'www.skylight.io'.freeze,
|
63
|
+
:'accounts.port' => 443,
|
64
|
+
:'accounts.ssl' => true,
|
65
|
+
:'accounts.deflate' => false,
|
66
|
+
:'me.credentials_path' => '~/.skylight',
|
67
|
+
:'metrics.report_interval' => 60
|
68
|
+
}.freeze
|
66
69
|
|
67
70
|
REQUIRED = {
|
68
71
|
:'authentication' => "authentication token",
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Metrics
|
3
|
+
|
4
|
+
# An exponentially-weighted moving average. Not thread-safe
|
5
|
+
class EWMA
|
6
|
+
include Util::Conversions
|
7
|
+
|
8
|
+
INTERVAL = 5
|
9
|
+
|
10
|
+
# Some common EWMA
|
11
|
+
attr_reader :interval
|
12
|
+
|
13
|
+
def initialize(alpha, interval)
|
14
|
+
@rate = 0.0
|
15
|
+
@alpha = alpha
|
16
|
+
@interval = secs_to_nanos(interval).to_f
|
17
|
+
@uncounted = 0
|
18
|
+
@initialized = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.alpha(minutes, interval = INTERVAL)
|
22
|
+
1 - Math.exp(-interval / 60.0 / minutes)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Some common EWMA
|
26
|
+
|
27
|
+
M1 = alpha(1)
|
28
|
+
M5 = alpha(5)
|
29
|
+
M15 = alpha(15)
|
30
|
+
|
31
|
+
def self.one_minute_ewma
|
32
|
+
EWMA.new M1, INTERVAL
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.five_minute_ewma
|
36
|
+
EWMA.new M5, INTERVAL
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.fifteen_minute_ewma
|
40
|
+
EWMA.new M15, INTERVAL
|
41
|
+
end
|
42
|
+
|
43
|
+
def update(count)
|
44
|
+
@uncounted += count
|
45
|
+
end
|
46
|
+
|
47
|
+
def tick
|
48
|
+
# Compute the rate this interval (aka the num of occurences this tick)
|
49
|
+
instant_rate = @uncounted / @interval
|
50
|
+
|
51
|
+
# Reset the count
|
52
|
+
@uncounted = 0
|
53
|
+
|
54
|
+
if @initialized
|
55
|
+
@rate += (@alpha * (instant_rate - @rate))
|
56
|
+
else
|
57
|
+
@rate = instant_rate
|
58
|
+
@initialized = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get the rate in the requested interval (where the interval is specified
|
63
|
+
# in number of seconds
|
64
|
+
def rate(interval = 1)
|
65
|
+
@rate * secs_to_nanos(interval)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Skylight
|
4
|
+
module Metrics
|
5
|
+
class Meter
|
6
|
+
def initialize(ewma = EWMA.one_minute_ewma, clock = Util::Clock.default)
|
7
|
+
@ewma = ewma
|
8
|
+
@lock = Mutex.new
|
9
|
+
@clock = clock
|
10
|
+
@start_time = @clock.tick
|
11
|
+
@last_tick = @start_time
|
12
|
+
end
|
13
|
+
|
14
|
+
def mark(n = 1)
|
15
|
+
@lock.synchronize do
|
16
|
+
tick_if_necessary
|
17
|
+
@ewma.update(n)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def rate
|
22
|
+
@lock.synchronize do
|
23
|
+
tick_if_necessary
|
24
|
+
@ewma.rate(1)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def call
|
29
|
+
rate
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def tick_if_necessary
|
35
|
+
old_tick = @last_tick
|
36
|
+
new_tick = @clock.tick
|
37
|
+
|
38
|
+
# How far behind are we
|
39
|
+
age = new_tick - old_tick
|
40
|
+
|
41
|
+
if age >= @ewma.interval
|
42
|
+
new_tick = new_tick - age % @ewma.interval
|
43
|
+
|
44
|
+
# Update the last seen tick
|
45
|
+
@last_tick = new_tick
|
46
|
+
|
47
|
+
# Number of missing ticks
|
48
|
+
required_ticks = age / @ewma.interval
|
49
|
+
|
50
|
+
while required_ticks > 0
|
51
|
+
@ewma.tick
|
52
|
+
required_ticks -= 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Metrics
|
3
|
+
class ProcessCpuGauge
|
4
|
+
|
5
|
+
def initialize(cache_for = 5, clock = Util::Clock.default)
|
6
|
+
@value = nil
|
7
|
+
@cache_for = cache_for
|
8
|
+
@last_check_at = 0
|
9
|
+
@clock = clock
|
10
|
+
|
11
|
+
@last_totaltime = nil
|
12
|
+
@last_usagetime = nil
|
13
|
+
@last_utime = nil
|
14
|
+
@last_stime = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(now = @clock.absolute_secs)
|
18
|
+
if !@value || should_check?(now)
|
19
|
+
@value = check
|
20
|
+
@last_check_at = now
|
21
|
+
end
|
22
|
+
|
23
|
+
@value
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def check
|
29
|
+
ret = nil
|
30
|
+
|
31
|
+
statfile = "/proc/stat"
|
32
|
+
pidstatfile = "/proc/#{Process.pid}/stat"
|
33
|
+
|
34
|
+
if File.exist?(statfile) && File.exist?(pidstatfile)
|
35
|
+
cpustats = File.readlines(statfile).grep(/^cpu /).first.split(' ')
|
36
|
+
usagetime = cpustats[1..3].reduce(0){|sum, i| sum + i.to_i }
|
37
|
+
totaltime = usagetime + cpustats[4].to_i
|
38
|
+
|
39
|
+
pidstats = File.read(pidstatfile).split(' ')
|
40
|
+
utime, stime = pidstats[13].to_i, pidstats[14].to_i
|
41
|
+
|
42
|
+
if @last_totaltime && @last_usagetime && @last_utime && @last_stime
|
43
|
+
elapsed = totaltime - @last_totaltime
|
44
|
+
ret = [(usagetime - @last_usagetime).to_f / elapsed,
|
45
|
+
(utime - @last_utime).to_f / elapsed,
|
46
|
+
(stime - @last_stime).to_f / elapsed]
|
47
|
+
end
|
48
|
+
|
49
|
+
@last_totaltime = totaltime
|
50
|
+
@last_usagetime = usagetime
|
51
|
+
@last_utime = utime
|
52
|
+
@last_stime = stime
|
53
|
+
end
|
54
|
+
|
55
|
+
ret
|
56
|
+
rescue Errno::ENOENT
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def should_check?(now)
|
61
|
+
now >= @last_check_at + @cache_for
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Skylight
|
2
|
+
module Metrics
|
3
|
+
class ProcessMemGauge
|
4
|
+
|
5
|
+
def initialize(cache_for = 30, clock = Util::Clock.default)
|
6
|
+
@value = nil
|
7
|
+
@cache_for = cache_for
|
8
|
+
@last_check_at = 0
|
9
|
+
@clock = clock
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(now = @clock.absolute_secs)
|
13
|
+
if !@value || should_check?(now)
|
14
|
+
@value = check
|
15
|
+
@last_check_at = now
|
16
|
+
end
|
17
|
+
|
18
|
+
@value
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def check
|
24
|
+
`ps -o rss= -p #{Process.pid}`.to_i / 1024
|
25
|
+
rescue Errno::ENOENT, Errno::EINTR
|
26
|
+
0
|
27
|
+
end
|
28
|
+
|
29
|
+
def should_check?(now)
|
30
|
+
now >= @last_check_at + @cache_for
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/skylight/util/clock.rb
CHANGED
@@ -2,22 +2,28 @@ module Skylight
|
|
2
2
|
module Util
|
3
3
|
class Clock
|
4
4
|
|
5
|
-
def absolute_secs
|
6
|
-
Time.now.to_i
|
7
|
-
end
|
8
|
-
|
9
5
|
if Skylight.native?
|
10
|
-
def
|
6
|
+
def tick
|
11
7
|
native_hrtime
|
12
8
|
end
|
13
9
|
else
|
14
|
-
|
15
|
-
def nanos
|
10
|
+
def tick
|
16
11
|
now = Time.now
|
17
12
|
now.to_i * 1_000_000_000 + now.usec * 1_000
|
18
13
|
end
|
19
14
|
end
|
20
15
|
|
16
|
+
# TODO: rename to secs
|
17
|
+
def absolute_secs
|
18
|
+
Time.now.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: remove
|
22
|
+
def nanos
|
23
|
+
tick
|
24
|
+
end
|
25
|
+
|
26
|
+
# TODO: remove
|
21
27
|
def secs
|
22
28
|
nanos / 1_000_000_000
|
23
29
|
end
|