skylight 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3b26b3f575af56669c5257a37d8d7ca11544aba4
4
- data.tar.gz: 5fb2964195f3d146693f62b6593ff2b0bbf3944d
3
+ metadata.gz: 727271788a0fddacdf3b7e53451c413023d74a0d
4
+ data.tar.gz: 0b911dd320834be2608b7cd294e5aacf395188b7
5
5
  SHA512:
6
- metadata.gz: 5e9759155ce35d86bd96b058788b153544dff9aa73d08cfb4f742ddd5dc2871b4c4c8bc4e4799eb006b59e3e8bb99b89920b98a67698fd601d612793b2f68ec3
7
- data.tar.gz: 0009517b20943ce01703c10210b925f3d687b16e471f7b57af1066bbdeb28e88f3f91937b00a4c4942167f2d7983d89b1621d10891f16962c644965dbf573fb8
6
+ metadata.gz: 425fe8a9ece2086b79e08cadcd7687c1d808ce65e2772c6b3d457c7f5b79c57fe9284d78f9964a7a161e95f67d0e87d2cf4dc89370488d6d7ad7906abec53357
7
+ data.tar.gz: bbbe029afd5bfaa9c203ad7103ac818bdebbc95a78b94435ed43344b5a00feb74e7992d75bc8fdca27e1fe63dadb784fcd64ef63abbb41130092c4511988f5ea
@@ -1,91 +1,89 @@
1
1
  require 'mkmf'
2
- require 'rbconfig'
3
- require 'net/http'
4
- require 'zlib'
5
2
  require 'yaml'
6
- require 'digest/sha2'
3
+ require 'logger'
7
4
 
8
- require_relative '../lib/skylight/version.rb'
5
+ LOG = Logger.new(STDOUT)
6
+ SKYLIGHT_REQUIRED = ENV.key?("SKYLIGHT_REQUIRED") && ENV['SKYLIGHT_REQUIRED'] !~ /^false$/i
9
7
 
10
- checksums = YAML.load_file("checksums.yml")
8
+ require_relative '../lib/skylight/version'
9
+ require_relative '../lib/skylight/util/native_ext_fetcher'
11
10
 
12
- rust_version = "74fb9b3"
11
+ include Skylight::Util
13
12
 
14
- arch = RbConfig::CONFIG["arch"]
13
+ # Handles terminating in the case of a failure. If we have a bug, we do not
14
+ # want to break our customer's deploy, but extconf.rb requires a Makefile to be
15
+ # present upon a successful exit. To satisfy this requirement, we create a
16
+ # dummy Makefile.
17
+ def fail(msg)
18
+ LOG.error msg
15
19
 
16
- url = "https://github.com/skylightio/skylight-rust/releases/download/#{rust_version}/libskylight.#{arch}.a.gz"
20
+ if SKYLIGHT_REQUIRED
21
+ exit 1
22
+ else
23
+ File.open("Makefile", "w") do |file|
24
+ file.puts "default:"
25
+ file.puts "install:"
26
+ end
17
27
 
18
- required = ENV.key?("SKYLIGHT_REQUIRED")
28
+ exit
29
+ end
30
+ end
19
31
 
20
- unless File.exist?("libskylight.a")
21
- puts "[SKYLIGHT] [#{Skylight::VERSION}] Downloading from #{url.inspect}"
22
- location = nil
23
- uri = URI.parse(url)
32
+ libskylight_a = File.expand_path('../libskylight.a', __FILE__)
33
+ libskylight_yml = File.expand_path('../libskylight.yml', __FILE__)
24
34
 
25
- begin
26
- Net::HTTP.start("github.com", 443, use_ssl: true) do |http|
27
- response = http.get(uri.request_uri)
28
- location = response["Location"]
29
- end
35
+ unless File.exist?(libskylight_a)
36
+ # Ensure that libskylight.yml is present and load it
37
+ unless File.exist?(libskylight_yml)
38
+ fail "`#{libskylight_yml}` does not exist"
39
+ end
30
40
 
31
- if location
32
- archive = nil
33
-
34
- uri = URI(location)
35
- Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
36
- response = http.get(uri.request_uri)
37
- archive = response.body
38
- end
39
- else
40
- raise "No location returned" if required
41
- missing_a = true
42
- end
43
- rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
44
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
45
- raise if required
46
- missing_a = true
41
+ unless libskylight_info = YAML.load_file(libskylight_yml)
42
+ fail "`#{libskylight_yml}` does not contain data"
47
43
  end
48
44
 
49
- unless missing_a
50
- expected_checksum = checksums[arch]
51
- actual_checksum = Digest::SHA2.hexdigest(archive)
45
+ unless version = libskylight_info["version"]
46
+ fail "libskylight version missing from `#{libskylight_yml}`"
47
+ end
52
48
 
