skylight 0.3.21 → 0.4.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -4
  3. data/ext/extconf.rb +92 -47
  4. data/ext/libskylight.yml +4 -4
  5. data/ext/skylight_native.c +248 -286
  6. data/lib/skylight.rb +19 -114
  7. data/lib/skylight/api.rb +1 -1
  8. data/lib/skylight/config.rb +176 -146
  9. data/lib/skylight/data/cacert.pem +717 -719
  10. data/lib/skylight/formatters/http.rb +1 -1
  11. data/lib/skylight/instrumenter.rb +28 -35
  12. data/lib/skylight/native.rb +58 -72
  13. data/lib/skylight/normalizers.rb +0 -1
  14. data/lib/skylight/normalizers/active_record/sql.rb +0 -4
  15. data/lib/skylight/probes/excon/middleware.rb +3 -1
  16. data/lib/skylight/probes/net_http.rb +3 -1
  17. data/lib/skylight/subscriber.rb +0 -4
  18. data/lib/skylight/trace.rb +189 -0
  19. data/lib/skylight/util.rb +10 -12
  20. data/lib/skylight/util/hostname.rb +17 -0
  21. data/lib/skylight/util/http.rb +33 -36
  22. data/lib/skylight/util/logging.rb +20 -1
  23. data/lib/skylight/util/multi_io.rb +21 -0
  24. data/lib/skylight/util/native_ext_fetcher.rb +83 -69
  25. data/lib/skylight/util/platform.rb +67 -0
  26. data/lib/skylight/util/ssl.rb +50 -0
  27. data/lib/skylight/version.rb +1 -1
  28. metadata +9 -34
  29. data/ext/rust_support/ruby.h +0 -93
  30. data/ext/skylight.h +0 -85
  31. data/ext/skylight.map +0 -4
  32. data/ext/test/extconf.rb +0 -18
  33. data/ext/test/skylight_native_test.c +0 -82
  34. data/ext/test/skylight_test.h +0 -20
  35. data/lib/skylight/formatters.rb +0 -6
  36. data/lib/skylight/messages.rb +0 -21
  37. data/lib/skylight/messages/error.rb +0 -15
  38. data/lib/skylight/messages/hello.rb +0 -13
  39. data/lib/skylight/messages/trace.rb +0 -179
  40. data/lib/skylight/messages/trace_envelope.rb +0 -19
  41. data/lib/skylight/metrics.rb +0 -9
  42. data/lib/skylight/metrics/ewma.rb +0 -69
  43. data/lib/skylight/metrics/meter.rb +0 -58
  44. data/lib/skylight/metrics/process_cpu_gauge.rb +0 -65
  45. data/lib/skylight/metrics/process_mem_gauge.rb +0 -34
  46. data/lib/skylight/util/conversions.rb +0 -9
  47. data/lib/skylight/util/queue.rb +0 -96
  48. data/lib/skylight/util/task.rb +0 -172
  49. data/lib/skylight/util/uniform_sample.rb +0 -63
  50. data/lib/skylight/worker.rb +0 -19
  51. data/lib/skylight/worker/builder.rb +0 -73
  52. data/lib/skylight/worker/collector.rb +0 -274
  53. data/lib/skylight/worker/connection.rb +0 -87
  54. data/lib/skylight/worker/connection_set.rb +0 -56
  55. data/lib/skylight/worker/embedded.rb +0 -24
  56. data/lib/skylight/worker/metrics_reporter.rb +0 -104
  57. data/lib/skylight/worker/server.rb +0 -336
  58. data/lib/skylight/worker/standalone.rb +0 -421
