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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 727271788a0fddacdf3b7e53451c413023d74a0d
4
- data.tar.gz: 0b911dd320834be2608b7cd294e5aacf395188b7
3
+ metadata.gz: 21e17f0c6b492a15fe9be1823c16121ffa55ffbb
4
+ data.tar.gz: 000df33e16f6d5cd9c8e007e96f20d0a7fac89cb
5
5
  SHA512:
6
- metadata.gz: 425fe8a9ece2086b79e08cadcd7687c1d808ce65e2772c6b3d457c7f5b79c57fe9284d78f9964a7a161e95f67d0e87d2cf4dc89370488d6d7ad7906abec53357
7
- data.tar.gz: bbbe029afd5bfaa9c203ad7103ac818bdebbc95a78b94435ed43344b5a00feb74e7992d75bc8fdca27e1fe63dadb784fcd64ef63abbb41130092c4511988f5ea
6
+ metadata.gz: 5bc55e53b477093f2239a954aa2892a14b34cf7a49d85d48c83c77a04348b09be58f6529fd6ce0e58a09dc9662f801ba890388390498ddf7045dfd83cb8250aa
7
+ data.tar.gz: 8635a462ded00edf9e8cdf8c05919a64201a7f9d7e5b39a4cb107b89454635602cd1ef2a655fe3b2a989c403f90d782423d01cbbed6af202c2c84e72dbfe241a
@@ -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
@@ -1,6 +1,6 @@
1
1
  ---
2
- version: "74fb9b3"
2
+ version: "f2a0e15"
3
3
  checksums:
4
- linux-x86_64: "98b04f7d73c1894cc79621a135b4598a679c421f5ff3eecc652f84ba07258d9c"
5
- linux-x86: "1d4bbd58e319237b18752607d087ce0c895fe99c58482e994abe62a9f07d41dd"
4
+ linux-x86_64: "a99d5542893418b0a5b6b53a599b2c2a07dc8186491181f6dbe0ccfab03dbed4"
5
+ linux-x86: "a4db4dfbaaa1181e74e6756f4d56ba00fdf4b88e54476294086e7e27bf0c3cdc"
6
6
 
@@ -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);
@@ -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'
@@ -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' => :'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
- 'TEST_CONSTANT_FLUSH' => :'test.constant_flush',
46
- 'TEST_IGNORE_TOKEN' => :'test.ignore_token' }
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' => '-'.freeze,
51
- :'log_level' => 'INFO'.freeze,
52
- :'hostname' => default_hostname,
53
- :'agent.keepalive' => 60,
54
- :'agent.interval' => 5,
55
- :'agent.sample' => 200,
56
- :'agent.max_memory' => 256, # MB
57
- :'report.host' => 'agent.skylight.io'.freeze,
58
- :'report.port' => 443,
59
- :'report.ssl' => true,
60
- :'report.deflate' => true,
61
- :'accounts.host' => 'www.skylight.io'.freeze,
62
- :'accounts.port' => 443,
63
- :'accounts.ssl' => true,
64
- :'accounts.deflate' => false,
65
- :'me.credentials_path' => '~/.skylight' }.freeze
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
@@ -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 nanos
6
+ def tick
11
7
  native_hrtime
12
8
  end
13
9
  else
14
- # Implement nanos to work when native extension is not present
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