53
- if expected_checksum == actual_checksum
54
- inflater, dest = Zlib::Inflate.new(32 + Zlib::MAX_WBITS), ""
55
- dest << inflater.inflate(archive)
56
- inflater.close
49
+ unless checksums = libskylight_info["checksums"]
50
+ fail "libskylight checksums missing from `#{libskylight_yml}`"
51
+ end
57
52
 
58
- File.open("libskylight.a", "w") { |file| file.write dest }
59
- else
60
- raise "Checksum mismatched; expected=#{expected_checksum.inspect}; actual=#{actual_checksum.inspect}" if required
61
- missing_a = true
53
+ begin
54
+ res = NativeExtFetcher.fetch(
55
+ version: version,
56
+ target: libskylight_a,
57
+ checksums: checksums,
58
+ required: SKYLIGHT_REQUIRED,
59
+ logger: LOG)
60
+
61
+ unless res
62
+ fail "could not fetch archive -- aborting skylight native extension build"
62
63
  end
64
+ rescue => e
65
+ fail "unable to fetch native extension; msg=#{e.message}\n#{e.backtrace.join("\n")}"
63
66
  end
64
67
  end
65
68
 
66
- if missing_a
67
- puts "[SKYLIGHT] [#{Skylight::VERSION}] Could not download Skylight native code from Github; version=#{rust_version.inspect}; arch=#{arch.inspect}"
69
+ #
70
+ #
71
+ # ===== By this point, libskylight.a is present =====
72
+ #
73
+ #
68
74
 
69
- exit 1 if required
75
+ have_header 'dlfcn.h'
70
76
 
71
- File.open("Makefile", "w") do |file|
72
- file.puts "default:"
73
- file.puts "install:"
74
- end
75
- else
76
- have_header 'dlfcn.h'
77
+ find_library("skylight", "factory", ".")
77
78
 
78
- find_library("skylight", "factory", ".")
79
-
80
- $CFLAGS << " -Werror"
81
- if RbConfig::CONFIG["arch"] =~ /darwin(\d+)?/
82
- $LDFLAGS << " -lpthread"
83
- else
84
- $LDFLAGS << " -Wl,--version-script=skylight.map"
85
- $LDFLAGS << " -lrt -ldl -lm -lpthread"
86
- end
79
+ $CFLAGS << " -Werror"
80
+ if RbConfig::CONFIG["arch"] =~ /darwin(\d+)?/
81
+ $LDFLAGS << " -lpthread"
82
+ else
83
+ $LDFLAGS << " -Wl,--version-script=skylight.map"
84
+ $LDFLAGS << " -lrt -ldl -lm -lpthread"
85
+ end
87
86
 
88
- CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
87
+ CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
89
88
 