@@ -1,20 +0,0 @@
1
- #ifndef __SKYLIGHT_TEST_H__
2
- #define __SKYLIGHT_TEST_H__
3
-
4
- #include <stddef.h>
5
- #include <stdint.h>
6
- #include <stdbool.h>
7
-
8
- #include <rust_support/ruby.h>
9
-
10
- typedef void * RustPerson;
11
-
12
- bool skylight_test_numeric_multiply(uint64_t, uint64_t, uint64_t*);
13
- bool skylight_test_strings_reverse(RustSlice, RustString*);
14
-
15
- bool skylight_test_person_new(RustSlice, uint64_t, RustPerson*);
16
- bool skylight_test_person_get_name(RustPerson, RustSlice*);
17
- bool skylight_test_person_get_age(RustPerson, uint64_t*);
18
- bool skylight_test_person_free(RustPerson);
19
-
20
- #endif
@@ -1,6 +0,0 @@
1
- module Skylight
2
- # @api private
3
- module Formatters
4
- autoload :HTTP, 'skylight/formatters/http'
5
- end
6
- end
@@ -1,21 +0,0 @@
1
- module Skylight
2
- # @api private
3
- module Messages
4
- require 'skylight/messages/trace'
5
- require 'skylight/messages/hello'
6
- require 'skylight/messages/error'
7
- require 'skylight/messages/trace_envelope'
8
-
9
- KLASS_TO_ID = {
10
- Skylight::Trace => 0,
11
- Skylight::Hello => 1,
12
- Skylight::Error => 2
13
- }
14
-
15
- ID_TO_KLASS = {
16
- 0 => Skylight::Messages::TraceEnvelope,
17
- 1 => Skylight::Hello,
18
- 2 => Skylight::Error
19
- }
20
- end
21
- end
@@ -1,15 +0,0 @@
1
- module Skylight
2
- module Messages
3
- class Error
4
- def self.deserialize(buf)
5
- decode(buf)
6
- end
7
-
8
- def self.build(group, description, details = nil)
9
- Skylight::Error.native_new(group, description).tap do |error|
10
- error.native_set_details(details) if details
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,13 +0,0 @@
1
- module Skylight
2
- # @api private
3
- module Messages
4
- class Hello
5
- def self.build(version, cmd=[])
6
- Skylight::Hello.native_new(version, 0).tap do |hello|
7
- cmd.each { |part| hello.native_add_cmd_part(part) }
8
- end
9
- end
10
-
11
- end
12
- end
13
- end
@@ -1,179 +0,0 @@
1
- module Skylight
2
- module Messages
3
- class Trace
4
- class Builder
5
- GC_CAT = 'noise.gc'.freeze
6
-
7
- include Util::Logging
8
-
9
- attr_reader :endpoint, :spans, :notifications
10
-
11
- def endpoint=(value)
12
- @endpoint = value.is_a?(String) ? value.freeze : value
13
- @native_builder.native_set_name(value)
14
- end
15
-
16
- def initialize(instrumenter, endpoint, start, cat, title=nil, desc=nil, annot=nil)
17
- raise ArgumentError, 'instrumenter is required' unless instrumenter
18
-
19
- start = normalize_time(start)
20
-
21
- @native_builder = ::Skylight::Trace.native_new(start, "TODO")
22
- @native_builder.native_set_name(endpoint)
23
-
24
- @instrumenter = instrumenter
25
- @endpoint = endpoint
26
- @submitted = false
27
- @start = start
28
-
29
- @notifications = []
30
-
31
- if Hash === title
32
- annot = title
33
- title = desc = nil
34
- elsif Hash === desc
35
- annot = desc
36
- desc = nil
37
- end
38
-
39
- # create the root node
40
- @root = @native_builder.native_start_span(@start, cat)
41
- @native_builder.native_span_set_title(@root, title) if title
42
- @native_builder.native_span_set_description(@root, desc) if desc
43
-
44
- @gc = config.gc.track unless ENV.key?("SKYLIGHT_DISABLE_GC_TRACKING")
45
- end
46
-
47
- def serialize
48
- raise "Can only serialize once" if @serialized
49
- @serialized = true
50
- @native_builder.native_serialize
51
- end
52
-
53
- def config
54
- @instrumenter.config
55
- end
56
-
57
- def record(cat, title=nil, desc=nil, annot=nil)
58
- if Hash === title
59
- annot = title
60
- title = desc = nil
61
- elsif Hash === desc
62
- annot = desc
63
- desc = nil
64
- end
65
-
66
- title.freeze if title.is_a?(String)
67
- desc.freeze if desc.is_a?(String)
68
-
69
- desc = @instrumenter.limited_description(desc)
70
-
71
- time = Util::Clock.nanos - gc_time
72
-
73
- stop(start(time, cat, title, desc), time)
74
-
75
- nil
76
- end
77
-
78
- def instrument(cat, title=nil, desc=nil, annot=nil)
79
- t { "instrument: #{cat}, #{title}" }
80
-
81
- if Hash === title
82
- annot = title
83
- title = desc = nil
84
- elsif Hash === desc
85
- annot = desc
86
- desc = nil
87
- end
88
-
89
- title.freeze if title.is_a?(String)
90
- desc.freeze if desc.is_a?(String)
91
-
92
- original_desc = desc
93
- now = Util::Clock.nanos
94
- desc = @instrumenter.limited_description(desc)
95
-
96
- if desc == Instrumenter::TOO_MANY_UNIQUES
97
- debug "[SKYLIGHT] [#{Skylight::VERSION}] A payload description produced <too many uniques>"
98
- debug "original desc=%s", original_desc
99
- debug "cat=%s, title=%s, desc=%s, annot=%s", cat, title, desc, annot.inspect
100
- end
101
-
102
- start(now - gc_time, cat, title, desc, annot)
103
- end
104
-
105
- def done(span)
106
- return unless span
107
- stop(span, Util::Clock.nanos - gc_time)
108
- end
109
-
110
- def release
111
- return unless @instrumenter.current_trace == self
112
- @instrumenter.current_trace = nil
113
- end
114
-
115
- def traced
116
- time = gc_time
117
- now = Util::Clock.nanos
118
-
119
- if time > 0
120
- t { fmt "tracking GC time; duration=%d", time }
121
- stop(start(now - time, GC_CAT, nil, nil, {}), now)
122
- end
123
-
124
- stop(@root, now)
125
- end
126
-
127
- def submit
128
- t { "submitting trace" }
129
-
130
- if @submitted
131
- t { "already submitted" }
132
- return
133
- end
134
-
135
- release
136
- @submitted = true
137
-
138
- traced
139
-
140
- @instrumenter.process(@native_builder)
141
- rescue Exception => e
142
- error e
143
- t { e.backtrace.join("\n") }
144
- end
145
-
146
- private
147
-
148
- def start(time, cat, title, desc, annot=nil)
149
- span(normalize_time(time), cat, title, desc, annot)
150
- end
151
-
152
- def stop(span, time)
153
- @native_builder.native_stop_span(span, normalize_time(time))
154
- nil
155
- end
156
-
157
- def normalize_time(time)
158
- # At least one customer has extensions that cause integer division to produce rationals.
159
- # Since the native code expects an integer, we force it again.
160
- (time.to_i / 100_000).to_i
161
- end
162
-
163
- def span(time, cat, title=nil, desc=nil, annot=nil)
164
- sp = @native_builder.native_start_span(time, cat.to_s)
165
- @native_builder.native_span_set_title(sp, title.to_s) if title
166
- @native_builder.native_span_set_description(sp, desc.to_s) if desc
167
- sp
168
- end
169
-
170
- def gc_time
171
- return 0 unless @gc
172
- @gc.update
173
- @gc.time
174
- end
175
-
176
- end
177
- end
178
- end
179
- end
@@ -1,19 +0,0 @@
1
- module Skylight
2
- module Messages
3
- class TraceEnvelope
4
- def self.deserialize(data)
5
- new(data)
6
- end
7
-
8
- attr_reader :data
9
-
10
- def initialize(data)
11
- @data = data
12
- end
13
-
14
- def endpoint_name
15
- Skylight::Trace.native_name_from_serialized(@data)
16
- end
17
- end
18
- end
19
- end
@@ -1,9 +0,0 @@
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,69 +0,0 @@
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
@@ -1,58 +0,0 @@
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
@@ -1,65 +0,0 @@
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