sqreen-kit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +3 -0
- data/lib/sqreen-kit.rb +3 -0
- data/lib/sqreen.rb +1 -0
- data/lib/sqreen/kit.rb +76 -0
- data/lib/sqreen/kit/configuration.rb +67 -0
- data/lib/sqreen/kit/http_client.rb +160 -0
- data/lib/sqreen/kit/http_client/authentication_error.rb +13 -0
- data/lib/sqreen/kit/http_client/unexpected_status_error.rb +18 -0
- data/lib/sqreen/kit/loggable.rb +14 -0
- data/lib/sqreen/kit/retry_policy.rb +56 -0
- data/lib/sqreen/kit/signals/actor.rb +26 -0
- data/lib/sqreen/kit/signals/auth_signals_client.rb +45 -0
- data/lib/sqreen/kit/signals/batch_collector.rb +177 -0
- data/lib/sqreen/kit/signals/context/http_context.rb +139 -0
- data/lib/sqreen/kit/signals/dto_helper.rb +147 -0
- data/lib/sqreen/kit/signals/metric.rb +16 -0
- data/lib/sqreen/kit/signals/point.rb +16 -0
- data/lib/sqreen/kit/signals/signal.rb +28 -0
- data/lib/sqreen/kit/signals/signal_attributes.rb +104 -0
- data/lib/sqreen/kit/signals/signals_client.rb +33 -0
- data/lib/sqreen/kit/signals/stack_trace.rb +140 -0
- data/lib/sqreen/kit/signals/trace.rb +34 -0
- data/lib/sqreen/kit/string_sanitizer.rb +46 -0
- metadata +82 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'sqreen/kit/signals/dto_helper'
|
2
|
+
require 'sqreen/kit/signals/signal'
|
3
|
+
|
4
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/signals.cue
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
module Kit
|
8
|
+
module Signals
|
9
|
+
class Metric < Signal
|
10
|
+
def type
|
11
|
+
'metric'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'sqreen/kit/signals/dto_helper'
|
2
|
+
require 'sqreen/kit/signals/signal'
|
3
|
+
|
4
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/signals.cue
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
module Kit
|
8
|
+
module Signals
|
9
|
+
class Point < Signal
|
10
|
+
def type
|
11
|
+
'point'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'sqreen/kit/signals/dto_helper'
|
2
|
+
require 'sqreen/kit/signals/signal_attributes'
|
3
|
+
|
4
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/signals.cue
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
module Kit
|
8
|
+
module Signals
|
9
|
+
# Not to be used directly. See Metric and Point
|
10
|
+
class Signal
|
11
|
+
include SignalAttributes
|
12
|
+
|
13
|
+
add_mandatory_attrs :signal_name, :payload
|
14
|
+
|
15
|
+
# mandatory
|
16
|
+
# @return [String]
|
17
|
+
attr_accessor :signal_name
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
attr_accessor :payload_schema
|
21
|
+
|
22
|
+
# mandatory
|
23
|
+
# @return [Object]
|
24
|
+
attr_accessor :payload
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'sqreen/kit/signals/dto_helper'
|
2
|
+
require 'sqreen/kit/signals/stack_trace'
|
3
|
+
require 'sqreen/kit/signals/actor'
|
4
|
+
|
5
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/signals.cue
|
6
|
+
|
7
|
+
module Sqreen
|
8
|
+
module Kit
|
9
|
+
module Signals
|
10
|
+
module SignalAttributes
|
11
|
+
include DtoHelper
|
12
|
+
|
13
|
+
# @param [Time]
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor_time :time
|
16
|
+
|
17
|
+
def type
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Actor]
|
22
|
+
attr_accessor :actor
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
attr_accessor :context_schema
|
26
|
+
|
27
|
+
# @return [Object] specified by context schema
|
28
|
+
attr_accessor :context
|
29
|
+
|
30
|
+
# @return [Location]
|
31
|
+
attr_accessor :location
|
32
|
+
|
33
|
+
# @return [LocationInfra]
|
34
|
+
attr_accessor :location_infra
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
attr_accessor :source
|
38
|
+
|
39
|
+
# @return [Hash{String=>Object}]
|
40
|
+
attr_accessor :trigger
|
41
|
+
|
42
|
+
def to_h
|
43
|
+
{
|
44
|
+
type: type,
|
45
|
+
}.merge(super())
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Location
|
50
|
+
include DtoHelper
|
51
|
+
|
52
|
+
# @param [Array<String>]
|
53
|
+
attr_writer :stack_trace
|
54
|
+
|
55
|
+
# @param [Exception] e
|
56
|
+
attr_writer :exception
|
57
|
+
|
58
|
+
def stack_trace
|
59
|
+
if @exception
|
60
|
+
Sqreen::Kit::StackTrace.parse(@exception)
|
61
|
+
elsif @stack_trace
|
62
|
+
Sqreen::Kit::StackTrace.parse_backtrace(@stack_trace)
|
63
|
+
else
|
64
|
+
raise 'Neither exception not stack_trace set'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class LocationInfra
|
70
|
+
include DtoHelper
|
71
|
+
|
72
|
+
add_mandatory_attrs :agent_version, :os_type, :hostname, :runtime_version
|
73
|
+
|
74
|
+
# mandatory
|
75
|
+
# @return [String]
|
76
|
+
attr_accessor :agent_version
|
77
|
+
|
78
|
+
# mandatory
|
79
|
+
# @return [String]
|
80
|
+
attr_accessor :os_type
|
81
|
+
|
82
|
+
# mandatory
|
83
|
+
# @return [String]
|
84
|
+
attr_accessor :hostname
|
85
|
+
|
86
|
+
# @return [String]
|
87
|
+
attr_accessor :runtime_type
|
88
|
+
|
89
|
+
# mandatory
|
90
|
+
# @return [String]
|
91
|
+
attr_accessor :runtime_version
|
92
|
+
|
93
|
+
# @return [String]
|
94
|
+
attr_accessor :libsqreen_version
|
95
|
+
|
96
|
+
def to_h
|
97
|
+
{
|
98
|
+
agent_type: 'ruby',
|
99
|
+
}.merge(super())
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end # module Signals
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'sqreen/kit/http_client'
|
2
|
+
|
3
|
+
module Sqreen
|
4
|
+
module Kit
|
5
|
+
module Signals
|
6
|
+
class SignalsClient
|
7
|
+
STATIC_HEADERS = { 'Content-type' => 'application/json' }.freeze
|
8
|
+
|
9
|
+
# @param http_client [Sqreen::Kit:HttpClient]
|
10
|
+
def initialize(http_client)
|
11
|
+
@http_client = http_client
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Array] signals_and_traces
|
15
|
+
# @param headers [Hash{String=>String}]
|
16
|
+
def report_batch(signals_and_traces, headers)
|
17
|
+
data = '[' + signals_and_traces.map(&:to_json).join(',') + ']'
|
18
|
+
@http_client.post('batches', data, STATIC_HEADERS.merge(headers))
|
19
|
+
end
|
20
|
+
|
21
|
+
def report_signal(signal, headers)
|
22
|
+
data = signal.to_json
|
23
|
+
@http_client.post('signals', data, STATIC_HEADERS.merge(headers))
|
24
|
+
end
|
25
|
+
|
26
|
+
def report_trace(trace, headers)
|
27
|
+
data = trace.to_json
|
28
|
+
@http_client.post('traces', data, STATIC_HEADERS.merge(headers))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# Includes code from Airbrake Technologies, Inc., under the MIT licence
|
2
|
+
# see https://github.com/airbrake/airbrake-ruby/blob/c172657dcd4eeaf62ea23f0f7d6111be2373ea59/LICENSE.md
|
3
|
+
|
4
|
+
require 'sqreen/kit/loggable'
|
5
|
+
|
6
|
+
module Sqreen
|
7
|
+
module Kit
|
8
|
+
module StackTrace
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class << Sqreen::Kit::StackTrace
|
14
|
+
module Patterns
|
15
|
+
# @return [Regexp] the pattern that matches standard Ruby stack frames,
|
16
|
+
# such as ./spec/notice_spec.rb:43:in `block (3 levels) in <top (required)>'
|
17
|
+
RUBY = %r{\A
|
18
|
+
(?<file>.+) # Matches './spec/notice_spec.rb'
|
19
|
+
:
|
20
|
+
(?<line>\d+) # Matches '43'
|
21
|
+
:in\s
|
22
|
+
`(?<function>.*)' # Matches "`block (3 levels) in <top (required)>'"
|
23
|
+
\z}x
|
24
|
+
|
25
|
+
# @return [Regexp] the pattern that matches JRuby Java stack frames, such
|
26
|
+
# as org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
|
27
|
+
JAVA = %r{\A
|
28
|
+
(?<function>.+) # Matches 'org.jruby.ast.NewlineNode.interpret'
|
29
|
+
\(
|
30
|
+
(?<file>
|
31
|
+
(?:uri:classloader:/.+(?=:)) # Matches '/META-INF/jruby.home/protocol.rb'
|
32
|
+
|
|
33
|
+
(?:uri_3a_classloader_3a_.+(?=:)) # Matches 'uri_3a_classloader_3a_/gems/...'
|
34
|
+
|
|
35
|
+
[^:]+ # Matches 'NewlineNode.java'
|
36
|
+
)
|
37
|
+
:?
|
38
|
+
(?<line>\d+)? # Matches '105'
|
39
|
+
\)
|
40
|
+
\z}x
|
41
|
+
|
42
|
+
# @return [Regexp] the pattern that tries to assume what a generic stack
|
43
|
+
# frame might look like, when exception's backtrace is set manually.
|
44
|
+
GENERIC = %r{\A
|
45
|
+
(?:from\s)?
|
46
|
+
(?<file>.+) # Matches '/foo/bar/baz.ext'
|
47
|
+
:
|
48
|
+
(?<line>\d+)? # Matches '43' or nothing
|
49
|
+
(?:
|
50
|
+
in\s`(?<function>.+)' # Matches "in `func'"
|
51
|
+
|
|
52
|
+
:in\s(?<function>.+) # Matches ":in func"
|
53
|
+
)? # ... or nothing
|
54
|
+
\z}x
|
55
|
+
end
|
56
|
+
|
57
|
+
include Sqreen::Kit::Loggable
|
58
|
+
|
59
|
+
# Parses an exception's backtrace.
|
60
|
+
#
|
61
|
+
# @param exception [Exception] The exception, which contains a backtrace to
|
62
|
+
# parse
|
63
|
+
# @return [Array<Hash{Symbol=>String,Integer}>] the parsed backtrace
|
64
|
+
def parse(exception)
|
65
|
+
return [] if exception.backtrace.nil? || exception.backtrace.none?
|
66
|
+
do_parse(exception)
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_backtrace(backtrace)
|
70
|
+
# assume normal ruby backtrace
|
71
|
+
backtrace.map do |stackframe|
|
72
|
+
stack_frame(Patterns::RUBY, stackframe)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def do_parse(exception)
|
79
|
+
regexp = best_regexp_for(exception)
|
80
|
+
|
81
|
+
exception.backtrace.map do |stackframe|
|
82
|
+
stack_frame(regexp, stackframe)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def best_regexp_for(exception)
|
87
|
+
if java_exception?(exception)
|
88
|
+
Patterns::JAVA
|
89
|
+
else
|
90
|
+
Patterns::RUBY
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Checks whether the given exception was generated by JRuby's VM.
|
95
|
+
#
|
96
|
+
# @param [Exception] exception
|
97
|
+
# @return [Boolean]
|
98
|
+
def java_exception?(exception)
|
99
|
+
if defined?(Java::JavaLang::Throwable) &&
|
100
|
+
exception.is_a?(Java::JavaLang::Throwable)
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
|
104
|
+
return false unless exception.respond_to?(:backtrace)
|
105
|
+
|
106
|
+
(Patterns::JAVA =~ exception.backtrace.first) != nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def stack_frame(regexp, stackframe)
|
110
|
+
if (match = match_frame(regexp, stackframe))
|
111
|
+
return {
|
112
|
+
in_app: sqreen_code?(match[:file]),
|
113
|
+
abs_path: match[:file],
|
114
|
+
function: match[:function],
|
115
|
+
lineno: (Integer(match[:line]) if match[:line]),
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
logger.error(
|
120
|
+
"can't parse '#{stackframe}' (please file an issue so we can fix " \
|
121
|
+
'it: https://github.com/sqreen/ruby-sdk/issues/new)',
|
122
|
+
)
|
123
|
+
{
|
124
|
+
in_app: false,
|
125
|
+
function: stackframe,
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def sqreen_code?(abs_path)
|
130
|
+
# Ruby uses / on Windows too
|
131
|
+
abs_path.include?('/lib/sqreen/')
|
132
|
+
end
|
133
|
+
|
134
|
+
def match_frame(regexp, stackframe)
|
135
|
+
match = regexp.match(stackframe)
|
136
|
+
return match if match
|
137
|
+
|
138
|
+
Patterns::GENERIC.match(stackframe)
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'sqreen/kit/signals/dto_helper'
|
2
|
+
require 'sqreen/kit/signals/signal'
|
3
|
+
require 'sqreen/kit/signals/signal_attributes'
|
4
|
+
|
5
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/trace.cue
|
6
|
+
|
7
|
+
module Sqreen
|
8
|
+
module Kit
|
9
|
+
module Signals
|
10
|
+
class Trace
|
11
|
+
include SignalAttributes
|
12
|
+
|
13
|
+
def self.attributes_for_to_h_self
|
14
|
+
[] # we handle data ourselves
|
15
|
+
end
|
16
|
+
|
17
|
+
add_mandatory_attrs :data
|
18
|
+
|
19
|
+
# @return [Array<Signal>]
|
20
|
+
attr_accessor :data
|
21
|
+
|
22
|
+
def type
|
23
|
+
'trace'
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
super.merge({
|
28
|
+
data: data.map(&:to_h),
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Sqreen
|
2
|
+
module Kit
|
3
|
+
module StringSanitizer
|
4
|
+
class << self
|
5
|
+
def sanitize(obj)
|
6
|
+
case obj
|
7
|
+
when String
|
8
|
+
sanitize_string(obj)
|
9
|
+
when Array
|
10
|
+
obj.map { |e| sanitize(e) }
|
11
|
+
when Hash
|
12
|
+
obj.each_with_object({}) { |(k, v), h| h[sanitize(k)] = sanitize(v) }
|
13
|
+
else
|
14
|
+
obj
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def sanitize_string_new(s)
|
21
|
+
return s if s.encoding == Encoding::UTF_8 && s.valid_encoding?
|
22
|
+
|
23
|
+
s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
|
24
|
+
end
|
25
|
+
|
26
|
+
def sanitize_string_old(s)
|
27
|
+
return s if s.encoding == Encoding::UTF_8 && s.valid_encoding?
|
28
|
+
|
29
|
+
s.encode('utf-16be', invalid: :replace, undef: :replace)
|
30
|
+
.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
|
31
|
+
end
|
32
|
+
|
33
|
+
repl_ok = "\x80".dup.force_encoding(Encoding::UTF_8)
|
34
|
+
.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
|
35
|
+
.valid_encoding?
|
36
|
+
if repl_ok
|
37
|
+
alias_method :sanitize_string, :sanitize_string_new
|
38
|
+
else
|
39
|
+
# for Ruby < 2
|
40
|
+
alias_method :sanitize_string, :sanitize_string_old
|
41
|
+
end
|
42
|
+
public :sanitize_string
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqreen-kit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Loic Nageleisen
|
8
|
+
- Gustavo Lopes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2020-06-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sqreen-backport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.1.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.1.0
|
28
|
+
description:
|
29
|
+
email:
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- CHANGELOG.md
|
35
|
+
- LICENSE
|
36
|
+
- lib/sqreen-kit.rb
|
37
|
+
- lib/sqreen.rb
|
38
|
+
- lib/sqreen/kit.rb
|
39
|
+
- lib/sqreen/kit/configuration.rb
|
40
|
+
- lib/sqreen/kit/http_client.rb
|
41
|
+
- lib/sqreen/kit/http_client/authentication_error.rb
|
42
|
+
- lib/sqreen/kit/http_client/unexpected_status_error.rb
|
43
|
+
- lib/sqreen/kit/loggable.rb
|
44
|
+
- lib/sqreen/kit/retry_policy.rb
|
45
|
+
- lib/sqreen/kit/signals/actor.rb
|
46
|
+
- lib/sqreen/kit/signals/auth_signals_client.rb
|
47
|
+
- lib/sqreen/kit/signals/batch_collector.rb
|
48
|
+
- lib/sqreen/kit/signals/context/http_context.rb
|
49
|
+
- lib/sqreen/kit/signals/dto_helper.rb
|
50
|
+
- lib/sqreen/kit/signals/metric.rb
|
51
|
+
- lib/sqreen/kit/signals/point.rb
|
52
|
+
- lib/sqreen/kit/signals/signal.rb
|
53
|
+
- lib/sqreen/kit/signals/signal_attributes.rb
|
54
|
+
- lib/sqreen/kit/signals/signals_client.rb
|
55
|
+
- lib/sqreen/kit/signals/stack_trace.rb
|
56
|
+
- lib/sqreen/kit/signals/trace.rb
|
57
|
+
- lib/sqreen/kit/string_sanitizer.rb
|
58
|
+
homepage: https://sqreen.com
|
59
|
+
licenses:
|
60
|
+
- Sqreen
|
61
|
+
metadata:
|
62
|
+
source_code_uri: https://github.com/sqreen/ruby-sdk
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.9.3
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubygems_version: 3.0.3
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Sqreen development kit for Ruby
|
82
|
+
test_files: []
|