90
- create_makefile 'skylight_native', '.'
91
- end
89
+ create_makefile 'skylight_native', '.'
@@ -0,0 +1,6 @@
1
+ ---
2
+ version: "74fb9b3"
3
+ checksums:
4
+ linux-x86_64: "98b04f7d73c1894cc79621a135b4598a679c421f5ff3eecc652f84ba07258d9c"
5
+ linux-x86: "1d4bbd58e319237b18752607d087ce0c895fe99c58482e994abe62a9f07d41dd"
6
+
@@ -0,0 +1,93 @@
1
+ #ifndef __SKYLIGHT_H__
2
+ #define __SKYLIGHT_H__
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+ #include <stdbool.h>
7
+
8
+ /**
9
+ * Rust types
10
+ */
11
+
12
+ typedef struct {
13
+ size_t fill; // in bytes; if zero, heapified
14
+ size_t alloc; // in bytes
15
+ uint8_t data[0];
16
+ } rust_str;
17
+
18
+ typedef struct {
19
+ char * data;
20
+ long len;
21
+ } RustSlice;
22
+
23
+ typedef struct {
24
+ uint8_t discrim;
25
+ RustSlice slice;
26
+ } OptionRustSlice;
27
+
28
+ typedef rust_str * RustString;
29
+ typedef RustString RustVector;
30
+
31
+ /**
32
+ * Externed Rust functions from libskylight
33
+ */
34
+
35
+ typedef void * RustHello;
36
+ typedef void * RustError;
37
+ typedef void * RustTrace;
38
+ typedef void * RustBatch;
39
+
40
+ void factory();
41
+
42
+ // Rust skylight_hello prototypes
43
+ bool skylight_hello_new(RustSlice, uint32_t, RustHello*);
44
+ bool skylight_hello_free(RustHello);
45
+ bool skylight_hello_load(RustSlice, RustHello*);
46
+ bool skylight_hello_cmd_add(RustHello, RustSlice);
47
+ bool skylight_hello_get_version(RustHello, RustSlice*);
48
+ bool skylight_hello_cmd_length(RustHello, uint32_t*);
49
+ bool skylight_hello_get_cmd(RustHello, int, RustSlice*);
50
+ bool skylight_hello_serialize_into_new_buffer(RustHello, RustString*);
51
+ bool skylight_high_res_time(uint64_t*);
52
+
53
+ // Rust skylight_trace prototypes
54
+ bool skylight_trace_new(uint64_t, RustSlice, RustTrace*);
55
+ bool skylight_trace_free(RustTrace);
56
+ bool skylight_trace_load(RustSlice, RustTrace*);
57
+ bool skylight_trace_name_from_serialized_into_new_buffer(RustSlice, RustString*);
58
+ bool skylight_trace_get_started_at(RustTrace, uint64_t*);
59
+ bool skylight_trace_set_name(RustTrace, RustSlice);
60
+ bool skylight_trace_get_name(RustTrace, RustSlice*);
61
+ bool skylight_trace_get_uuid(RustTrace, RustSlice*);
62
+ bool skylight_trace_start_span(RustTrace, uint64_t, RustSlice, uint32_t*);
63
+ bool skylight_trace_stop_span(RustTrace, uint32_t, uint64_t);
64
+ bool skylight_trace_serialize_into_new_buffer(RustTrace, RustString*);
65
+ bool skylight_trace_span_set_title(RustTrace, uint64_t, RustSlice);
66
+ bool skylight_trace_span_set_description(RustTrace, uint64_t, RustSlice);
67
+
68
+ // Trace annotation methods
69
+ bool skylight_trace_add_annotation_int(RustTrace, uint32_t, uint32_t*, RustSlice*, int64_t);
70
+ bool skylight_trace_add_annotation_double(RustTrace, uint32_t, uint32_t*, RustSlice*, double);
71
+ bool skylight_trace_add_annotation_string(RustTrace, uint32_t, uint32_t*, RustSlice*, RustSlice);
72
+ bool skylight_trace_add_annotation_nested(RustTrace, uint32_t, uint32_t*, RustSlice*, uint32_t*);
73
+
74
+ // Batch methods
75
+ bool skylight_batch_new(uint32_t, RustString, RustBatch*);
76
+ bool skylight_batch_free(RustBatch);
77
+ bool skylight_batch_set_endpoint_count(RustBatch, RustSlice, uint64_t);
78
+ bool skylight_batch_move_in(RustBatch, RustString);
79
+ bool skylight_batch_serialize_into_new_buffer(RustBatch, RustString*);
80
+
81
+ // Error methods
82
+ bool skylight_error_new(RustSlice, RustSlice, RustError*);
83
+ bool skylight_error_free(RustError);
84
+ bool skylight_error_load(RustSlice, RustError*);
85
+ bool skylight_error_get_group(RustError, RustSlice*);
86
+ bool skylight_error_get_description(RustError, RustSlice*);
87
+ bool skylight_error_get_details(RustError, RustSlice*);
88
+ bool skylight_error_set_details(RustError, RustSlice);
89
+ bool skylight_error_serialize_into_new_buffer(RustError, RustString*);
90
+
91
+ void skylight_free_buf(RustString);
92
+
93
+ #endif
@@ -1,5 +1,5 @@
1
+ #include <skylight.h>
1
2
  #include <ruby.h>
2
- #include <stdbool.h>
3
3
 
4
4
  #ifdef HAVE_RUBY_ENCODING_H
5
5
  #include <ruby/encoding.h>
@@ -49,104 +49,50 @@
49
49
  } \
50
50
 
51
51
  #define CHECK_FFI(success, message) \
52
- { \
52
+ ({ \
53
53
  if (!(success)) \
54
54
  rb_raise(rb_eRuntimeError, message); \
55
- } \
56
-
57
- /**
58
- * Rust types
59
- */
60
-
61
- typedef struct {
62
- size_t fill; // in bytes; if zero, heapified
63
- size_t alloc; // in bytes
64
- uint8_t data[0];
65
- } rust_str;
66
-
67
- typedef struct {
68
- char * data;
69
- long len;
70
- } RustSlice;
71
-
72
- typedef rust_str * RustString;
73
- typedef RustString RustVector;
74
- #define VEC2STR(vector) ({ RustVector v = (vector); VALUE ret = rb_str_new((char *)v->data, v->fill); ret; })
75
- #define SLICE2STR(slice) ({ RustSlice s = (slice); VALUE str = rb_str_new(s.data, s.len); rb_enc_associate(str, rb_utf8_encoding()); str; })
76
- #define STR2SLICE(string) ({ RustSlice s; VALUE rb_str = (string); s.data = RSTRING_PTR(rb_str); s.len = RSTRING_LEN(rb_str); s; })
77
-
78
- #define UnwrapOption(T, val, transform) ({ T * v = (val); VALUE ret; if (v == NULL) ret = Qnil; else ret = transform(*v); ret; })
79
-
80
- typedef struct {
81
- uint8_t discrim;
82
- RustSlice slice;
83
- } OptionRustSlice;
55
+ })
56
+
57
+ #define VEC2STR(vector) \
58
+ ({ \
59
+ RustVector v = (vector); \
60
+ VALUE ret = rb_str_new((char *)v->data, v->fill); \
61
+ ret; \
62
+ })
63
+
64
+ #define SLICE2STR(slice) \
65
+ ({ \
66
+ RustSlice s = (slice); \
67
+ VALUE str = rb_str_new(s.data, s.len); \
68
+ rb_enc_associate(str, rb_utf8_encoding()); \
69
+ str; \
70
+ })
71
+
72
+ #define STR2SLICE(string) \
73
+ ({ \
74
+ RustSlice s; \
75
+ VALUE rb_str = (string); \
76
+ s.data = RSTRING_PTR(rb_str); \
77
+ s.len = RSTRING_LEN(rb_str); \
78
+ s; \
79
+ })
80
+
81
+ #define UnwrapOption(T, val, transform) \
82
+ ({ \
83
+ T * v = (val); \
84
+ VALUE ret; \
85
+ if (v == NULL) { \
86
+ ret = Qnil; \
87
+ } \
88
+ else { \
89
+ ret = transform(*v); \
90
+ } \
91
+ ret; \
92
+ })
84
93
 
