skylight 0.3.7 → 0.3.8
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 +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
|