skylight 0.3.6 → 0.3.7
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/ext/extconf.rb +65 -67
- data/ext/libskylight.yml +6 -0
- data/ext/skylight.h +93 -0
- data/ext/skylight_native.c +47 -95
- data/lib/skylight.rb +40 -58
- data/lib/skylight/instrumenter.rb +8 -0
- data/lib/skylight/native.rb +57 -54
- data/lib/skylight/probes.rb +2 -0
- data/lib/skylight/util/clock.rb +10 -2
- data/lib/skylight/util/native_ext_fetcher.rb +195 -0
- data/lib/skylight/version.rb +1 -1
- metadata +16 -14
- data/ext/checksums.yml +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 727271788a0fddacdf3b7e53451c413023d74a0d
|
4
|
+
data.tar.gz: 0b911dd320834be2608b7cd294e5aacf395188b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 425fe8a9ece2086b79e08cadcd7687c1d808ce65e2772c6b3d457c7f5b79c57fe9284d78f9964a7a161e95f67d0e87d2cf4dc89370488d6d7ad7906abec53357
|
7
|
+
data.tar.gz: bbbe029afd5bfaa9c203ad7103ac818bdebbc95a78b94435ed43344b5a00feb74e7992d75bc8fdca27e1fe63dadb784fcd64ef63abbb41130092c4511988f5ea
|
data/ext/extconf.rb
CHANGED
@@ -1,91 +1,89 @@
|
|
1
1
|
require 'mkmf'
|
2
|
-
require 'rbconfig'
|
3
|
-
require 'net/http'
|
4
|
-
require 'zlib'
|
5
2
|
require 'yaml'
|
6
|
-
require '
|
3
|
+
require 'logger'
|
7
4
|
|
8
|
-
|
5
|
+
LOG = Logger.new(STDOUT)
|
6
|
+
SKYLIGHT_REQUIRED = ENV.key?("SKYLIGHT_REQUIRED") && ENV['SKYLIGHT_REQUIRED'] !~ /^false$/i
|
9
7
|
|
10
|
-
|
8
|
+
require_relative '../lib/skylight/version'
|
9
|
+
require_relative '../lib/skylight/util/native_ext_fetcher'
|
11
10
|
|
12
|
-
|
11
|
+
include Skylight::Util
|
13
12
|
|
14
|
-
|
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
|
-
|
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
|
-
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
end
|
19
31
|
|
20
|
-
|
21
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
32
|
-
|
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
|
50
|
-
|
51
|
-
|
45
|
+
unless version = libskylight_info["version"]
|
46
|
+
fail "libskylight version missing from `#{libskylight_yml}`"
|
47
|
+
end
|
52
48
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
inflater.close
|
49
|
+
unless checksums = libskylight_info["checksums"]
|
50
|
+
fail "libskylight checksums missing from `#{libskylight_yml}`"
|
51
|
+
end
|
57
52
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
67
|
-
|
69
|
+
#
|
70
|
+
#
|
71
|
+
# ===== By this point, libskylight.a is present =====
|
72
|
+
#
|
73
|
+
#
|
68
74
|
|
69
|
-
|
75
|
+
have_header 'dlfcn.h'
|
70
76
|
|
71
|
-
|
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
|
-
|
79
|
-
|
80
|
-
$
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
87
|
+
CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
|
89
88
|
|
90
|
-
|
91
|
-
end
|
89
|
+
create_makefile 'skylight_native', '.'
|
data/ext/libskylight.yml
ADDED
data/ext/skylight.h
ADDED
@@ -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
|
data/ext/skylight_native.c
CHANGED
@@ -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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
}
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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)
|
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
|
data/lib/skylight.rb
CHANGED
@@ -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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
data/lib/skylight/native.rb
CHANGED
@@ -1,80 +1,83 @@
|
|
1
1
|
module Skylight
|
2
|
-
class Hello
|
3
|
-
DIGITS = /^\s*\d+\s*$/
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
if native?
|
4
|
+
class Hello
|
5
|
+
DIGITS = /^\s*\d+\s*$/
|
7
6
|
|
8
|
-
|
9
|
-
alias
|
10
|
-
end
|
7
|
+
alias serialize native_serialize
|
8
|
+
alias version native_get_version
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
native_cmd_get(offset)
|
10
|
+
class << self
|
11
|
+
alias deserialize native_load
|
15
12
|
end
|
16
|
-
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def cmd
|
15
|
+
native_cmd_length.times.map do |offset|
|
16
|
+
native_cmd_get(offset)
|
17
|
+
end
|
18
|
+
end
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
def newer?(other = VERSION)
|
21
|
+
other = split(other)
|
22
|
+
curr = split(version)
|
25
23
|
|
26
|
-
|
27
|
-
if
|
28
|
-
|
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
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
42
|
-
|
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
|
-
|
48
|
-
|
49
|
+
false
|
50
|
+
end
|
49
51
|
|
50
|
-
|
52
|
+
private
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
def split(v)
|
55
|
+
v.split('.')
|
56
|
+
end
|
55
57
|
|
56
|
-
|
58
|
+
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
65
|
-
|
66
|
+
class << self
|
67
|
+
alias deserialize native_load
|
68
|
+
end
|
66
69
|
end
|
67
|
-
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
+
class Trace
|
72
|
+
alias serialize native_serialize
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
+
class << self
|
75
|
+
alias deserialize native_load
|
76
|
+
end
|
74
77
|
end
|
75
|
-
end
|
76
78
|
|
77
|
-
|
78
|
-
|
79
|
+
class Batch
|
80
|
+
alias serialize native_serialize
|
81
|
+
end
|
79
82
|
end
|
80
83
|
end
|
data/lib/skylight/probes.rb
CHANGED
data/lib/skylight/util/clock.rb
CHANGED
@@ -6,8 +6,16 @@ module Skylight
|
|
6
6
|
Time.now.to_i
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
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
|
data/lib/skylight/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
data/ext/checksums.yml
DELETED