85
94
  #define IsNone(val) val.discrim == 0
86
95
 
87
- /**
88
- * Externed Rust functions from libskylight
89
- */
90
-
91
- typedef void * RustHello;
92
- typedef void * RustError;
93
- typedef void * RustTrace;
94
- typedef void * RustBatch;
95
-
96
- void factory();
97
-
98
-
99
- // Rust skylight_hello prototypes
100
- bool skylight_hello_new(RustSlice, uint32_t, RustHello*);
101
- bool skylight_hello_free(RustHello);
102
- bool skylight_hello_load(RustSlice, RustHello*);
103
- bool skylight_hello_cmd_add(RustHello, RustSlice);
104
- bool skylight_hello_get_version(RustHello, RustSlice*);
105
- bool skylight_hello_cmd_length(RustHello, uint32_t*);
106
- bool skylight_hello_get_cmd(RustHello, int, RustSlice*);
107
- bool skylight_hello_serialize_into_new_buffer(RustHello, RustString*);
108
- bool skylight_high_res_time(uint64_t*);
109
-
110
- // Rust skylight_trace prototypes
111
- bool skylight_trace_new(uint64_t, RustSlice, RustTrace*);
112
- bool skylight_trace_free(RustTrace);
113
- bool skylight_trace_load(RustSlice, RustTrace*);
114
- bool skylight_trace_name_from_serialized_into_new_buffer(RustSlice, RustString*);
115
- bool skylight_trace_get_started_at(RustTrace, uint64_t*);
116
- bool skylight_trace_set_name(RustTrace, RustSlice);
117
- bool skylight_trace_get_name(RustTrace, RustSlice*);
118
- bool skylight_trace_get_uuid(RustTrace, RustSlice*);
119
- bool skylight_trace_start_span(RustTrace, uint64_t, RustSlice, uint32_t*);
120
- bool skylight_trace_stop_span(RustTrace, uint32_t, uint64_t);
121
- bool skylight_trace_serialize_into_new_buffer(RustTrace, RustString*);
122
- bool skylight_trace_span_set_title(RustTrace, uint64_t, RustSlice);
123
- bool skylight_trace_span_set_description(RustTrace, uint64_t, RustSlice);
124
-
125
- // Trace annotation methods
126
- bool skylight_trace_add_annotation_int(RustTrace, uint32_t, uint32_t*, RustSlice*, int64_t);
127
- bool skylight_trace_add_annotation_double(RustTrace, uint32_t, uint32_t*, RustSlice*, double);
128
- bool skylight_trace_add_annotation_string(RustTrace, uint32_t, uint32_t*, RustSlice*, RustSlice);
129
- bool skylight_trace_add_annotation_nested(RustTrace, uint32_t, uint32_t*, RustSlice*, uint32_t*);
130
-
131
- // Batch methods
132
- bool skylight_batch_new(uint32_t, RustString, RustBatch*);
133
- bool skylight_batch_free(RustBatch);
134
- bool skylight_batch_set_endpoint_count(RustBatch, RustSlice, uint64_t);
135
- bool skylight_batch_move_in(RustBatch, RustString);
136
- bool skylight_batch_serialize_into_new_buffer(RustBatch, RustString*);
137
-
138
- // Error methods
139
- bool skylight_error_new(RustSlice, RustSlice, RustError*);
140
- bool skylight_error_free(RustError);
141
- bool skylight_error_load(RustSlice, RustError*);
142
- bool skylight_error_get_group(RustError, RustSlice*);
143
- bool skylight_error_get_description(RustError, RustSlice*);
144
- bool skylight_error_get_details(RustError, RustSlice*);
145
- bool skylight_error_set_details(RustError, RustSlice);
146
- bool skylight_error_serialize_into_new_buffer(RustError, RustString*);
147
-
148
- void skylight_free_buf(RustString);
149
-
150
96
  /**
151
97
  * Convert Ruby String to a Rust String
152
98
  */
@@ -154,7 +100,13 @@ void skylight_free_buf(RustString);
154
100
  RustString skylight_slice_to_owned(RustSlice);
155
101
  RustString skylight_bytes_to_new_vec(uint8_t*, uint64_t);
156
102
 
157
- #define STR2RUST(string) ({ VALUE rb_str = (string); skylight_bytes_to_new_vec((uint8_t*)RSTRING_PTR(rb_str), RSTRING_LEN(rb_str)); })
103
+ #define STR2RUST(string) \
104
+ ({ \
105
+ VALUE rb_str = (string); \
106
+ skylight_bytes_to_new_vec( \
107
+ (uint8_t*) RSTRING_PTR(rb_str), \
108
+ RSTRING_LEN(rb_str)); \
109
+ })
158
110
 
159
111
  /**
160
112
  * Ruby types defined here
@@ -2,25 +2,32 @@ require 'rbconfig'
2
2
  require 'socket'
3
3
  require 'skylight/version'
4
4
 
5
- begin
6
- unless ENV["SKYLIGHT_DISABLE_AGENT"]
7
- require 'skylight_native'
8
- require 'skylight/native'
9
- has_native_ext = true
10
- end
11
- rescue LoadError
12
- if defined?(Rails) && !Rails.env.development? && !Rails.env.test?
13
- 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."
14
- elsif defined?(Rails)
15
- puts "[SKYLIGHT] [#{Skylight::VERSION}] Running Skylight in #{Rails.env} mode. No data will be reported until you deploy your app."
16
- else
17
- puts "[SKYLIGHT] [#{Skylight::VERSION}] Running Skylight in development mode."
18
- end
19
- raise if ENV.key?("SKYLIGHT_REQUIRED")
20
- end
21
-
22
5
  module Skylight
23
6
  TRACE_ENV_KEY = 'SKYLIGHT_ENABLE_TRACE_LOGS'.freeze
7
+ STANDALONE_ENV_KEY = 'SKYLIGHT_STANDALONE'.freeze
8
+ STANDALONE_ENV_VAL = 'server'.freeze
9
+
10
+ # Whether or not the native extension is present
11
+ @@has_native_ext = false
12
+
13
+ def self.native?
14
+ @@has_native_ext
15
+ end
16
+
17
+ begin
18
+ unless ENV["SKYLIGHT_DISABLE_AGENT"]
19
+ # First attempt to require the native extension
20
+ require 'skylight_native'
21
+
22
+ # If nothing was thrown, then the native extension is present
23
+ @@has_native_ext = true
24
+
25
+ # Require ruby support for the native extension
26
+ require 'skylight/native'
27
+ end
28
+ rescue LoadError
29
+ raise if ENV.key?("SKYLIGHT_REQUIRED")
30
+ end
24
31
 
25
32
  autoload :Api, 'skylight/api'
26
33
  autoload :CLI, 'skylight/cli'
@@ -42,16 +49,16 @@ module Skylight
42
49
  if defined?(Rails)
43
50
  require 'skylight/railtie'
44
51
  end
45
- end
46
-
47
- if has_native_ext
48
52
 
49
- module Skylight
50
- STANDALONE_ENV_KEY = 'SKYLIGHT_STANDALONE'.freeze
51
- STANDALONE_ENV_VAL = 'server'.freeze
52
-
53
- def self.native?
54
- true
53
+ def self.warn_skylight_native_missing
54
+ # TODO: Dumping the error messages this way is pretty hacky
55
+ if defined?(Rails) && !Rails.env.development? && !Rails.env.test?
56
+ 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."
57
+ elsif defined?(Rails)
58
+ puts "[SKYLIGHT] [#{Skylight::VERSION}] Running Skylight in #{Rails.env} mode. No data will be reported until you deploy your app."
59
+ else
60
+ puts "[SKYLIGHT] [#{Skylight::VERSION}] Running Skylight in development mode."
61
+ end
55
62
  end
56
63
 
57
64
  def self.daemon?
@@ -103,6 +110,12 @@ module Skylight
103
110
  DEFAULT_CATEGORY = "app.block".freeze
104
111
  DEFAULT_OPTIONS = { category: DEFAULT_CATEGORY }
105
112
 
113
+ #
114
+ #
115
+ # ===== Public API =====
116
+ #
117
+ #
118
+
106
119
  def self.start!(*args)
107
120
  Instrumenter.start!(*args)
108
121
  end
@@ -136,7 +149,7 @@ module Skylight
136
149
  end
137
150
 
138
151
  if Hash === opts
139
- category = opts.delete(:category)
152
+ category = opts.delete(:category) || DEFAULT_CATEGORY
140
153
  title = opts.delete(:title)
141
154
  desc = opts.delete(:description)
142
155
  else
@@ -170,34 +183,3 @@ module Skylight
170
183
 
171
184
  require 'skylight/probes'
172
185
  end
173
-
174
- else
175
-
176
- module Skylight
177
- def self.native?
178
- false
179
- end
180
-
181
- def self.start!(*)
182
- end
183
-
184
- def self.stop!(*)
185
- end
186
-
187
- def self.trace(*)
188
- yield if block_given?
189
- end
190
-
191
- def self.done(*)
192
- end
193
-
194
- def self.instrument(*)
195
- yield if block_given?
196
- end
197
-
198
- def self.disable(*)
199
- yield if block_given?
200
- end
201
- end
202
-
203
- end
@@ -1,6 +1,7 @@
1
1
  require 'thread'
2
2
  require 'set'
3
3
  require 'base64'
4
+ require 'strscan'
4
5
 
5
6
  module Skylight
6
7
  class Instrumenter
@@ -70,6 +71,11 @@ module Skylight
70
71
  def start!
71
72
  return unless config
72
73
 
74
+ unless Skylight.native?
75
+ Skylight.warn_skylight_native_missing
76
+ return
77
+ end
78
+
73
79
  t { "starting instrumenter" }
74
80
  @config.validate!
75
81
 
@@ -153,6 +159,8 @@ module Skylight
153
159
  end
154
160
 
155
161
  def instrument(cat, title=nil, desc=nil, annot=nil)
162
+ raise ArgumentError, 'cat is required' unless cat
163
+
156
164
  unless trace = @trace_info.current
157
165
  return yield if block_given?
158
166
  return
@@ -1,80 +1,83 @@
1
1
  module Skylight
2
- class Hello
3
- DIGITS = /^\s*\d+\s*$/
4
2
 
5
- alias serialize native_serialize
6
- alias version native_get_version
3
+ if native?
4
+ class Hello
5
+ DIGITS = /^\s*\d+\s*$/
7
6
 
8
- class << self
9
- alias deserialize native_load
10
- end
7
+ alias serialize native_serialize
8
+ alias version native_get_version
11
9
 
12
- def cmd
13
- native_cmd_length.times.map do |offset|
14
- native_cmd_get(offset)
10
+ class << self
11
+ alias deserialize native_load
15
12
  end
16
- end
17
13
 
18
- def newer?(other = VERSION)
19
- other = split(other)
20
- curr = split(version)
14
+ def cmd
15
+ native_cmd_length.times.map do |offset|
16
+ native_cmd_get(offset)
17
+ end
18
+ end
21
19
 
22
- [other.length, curr.length].max.times do |i|
23
- next if other[i] == curr[i]
24
- return true unless other[i]
20
+ def newer?(other = VERSION)
21
+ other = split(other)
22
+ curr = split(version)
25
23
 
26
- if other[i] =~ DIGITS
27
- if curr[i] =~ DIGITS
28
- other_i = other[i].to_i
29
- curr_i = curr[i].to_i
24
+ [other.length, curr.length].max.times do |i|
25
+ next if other[i] == curr[i]
26
+ return true unless other[i]
30
27
 
31
- next if other_i == curr_i
28
+ if other[i] =~ DIGITS
29
+ if curr[i] =~ DIGITS
30
+ other_i = other[i].to_i
31
+ curr_i = curr[i].to_i
32
32
 
33
- return curr_i > other_i
34
- else
35
- return false
36
- end
37
- else
38
- if curr[i] =~ DIGITS
39
- return true
33
+ next if other_i == curr_i
34
+
35
+ return curr_i > other_i
36
+ else
37
+ return false
38
+ end
40
39
  else
41
- next if curr[i] == other[i]
42
- return curr[i] > other[i]
40
+ if curr[i] =~ DIGITS
41
+ return true
42
+ else
43
+ next if curr[i] == other[i]
44
+ return curr[i] > other[i]
45
+ end
43
46
  end
44
47
  end
45
- end
46
48
 
47
- false
48
- end
49
+ false
50
+ end
49
51
 
50
- private
52
+ private
51
53
 
52
- def split(v)
53
- v.split('.')
54
- end
54
+ def split(v)
55
+ v.split('.')
56
+ end
55
57
 
56
- end
58
+ end
57
59
 
58
- class Error
59
- alias serialize native_serialize
60
- alias type native_get_group
61
- alias description native_get_description
62
- alias details native_get_details
60
+ class Error
61
+ alias serialize native_serialize
62
+ alias type native_get_group
63
+ alias description native_get_description
64
+ alias details native_get_details
63
65
 
64
- class << self
65
- alias deserialize native_load
66
+ class << self
67
+ alias deserialize native_load
68
+ end
66
69
  end
67
- end
68
70
 
69
- class Trace
70
- alias serialize native_serialize
71
+ class Trace
72
+ alias serialize native_serialize
71
73
 
72
- class << self
73
- alias deserialize native_load
74
+ class << self
75
+ alias deserialize native_load
76
+ end
74
77
  end
75
- end
76
78
 
77
- class Batch
78
- alias serialize native_serialize
79
+ class Batch
80
+ alias serialize native_serialize
81
+ end
79
82
  end
80
83
  end
@@ -39,6 +39,8 @@ module Skylight
39
39
  end
40
40
 
41
41
  def self.require_hook(require_path)
42
+ return unless Skylight.native?
43
+
42
44
  registration = lookup_by_require_path(require_path)
43
45
  return unless registration
44
46
 
@@ -6,8 +6,16 @@ module Skylight
6
6
  Time.now.to_i
7
7
  end
8
8
 
9
- def nanos
10
- native_hrtime
9
+ if Skylight.native?
10
+ def nanos
11
+ native_hrtime
12
+ end
13
+ else
14
+ # Implement nanos to work when native extension is not present
15
+ def nanos
16
+ now = Time.now
17
+ now.to_i * 1_000_000_000 + now.usec * 1_000
18
+ end
11
19
  end
12
20
 
13
21
  def secs
@@ -0,0 +1,195 @@
1
+ require 'uri'
2
+ require 'logger'
3
+ require 'zlib'
4
+ require 'net/http'
5
+ require 'digest/sha2'
6
+
7
+ # Must require 'rubygems/platform' vs. just requiring 'rubygems' to avoid a
8
+ # stack overflow bug on ruby 1.9.2.
9
+ require 'rubygems/platform'
10
+
11
+ module Skylight
12
+ module Util
13
+ class NativeExtFetcher
14
+ BASE_URL = "https://github.com/skylightio/skylight-rust/releases/download"
15
+ MAX_REDIRECTS = 5
16
+ MAX_RETRIES = 3
17
+
18
+ class FetchError < StandardError; end
19
+
20
+ def self.fetch(opts = {})
21
+ platform = Gem::Platform.local
22
+
23
+ fetcher = new(
24
+ BASE_URL,
25
+ opts[:target],
26
+ opts[:version],
27
+ opts[:checksums],
28
+ opts[:cpu] || platform.cpu,
29
+ opts[:os] || platform.os,
30
+ opts[:required],
31
+ opts[:logger] || Logger.new(STDOUT))
32
+
33
+ fetcher.fetch
34
+ end
35
+
36
+ def initialize(source, target, version, checksums, cpu, os, required, log)
37
+ raise "source required" unless source
38
+ raise "checksums required" unless checksums
39
+ raise "cpu required" unless cpu
40
+ raise "os required" unless os
41
+
42
+ @source = source
43
+ @target = target
44
+ @version = version
45
+ @checksums = checksums
46
+ @required = required
47
+ @arch = "#{os}-#{cpu}"
48
+ @log = log
49
+ end
50
+
51
+ 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
+ log "fetching native ext; curr-platform=#{Gem::Platform.local.to_s}; " \
61
+ "requested-arch=#{@arch}; version=#{@version}"
62
+
63
+ unless gziped = fetch_native_ext(source_uri, MAX_RETRIES, MAX_REDIRECTS)
64
+ maybe_raise "could not fetch native extension"
65
+ return
66
+ end
67
+
68
+ unless verify_checksum(gziped)
69
+ maybe_raise "could not verify checksum"
70
+ return
71
+ end
72
+
73
+ archive = inflate(gziped)
74
+
75
+ if @target
76
+ File.open @target, 'w' do |f|
77
+ f.write(archive)
78
+ end
79
+ end
80
+
81
+ archive
82
+ end
83
+
84
+ def self.http_get(host, port, use_ssl, path)
85
+ Net::HTTP.start(host, port, use_ssl: use_ssl) do |http|
86
+ case response = http.get(path)
87
+ when Net::HTTPSuccess
88
+ return [ :success, response.body ]
89
+ when Net::HTTPRedirection
90
+ unless location = response['location']
91
+ raise "received redirect but no location"
92
+ end
93
+
94
+ return [ :redirect, location ]
95
+ else
96
+ raise "received HTTP status code #{response.code}"
97
+ end
98
+ end
99
+ end
100
+
101
+ def fetch_native_ext(uri, attempts, redirects)
102
+ redirects.times do |i|
103
+ remaining_attempts = attempts
104
+
105
+ log "attempting to fetch from remote; uri=#{uri}"
106
+
107
+ begin
108
+ host, port, use_ssl, path = deconstruct_uri(uri)
109
+
110
+ status, body = NativeExtFetcher.http_get(host, port, use_ssl, path)
111
+
112
+ case status
113
+ when :success
114
+ if body
115
+ log "successfully downloaded native ext; body=#{body.bytesize}bytes"
116
+ else
117
+ log "response did not contain a body"
118
+ end
119
+
120
+ return body
121
+ when :redirect
122
+ log "fetching native ext; uri=#{uri}; redirected=#{body}"
123
+ uri = body
124
+
125
+ next
126
+ else
127
+ raise "received unknown return; status=#{status}; body=#{body}"
128
+ end
129
+
130
+ rescue => e
131
+ remaining_attempts -= 1
132
+
133
+ log "failed to fetch native extension; uri=#{uri}; msg=#{e.message}; remaining-attempts=#{remaining_attempts}", e
134
+
135
+ if remaining_attempts > 0
136
+ sleep 2
137
+ retry
138
+ end
139
+
140
+ return
141
+ end
142
+ end
143
+
144
+ log "exceeded max redirects"
145
+ return
146
+ end
147
+
148
+ def verify_checksum(archive)
149
+ unless expected = @checksums[@arch]
150
+ log "no checksum provided; arch=#{@arch}"
151
+ return false
152
+ end
153
+
154
+ actual = Digest::SHA2.hexdigest(archive)
155
+
156
+ unless expected == actual
157
+ log "checksum mismatch; expected=#{expected}; actual=#{actual}"
158
+ return false
159
+ end
160
+
161
+ true
162
+ end
163
+
164
+ def inflate(archive)
165
+ inflater = Zlib::Inflate.new(32 + Zlib::MAX_WBITS)
166
+ inflated = inflater.inflate(archive)
167
+ inflater.close
168
+ inflated
169
+ end
170
+
171
+ def source_uri
172
+ "#{@source}/#{@version}/libskylight.#{@arch}.a.gz"
173
+ end
174
+
175
+ def deconstruct_uri(uri)
176
+ uri = URI(uri)
177
+ [ uri.host, uri.port, uri.scheme == 'https', uri.request_uri ]
178
+ end
179
+
180
+ def maybe_raise(err)
181
+ log err
182
+
183
+ if @required
184
+ raise err
185
+ end
186
+ end
187
+
188
+ def log(msg, e = nil)
189
+ msg = "[SKYLIGHT] #{msg}"
190
+ msg << "\n#{e.backtrace.join("\n")}" if e
191
+ @log.info msg
192
+ end
193
+ end
194
+ end
195
+ end
@@ -1,4 +1,4 @@
1
1
  module Skylight
2
- VERSION = '0.3.6'
2
+ VERSION = '0.3.7'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
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-03-27 00:00:00.000000000 Z
11
+ date: 2014-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.0.0
27
27
  description:
@@ -33,13 +33,6 @@ extensions:
33
33
  - ext/extconf.rb
34
34
  extra_rdoc_files: []
35
35
  files:
36
- - CHANGELOG.md
37
- - README.md
38
- - bin/skylight
39
- - ext/checksums.yml
40
- - ext/extconf.rb
41
- - ext/skylight.map
42
- - ext/skylight_native.c
43
36
  - lib/skylight.rb
44
37
  - lib/skylight/api.rb
45
38
  - lib/skylight/cli.rb
@@ -78,6 +71,7 @@ files:
78
71
  - lib/skylight/util/http.rb
79
72
  - lib/skylight/util/inflector.rb
80
73
  - lib/skylight/util/logging.rb
74
+ - lib/skylight/util/native_ext_fetcher.rb
81
75
  - lib/skylight/util/queue.rb
82
76
  - lib/skylight/util/task.rb
83
77
  - lib/skylight/util/uniform_sample.rb
@@ -139,6 +133,14 @@ files:
139
133
  - lib/sql_lexer.rb
140
134
  - lib/sql_lexer/lexer.rb
141
135
  - lib/sql_lexer/version.rb
136
+ - ext/skylight.h
137
+ - ext/skylight_native.c
138
+ - ext/skylight.map
139
+ - ext/extconf.rb
140
+ - ext/libskylight.yml
141
+ - CHANGELOG.md
142
+ - README.md
143
+ - bin/skylight
142
144
  homepage: http://www.skylight.io
143
145
  licenses: []
144
146
  metadata: {}
@@ -148,17 +150,17 @@ require_paths:
148
150
  - lib
149
151
  required_ruby_version: !ruby/object:Gem::Requirement
150
152
  requirements:
151
- - - ">="
153
+ - - '>='
152
154
  - !ruby/object:Gem::Version
153
155
  version: 1.9.2
154
156
  required_rubygems_version: !ruby/object:Gem::Requirement
155
157
  requirements:
156
- - - ">="
158
+ - - '>='
157
159
  - !ruby/object:Gem::Version
158
160
  version: '0'
159
161
  requirements: []
160
162
  rubyforge_project:
161
- rubygems_version: 2.2.1
163
+ rubygems_version: 2.0.3
162
164
  signing_key:
163
165
  specification_version: 4
164
166
  summary: Skylight is a ruby application monitoring tool. Currently in closed beta.
@@ -1,3 +0,0 @@
1
- ---
2
- x86_64-linux: "98b04f7d73c1894cc79621a135b4598a679c421f5ff3eecc652f84ba07258d9c"
3
- i686-linux : "1d4bbd58e319237b18752607d087ce0c895fe99c58482e994abe62a9f07d41dd"