stackify-api-ruby 1.2.4 → 1.3.0.beta1
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/Gemfile +8 -1
- data/Gemfile.lock +42 -4
- data/README.md +17 -0
- data/lib/core_ext/core_ext.rb +0 -1
- data/lib/stackify-api-ruby.rb +6 -4
- data/lib/stackify/agent_base_sender.rb +18 -19
- data/lib/stackify/agent_client.rb +5 -5
- data/lib/stackify/agent_http_sender.rb +4 -6
- data/lib/stackify/authorization/authorizable.rb +5 -1
- data/lib/stackify/engine.rb +47 -0
- data/lib/stackify/error.rb +12 -3
- data/lib/stackify/logger_client.rb +27 -1
- data/lib/stackify/logger_proxy.rb +6 -4
- data/lib/stackify/metrics/metrics_client.rb +3 -3
- data/lib/stackify/rum.rb +72 -0
- data/lib/stackify/unix_socket_sender.rb +4 -6
- data/lib/stackify/utils/backtrace.rb +2 -1
- data/lib/stackify/utils/configuration.rb +54 -2
- data/lib/stackify/utils/methods.rb +26 -1
- data/lib/stackify/version.rb +1 -1
- data/lib/stackify/workers/logs_sender_worker.rb +8 -0
- data/spec/rum_spec.rb +291 -0
- data/spec/spec_helper.rb +9 -0
- data/stackify-api-ruby.gemspec +6 -1
- metadata +14 -12
- data/lib/core_ext/fixnum.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae96dffa800668cd0f8ab55fc62232c43951fbe5bf9700992698ece32bbbf006
|
4
|
+
data.tar.gz: 7e44e75717ecb342cdb632766708bb765793df1a92b534e689d59079c43d2bbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 032502e0aff449fa9ad239f282751ee0699cffcca713f14dff414eaac255cbabba348bcbabc5f5800be8aadecd787c1a7ba9d92620a86cb41ee7f579a1f6d56b
|
7
|
+
data.tar.gz: 8e93149a91583a7f9accc6d6ba1e87767ea8daa96049fc25941b89b27f4a1c459e4d6cce050126306b8097d979b993b5ddfe0c984191b7f503a6bc3af50948a3
|
data/Gemfile
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
|
1
|
+
group :test do
|
2
|
+
if ENV['STACKIFY_RUBY_TEST']
|
3
|
+
gem 'stackify-ruby-apm', '~> 1.15', source: ENV['STACKIFY_RUBY_TEST_REPO']
|
4
|
+
else
|
5
|
+
gem 'stackify-ruby-apm', '~> 1.15'
|
6
|
+
end
|
7
|
+
end
|
2
8
|
|
9
|
+
source 'https://rubygems.org'
|
3
10
|
# Specify your gem's dependencies in stackify.gemspec
|
4
11
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,24 +1,62 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
stackify-api-ruby (1.
|
4
|
+
stackify-api-ruby (1.3.0.beta1)
|
5
5
|
faraday (~> 0.8)
|
6
|
+
net_http_unix (~> 0.2)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
|
-
|
11
|
+
concurrent-ruby (1.1.9)
|
12
|
+
diff-lcs (1.4.4)
|
13
|
+
et-orbi (1.2.4)
|
14
|
+
tzinfo
|
15
|
+
faraday (0.17.4)
|
11
16
|
multipart-post (>= 1.2, < 3)
|
12
|
-
|
17
|
+
fugit (1.5.0)
|
18
|
+
et-orbi (~> 1.1, >= 1.1.8)
|
19
|
+
raabro (~> 1.4)
|
20
|
+
multipart-post (2.1.1)
|
21
|
+
net_http_unix (0.2.2)
|
22
|
+
raabro (1.4.0)
|
13
23
|
rake (0.9.6)
|
24
|
+
rspec (3.10.0)
|
25
|
+
rspec-core (~> 3.10.0)
|
26
|
+
rspec-expectations (~> 3.10.0)
|
27
|
+
rspec-mocks (~> 3.10.0)
|
28
|
+
rspec-core (3.10.1)
|
29
|
+
rspec-support (~> 3.10.0)
|
30
|
+
rspec-expectations (3.10.1)
|
31
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
+
rspec-support (~> 3.10.0)
|
33
|
+
rspec-mocks (3.10.2)
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
+
rspec-support (~> 3.10.0)
|
36
|
+
rspec-support (3.10.2)
|
37
|
+
rufus-scheduler (3.8.0)
|
38
|
+
fugit (~> 1.1, >= 1.1.6)
|
39
|
+
stackify-ruby-apm (1.15.1)
|
40
|
+
concurrent-ruby (~> 1.0)
|
41
|
+
faraday (~> 0.8)
|
42
|
+
net_http_unix (~> 0.2)
|
43
|
+
rufus-scheduler (~> 3.0)
|
44
|
+
tzinfo (2.0.4)
|
45
|
+
concurrent-ruby (~> 1.0)
|
46
|
+
tzinfo-data (1.2021.1)
|
47
|
+
tzinfo (>= 1.0.0)
|
14
48
|
|
15
49
|
PLATFORMS
|
16
50
|
ruby
|
51
|
+
x86-mingw32
|
17
52
|
|
18
53
|
DEPENDENCIES
|
19
54
|
bundler (~> 1.6)
|
20
55
|
rake (~> 0)
|
56
|
+
rspec (~> 3.0)
|
21
57
|
stackify-api-ruby!
|
58
|
+
stackify-ruby-apm (~> 1.15)
|
59
|
+
tzinfo-data
|
22
60
|
|
23
61
|
BUNDLED WITH
|
24
|
-
1.17.
|
62
|
+
1.17.13
|
data/README.md
CHANGED
@@ -124,6 +124,23 @@ We can configure every metric with settings:
|
|
124
124
|
|
125
125
|
Note, "autoreport_last_value_if_nothing_reported" property has influence only on "average" metric.
|
126
126
|
|
127
|
+
### **Real User Monitoring (RUM)**
|
128
|
+
|
129
|
+
Real user monitoring injects a script tag containing the [RUM JS](https://stackify.com/retrace-real-user-monitoring/) that is responsible for capturing information about the http requests on the browser. This approach is manual and needs to be configured.
|
130
|
+
|
131
|
+
#### RUM - Setup
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
# Configuration - Standard API
|
135
|
+
Stackify.setup do |config|
|
136
|
+
...
|
137
|
+
config.rum_key = "YourRumKey"
|
138
|
+
end
|
139
|
+
|
140
|
+
# Use this to apply on views
|
141
|
+
Stackify.rum.insert_rum_script
|
142
|
+
```
|
143
|
+
|
127
144
|
## Troubleshooting
|
128
145
|
|
129
146
|
If there are problems, you can enable internal logging of the stackify-api-ruby project. Uncomment out the config.logger and config.logger.level lines in the 'config/initializers/stackify.rb' file:
|
data/lib/core_ext/core_ext.rb
CHANGED
data/lib/stackify-api-ruby.rb
CHANGED
@@ -2,8 +2,6 @@ require 'stackify/version'
|
|
2
2
|
require 'stackify/utils/methods'
|
3
3
|
require 'core_ext/core_ext' unless defined? Rails
|
4
4
|
|
5
|
-
require 'google/protobuf'
|
6
|
-
require 'proto/stackify-agent.rb'
|
7
5
|
|
8
6
|
module Stackify
|
9
7
|
|
@@ -14,7 +12,6 @@ module Stackify
|
|
14
12
|
|
15
13
|
autoload :Backtrace, 'stackify/utils/backtrace'
|
16
14
|
autoload :MsgObject, 'stackify/utils/msg_object'
|
17
|
-
autoload :ProtobufLogObject, 'stackify/utils/protobuf_log_object'
|
18
15
|
autoload :Configuration, 'stackify/utils/configuration'
|
19
16
|
autoload :HttpClient, 'stackify/http_client'
|
20
17
|
autoload :Authorizable, 'stackify/authorization/authorizable'
|
@@ -40,6 +37,7 @@ module Stackify
|
|
40
37
|
autoload :StringException, 'stackify/error'
|
41
38
|
autoload :ErrorsGovernor, 'stackify/errors_governor'
|
42
39
|
autoload :Metrics, 'stackify/metrics/metrics'
|
40
|
+
autoload :Rum, 'stackify/rum'
|
43
41
|
|
44
42
|
include Authorizable
|
45
43
|
|
@@ -51,6 +49,10 @@ module Stackify
|
|
51
49
|
@config ||= Stackify::Configuration.new
|
52
50
|
end
|
53
51
|
|
52
|
+
def rum
|
53
|
+
@rum ||= Stackify::Rum.new(configuration)
|
54
|
+
end
|
55
|
+
|
54
56
|
def setup
|
55
57
|
@workers = []
|
56
58
|
yield(configuration) if block_given?
|
@@ -123,7 +125,7 @@ module Stackify
|
|
123
125
|
|
124
126
|
def run
|
125
127
|
Stackify::Utils.is_api_enabled
|
126
|
-
Stackify.internal_log :info, "Stackify.run() transportType
|
128
|
+
Stackify.internal_log :info, "Stackify.run() transportType: #{Stackify.configuration.transport} | API version: #{Stackify::VERSION} | Ruby version: #{RUBY_VERSION}"
|
127
129
|
if Stackify.configuration.api_enabled
|
128
130
|
if Stackify.is_valid?
|
129
131
|
# check transport types
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# This class will handle the sending of
|
2
|
+
# This class will handle the sending of log group message to agent
|
3
3
|
#
|
4
4
|
module Stackify
|
5
5
|
class AgentBaseSender < Worker
|
@@ -23,28 +23,27 @@ module Stackify
|
|
23
23
|
def send_logs_task attempts = nil, msgs
|
24
24
|
properties[:attempts] = attempts if attempts
|
25
25
|
Stackify::ScheduleTask.new properties do
|
26
|
-
data =
|
26
|
+
data = gather_and_pack_data(msgs).to_json
|
27
27
|
send_request data
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
log_group
|
31
|
+
def gather_and_pack_data msgs
|
32
|
+
details = Stackify::EnvDetails.instance.auth_info
|
33
|
+
{
|
34
|
+
'CDID' => details['DeviceID'],
|
35
|
+
'CDAppID' => details['DeviceAppID'],
|
36
|
+
'Logger' => 'Rails logger',
|
37
|
+
'AppName' => details['AppName'],
|
38
|
+
'AppNameID' => details['AppNameID'],
|
39
|
+
'Env' => details['Env'],
|
40
|
+
'EnvID' => details['EnvID'],
|
41
|
+
'AppEnvID' => details['AppEnvID'],
|
42
|
+
'ServerName' => details['DeviceName'],
|
43
|
+
'Msgs' => msgs,
|
44
|
+
'AppLoc' => details['AppLocation'],
|
45
|
+
'Platform' => 'Ruby'
|
46
|
+
}
|
48
47
|
end
|
49
48
|
|
50
49
|
def send_request log_group
|
@@ -36,11 +36,11 @@ module Stackify
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def has_error msg
|
39
|
-
!msg.
|
39
|
+
!msg['Ex'].nil?
|
40
40
|
end
|
41
41
|
|
42
42
|
def get_epoch msg
|
43
|
-
msg
|
43
|
+
msg['EpochMs']
|
44
44
|
end
|
45
45
|
|
46
46
|
def send_logs msgs, attempts = 3
|
@@ -59,16 +59,16 @@ module Stackify
|
|
59
59
|
e
|
60
60
|
end
|
61
61
|
ex = StackifiedError.new(ex, binding())
|
62
|
-
Stackify.msgs_queue << Stackify::
|
62
|
+
Stackify.msgs_queue << Stackify::MsgObject.new(level, ex.message, caller[0], trans_id, log_uuid, ex).to_h
|
63
63
|
else
|
64
|
-
Stackify.msgs_queue << Stackify::
|
64
|
+
Stackify.msgs_queue << Stackify::MsgObject.new(level, msg, caller[0], trans_id, log_uuid).to_h
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
def log_exception_task level, ex, trans_id=nil, log_uuid=nil
|
70
70
|
Stackify::ScheduleTask.new ({limit: 1}) do
|
71
|
-
Stackify.msgs_queue << Stackify::
|
71
|
+
Stackify.msgs_queue << Stackify::MsgObject.new(level, ex.message, caller[0], trans_id, log_uuid, ex).to_h
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
@@ -3,27 +3,25 @@ require 'faraday'
|
|
3
3
|
require 'ostruct'
|
4
4
|
|
5
5
|
#
|
6
|
-
# This class will handle the sending of
|
6
|
+
# This class will handle the sending of log messages to agent using http request
|
7
7
|
#
|
8
8
|
module Stackify
|
9
9
|
class AgentHTTPSender < AgentBaseSender
|
10
10
|
|
11
11
|
HEADERS = {
|
12
|
-
'Content-Type' => 'application/
|
12
|
+
'Content-Type' => 'application/json'
|
13
13
|
}
|
14
14
|
|
15
15
|
# send_request() This function will post an http request
|
16
|
-
# @msgs {Object}
|
16
|
+
# @msgs {Object} log group message
|
17
17
|
# return {Object} Return an object {status, message}
|
18
18
|
def send_request log_group
|
19
19
|
begin
|
20
|
-
# Convert data into binary and send it to agent
|
21
|
-
message = Stackify::LogGroup.encode(log_group)
|
22
20
|
conn = Faraday.new(proxy: Stackify.configuration.proxy, ssl: { verify: false })
|
23
21
|
@response = conn.post do |req|
|
24
22
|
req.url URI(Stackify.configuration.http_endpoint + Stackify.configuration.agent_log_url)
|
25
23
|
req.headers = HEADERS
|
26
|
-
req.body =
|
24
|
+
req.body = log_group
|
27
25
|
end
|
28
26
|
if @response.try(:status) == 200
|
29
27
|
Stackify.internal_log :debug, "[AgentHTTPSender]: Successfully send message via http request."
|
@@ -11,7 +11,11 @@ module Stackify::Authorizable
|
|
11
11
|
@@auth_client = nil
|
12
12
|
|
13
13
|
def authorize attempts=3
|
14
|
-
|
14
|
+
# Check if the ruby version is 2.0 we get the Rails info properties such as
|
15
|
+
# <Application root: e.g., /home/user/rails_app> which is required in authorization
|
16
|
+
if Gem::Version.new(RUBY_VERSION) <= Gem::Version.new('2.0')
|
17
|
+
Stackify::EnvDetails.instance.set_rails_info
|
18
|
+
end
|
15
19
|
@@auth_lock.synchronize do
|
16
20
|
return unless @@auth_client.nil?
|
17
21
|
@@auth_client = Stackify::Authorizable::AuthorizationClient.new
|
data/lib/stackify/engine.rb
CHANGED
@@ -4,7 +4,32 @@ module Stackify
|
|
4
4
|
|
5
5
|
if Rails.version > '3.1'
|
6
6
|
initializer 'Stackify set up of logger', group: :all do
|
7
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('4.0')
|
8
|
+
# check if the client app is using the ActiveSupport::Logger
|
9
|
+
is_activesupport_logger = ::Rails.logger.is_a?(ActiveSupport::Logger)
|
10
|
+
elsif Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('3.0')
|
11
|
+
Stackify::Utils.check_buffered_logger
|
12
|
+
end
|
13
|
+
|
14
|
+
# Check if the log output is STDOUT
|
15
|
+
Stackify::Utils.check_log_output
|
16
|
+
|
17
|
+
# Proxy the client Rails logger and write logs to its default log_path.
|
18
|
+
# At the same time, we send the log messages to the LoggerClient.
|
7
19
|
::Rails.logger = ::Stackify::LoggerProxy.new ::Rails.logger
|
20
|
+
|
21
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('6.0')
|
22
|
+
set_console_logs ::Rails.logger
|
23
|
+
elsif Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('4.0')
|
24
|
+
if is_activesupport_logger && Stackify.configuration.stdout_output
|
25
|
+
set_console_logs ::Rails.logger
|
26
|
+
end
|
27
|
+
# Another checking if the client app is using the default logger and not STDOUT
|
28
|
+
if Stackify.configuration.stdout_output == false
|
29
|
+
set_console_logs ::Rails.logger
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
8
33
|
Stackify.run
|
9
34
|
end
|
10
35
|
|
@@ -14,6 +39,28 @@ module Stackify
|
|
14
39
|
end
|
15
40
|
end
|
16
41
|
|
42
|
+
def set_console_logs new_logger
|
43
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('6.0')
|
44
|
+
ActiveSupport.on_load(:action_controller_base) do
|
45
|
+
logger = new_logger
|
46
|
+
end
|
47
|
+
ActiveSupport.on_load(:action_view) do
|
48
|
+
logger = new_logger
|
49
|
+
end
|
50
|
+
ActiveSupport.on_load(:active_record) do
|
51
|
+
logger = new_logger
|
52
|
+
end
|
53
|
+
else
|
54
|
+
# Handle the stdout logs from Action Controller
|
55
|
+
ActionController::Base.logger = new_logger
|
56
|
+
|
57
|
+
# Handle the stdout logs from Action View
|
58
|
+
ActionView::Base.logger = new_logger
|
59
|
+
|
60
|
+
# Handle the stdout logs from Active Record
|
61
|
+
ActiveRecord::Base.logger = new_logger
|
62
|
+
end
|
63
|
+
end
|
17
64
|
end
|
18
65
|
|
19
66
|
end
|
data/lib/stackify/error.rb
CHANGED
@@ -40,7 +40,7 @@ module Stackify
|
|
40
40
|
|
41
41
|
def to_h
|
42
42
|
env = Stackify::EnvDetails.instance
|
43
|
-
{
|
43
|
+
data = {
|
44
44
|
'OccurredEpochMillis' => Time.now.to_f*1000,
|
45
45
|
'Error' => {
|
46
46
|
'InnerError' => @exception.try(:cause),
|
@@ -52,11 +52,20 @@ module Stackify
|
|
52
52
|
'SourceMethod' => source_method,
|
53
53
|
},
|
54
54
|
'EnvironmentDetail' => env.auth_info,
|
55
|
-
'WebRequestDetail' => env.request_details.try{ |d| d.fetch('webrequest_details', '') },
|
56
|
-
'ServerVariables' => env.request_details.try{ |d| d.fetch('server_variables', '') },
|
57
55
|
'CustomerName' => 'Customer',
|
58
56
|
'UserName' => @context.fetch('user', '')
|
59
57
|
}
|
58
|
+
web_request_details = env.request_details.try{ |d| d.fetch('webrequest_details', '') }
|
59
|
+
if web_request_details.nil?
|
60
|
+
data['WebRequestDetail'] = web_request_details
|
61
|
+
end
|
62
|
+
|
63
|
+
server_variables = env.request_details.try{ |d| d.fetch('server_variables', '') }
|
64
|
+
if server_variables.nil?
|
65
|
+
data['ServerVariables'] = server_variables
|
66
|
+
end
|
67
|
+
|
68
|
+
data
|
60
69
|
end
|
61
70
|
|
62
71
|
end
|
@@ -12,7 +12,33 @@ module Stackify
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
# This function is responsible in displaying log messages based on the level criteria
|
16
|
+
# @param num_level [Integer] level of the clients Rails.logger
|
17
|
+
# @param level [String] level coming from array of levels(debug info warn error fatal unknown) that we are going to filter with num_level
|
18
|
+
# So we filter all logs from num_level up to this level
|
19
|
+
# @param msg [Integer] log messages
|
20
|
+
# @param call_trace [Object] return the current execution stack
|
21
|
+
def log num_level, level, msg, call_trace
|
22
|
+
display_log = true
|
23
|
+
log_appender = false
|
24
|
+
buffer_log = false
|
25
|
+
if defined? Rails
|
26
|
+
display_log = false if Stackify.configuration.stdout_output
|
27
|
+
log_appender = true if defined?(Logging)
|
28
|
+
buffer_log = true if Stackify.configuration.buffered_logger
|
29
|
+
unless buffer_log
|
30
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('4.0')
|
31
|
+
if display_log && log_appender
|
32
|
+
puts msg if num_level <= Logger.const_get(level.upcase).to_i
|
33
|
+
elsif display_log && log_appender == false
|
34
|
+
puts msg if num_level <= Logger.const_get(level.upcase).to_i
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
puts msg if num_level <= Logger.const_get(level.upcase).to_i
|
40
|
+
end
|
41
|
+
|
16
42
|
return if @@transport.nil?
|
17
43
|
task = log_message_task level, msg, call_trace
|
18
44
|
@@transport.log level, msg, call_trace, task
|
@@ -1,14 +1,16 @@
|
|
1
|
+
|
1
2
|
module Stackify
|
2
3
|
class LoggerProxy < Object
|
3
4
|
|
4
5
|
def initialize logger
|
5
|
-
|
6
|
-
|
6
|
+
rails_logger = logger
|
7
|
+
num_level = logger.level
|
8
|
+
@logger = rails_logger
|
7
9
|
%w(debug info warn error fatal unknown).each do |level|
|
8
10
|
stackify_logger = if level == 'debug'
|
9
|
-
-> (msg, caller) { Stackify.logger_client.log(level.downcase, msg, caller) unless msg.to_s.empty? }
|
11
|
+
-> (msg, caller) { Stackify.logger_client.log(num_level, level.downcase, msg, caller) unless msg.to_s.empty? }
|
10
12
|
else
|
11
|
-
-> (msg, caller) { Stackify.logger_client.log(level.downcase, msg, caller) }
|
13
|
+
-> (msg, caller) { Stackify.logger_client.log(num_level, level.downcase, msg, caller) }
|
12
14
|
end
|
13
15
|
LoggerProxy.class_eval do
|
14
16
|
define_method level.to_sym do |*args , &block|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Stackify::Metrics
|
2
2
|
class MetricsClient
|
3
|
-
|
3
|
+
TEN_MINUTES = 600
|
4
4
|
attr_reader :metrics_queue
|
5
5
|
|
6
6
|
def initialize
|
@@ -57,7 +57,7 @@ module Stackify::Metrics
|
|
57
57
|
|
58
58
|
def start_upload_metrics
|
59
59
|
current_time = Stackify::Utils.rounded_current_time
|
60
|
-
purge_older_than = current_time -
|
60
|
+
purge_older_than = current_time - TEN_MINUTES
|
61
61
|
#read everything up to the start of the current minute
|
62
62
|
read_queued_metrics_batch current_time
|
63
63
|
handle_zero_reports current_time
|
@@ -67,7 +67,7 @@ module Stackify::Metrics
|
|
67
67
|
if first_50_metrics.length > 0
|
68
68
|
#only getting metrics less than 10 minutes old to drop old data in case we get backed up
|
69
69
|
#they are removed from the @aggregated_metrics in the upload function upon success
|
70
|
-
upload_aggregates(first_50_metrics.select { |_key, aggr| aggr.occurred_utc > current_time -
|
70
|
+
upload_aggregates(first_50_metrics.select { |_key, aggr| aggr.occurred_utc > current_time - TEN_MINUTES })
|
71
71
|
end
|
72
72
|
@aggregate_metrics.delete_if { |_key, aggr| aggr.occurred_utc < purge_older_than }
|
73
73
|
end
|
data/lib/stackify/rum.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
$apmLoaded = false
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'stackify-ruby-apm'
|
5
|
+
$apmLoaded = true
|
6
|
+
rescue LoadError
|
7
|
+
end
|
8
|
+
|
9
|
+
module Stackify
|
10
|
+
class Rum
|
11
|
+
def initialize(config)
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def insert_rum_script()
|
16
|
+
return StackifyRubyAPM.inject_rum_script if Rum.apm_loaded && defined?(StackifyRubyAPM) && StackifyRubyAPM.respond_to?(:inject_rum_script)
|
17
|
+
|
18
|
+
return '' unless @config
|
19
|
+
|
20
|
+
config = @config
|
21
|
+
|
22
|
+
return '' if config.rum_script_url.to_s.empty? || config.rum_key.to_s.empty?
|
23
|
+
|
24
|
+
transaction_id = get_transaction_id().to_s
|
25
|
+
return '' if transaction_id.empty?
|
26
|
+
|
27
|
+
reporting_url = get_reporting_url().to_s
|
28
|
+
return '' if reporting_url.empty?
|
29
|
+
|
30
|
+
environment_name = defined?(config.env) ? config.env.to_s : 'Development'
|
31
|
+
return '' if environment_name.empty?
|
32
|
+
|
33
|
+
application_name = defined?(config.app_name) ? config.app_name.to_s : ''
|
34
|
+
return '' if application_name.empty?
|
35
|
+
|
36
|
+
rum_settings = {
|
37
|
+
"ID" => transaction_id
|
38
|
+
}
|
39
|
+
|
40
|
+
if !environment_name.empty?
|
41
|
+
rum_settings["Env"] = Base64.strict_encode64(environment_name.encode('utf-8'))
|
42
|
+
end
|
43
|
+
|
44
|
+
if !application_name.empty?
|
45
|
+
rum_settings["Name"] = Base64.strict_encode64(application_name.strip.encode('utf-8'))
|
46
|
+
end
|
47
|
+
|
48
|
+
if !reporting_url.empty?
|
49
|
+
rum_settings["Trans"] = Base64.strict_encode64(reporting_url.encode('utf-8'))
|
50
|
+
end
|
51
|
+
|
52
|
+
rum_content = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json}))</script><script src=\"#{config.rum_script_url}\" data-key=\"#{config.rum_key}\" async></script>"
|
53
|
+
if rum_content.respond_to?(:html_safe)
|
54
|
+
rum_content.html_safe
|
55
|
+
else
|
56
|
+
rum_content
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.apm_loaded
|
61
|
+
$apmLoaded
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_reporting_url
|
65
|
+
''
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_transaction_id
|
69
|
+
''
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -2,22 +2,20 @@ require 'net_http_unix'
|
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
4
|
#
|
5
|
-
# This class will handle the sending of
|
5
|
+
# This class will handle the sending of log messages to unix domain socket
|
6
6
|
#
|
7
7
|
module Stackify
|
8
8
|
class UnixSocketSender < AgentBaseSender
|
9
9
|
|
10
10
|
# send_request() This function will send http request via unix domain socket
|
11
|
-
# @msgs {Object}
|
11
|
+
# @msgs {Object} log group message
|
12
12
|
# return {Object} Return an object {status, message}
|
13
13
|
def send_request log_group
|
14
14
|
begin
|
15
|
-
# Convert data into binary and send it to unix domain socket
|
16
|
-
message = Stackify::LogGroup.encode(log_group)
|
17
15
|
client = NetX::HTTPUnix.new('unix://' + Stackify.configuration.unix_socket_path)
|
18
16
|
req = Net::HTTP::Post.new(Stackify.configuration.agent_log_url)
|
19
|
-
req.set_content_type('application/
|
20
|
-
req.body =
|
17
|
+
req.set_content_type('application/json')
|
18
|
+
req.body = log_group
|
21
19
|
response = client.request(req)
|
22
20
|
Stackify.internal_log :debug, "[UnixSocketSender] status_code = #{response.code}"
|
23
21
|
if response.code.to_i == 200
|
@@ -3,6 +3,7 @@ module Stackify::Backtrace
|
|
3
3
|
ALL_TEXT_FROM_START_TO_FIRST_COLON_REGEXP = /\A([^:]+)/
|
4
4
|
NUMBER_BETWEEN_TWO_COLONS_REGEXP = /:(\d+):/
|
5
5
|
TEXT_AFTER_IN_BEFORE_END_REGEXP = /in\s`(\S+)'\z/
|
6
|
+
TEXT_AFTER_IN_BEFORE_END_REGEXP_ = /in\s(\S+)'\z/
|
6
7
|
|
7
8
|
def self.line_number backtrace_str
|
8
9
|
backtrace_str[NUMBER_BETWEEN_TWO_COLONS_REGEXP, 1]
|
@@ -10,7 +11,7 @@ module Stackify::Backtrace
|
|
10
11
|
|
11
12
|
def self.method_name backtrace_str
|
12
13
|
return nil unless backtrace_str
|
13
|
-
backtrace_str[TEXT_AFTER_IN_BEFORE_END_REGEXP, 1]
|
14
|
+
backtrace_str[TEXT_AFTER_IN_BEFORE_END_REGEXP, 1] || backtrace_str[TEXT_AFTER_IN_BEFORE_END_REGEXP_, 1]
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.file_name backtrace_str
|
@@ -3,9 +3,10 @@ module Stackify
|
|
3
3
|
class Configuration
|
4
4
|
|
5
5
|
attr_accessor :api_key, :app_name, :app_location, :env, :log_level, :logger,
|
6
|
-
:proxy, :mode, :base_api_url, :api_enabled, :transport, :errors, :http_endpoint
|
6
|
+
:proxy, :mode, :base_api_url, :api_enabled, :transport, :errors, :http_endpoint, :stdout_output, :buffered_logger
|
7
7
|
|
8
|
-
attr_reader :send_interval, :flood_limit, :queue_max_size, :agent_log_url, :unix_socket_path, :http_endpoint
|
8
|
+
attr_reader :send_interval, :flood_limit, :queue_max_size, :agent_log_url, :unix_socket_path, :http_endpoint,
|
9
|
+
:rum_key, :rum_script_url
|
9
10
|
|
10
11
|
def initialize
|
11
12
|
@base_api_url = 'https://api.stackify.com'
|
@@ -25,6 +26,13 @@ module Stackify
|
|
25
26
|
@agent_log_url = '/log'
|
26
27
|
@unix_socket_path = '/usr/local/stackify/stackify.sock'
|
27
28
|
@http_endpoint = get_env 'STACKIFY_TRANSPORT_HTTP_ENDPOINT', 'https://localhost:10601'
|
29
|
+
@stdout_output = false
|
30
|
+
@buffered_logger = false
|
31
|
+
@default_rum_script_url = 'https://stckjs.stackify.com/stckjs.js'
|
32
|
+
@default_rum_key = ''
|
33
|
+
|
34
|
+
self.rum_key = get_env 'RETRACE_RUM_KEY', @default_rum_key
|
35
|
+
self.rum_script_url = get_env 'RETRACE_RUM_SCRIPT_URL', @default_rum_script_url
|
28
36
|
end
|
29
37
|
|
30
38
|
def get_env env_key, default
|
@@ -50,6 +58,28 @@ module Stackify
|
|
50
58
|
@errors << 'Transport should be one of these values: [agent_socket, agent_http, default]. Should be a String.'
|
51
59
|
end
|
52
60
|
|
61
|
+
def rum_script_url=(rum_script_url)
|
62
|
+
if rum_script_url.empty?
|
63
|
+
@rum_script_url = @default_rum_script_url
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
if validate_rum_script_url(rum_script_url)
|
68
|
+
@rum_script_url = rum_script_url
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def rum_key=(rum_key)
|
73
|
+
if rum_key.empty?
|
74
|
+
@rum_key = @default_rum_key
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
if validate_rum_key(rum_key)
|
79
|
+
@rum_key = rum_key
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
53
83
|
private
|
54
84
|
|
55
85
|
def validate_config_types
|
@@ -108,5 +138,27 @@ module Stackify
|
|
108
138
|
return true if MODES.has_value? @mode
|
109
139
|
@errors << 'Mode should be one of these values: [:both, :logging, :metrics]'
|
110
140
|
end
|
141
|
+
|
142
|
+
def validate_rum_script_url(rum_script_url)
|
143
|
+
result = false
|
144
|
+
if rum_script_url.is_a?(String) && !rum_script_url.empty?
|
145
|
+
result = rum_script_url =~ /^((((https?|ftps?|gopher|telnet|nntp):\/\/)|(mailto:|news:))(%[0-9A-Fa-f]{2}|[\-\(\)_\.!~*';\/?:@&=+$,A-Za-z0-9])+)([\)\.!';\/?:,][\[:blank:|:blank:\]])?$/
|
146
|
+
end
|
147
|
+
if !result
|
148
|
+
@errors << 'RUM Script URL is in invalid format.'
|
149
|
+
end
|
150
|
+
result
|
151
|
+
end
|
152
|
+
|
153
|
+
def validate_rum_key(rum_key)
|
154
|
+
result = false
|
155
|
+
if rum_key.is_a?(String) && !rum_key.empty?
|
156
|
+
result = rum_key =~ %r{^[A-Za-z0-9_-]+$}
|
157
|
+
end
|
158
|
+
if !result
|
159
|
+
@errors << 'RUM Key is in invalid format.'
|
160
|
+
end
|
161
|
+
result
|
162
|
+
end
|
111
163
|
end
|
112
164
|
end
|
@@ -46,4 +46,29 @@ module Stackify::Utils
|
|
46
46
|
'app_location' => Stackify.configuration.app_location || Dir.pwd
|
47
47
|
}
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
|
+
# Check if the app is running on rails and the logger output is using STDOUT
|
51
|
+
def self.check_log_output
|
52
|
+
if defined? Rails
|
53
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('5.0')
|
54
|
+
Stackify.configuration.stdout_output = ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDOUT)
|
55
|
+
else
|
56
|
+
Stackify.configuration.stdout_output = self.logger_stdout
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.logger_stdout
|
62
|
+
logdev = ::Rails.logger.instance_variable_get(:@logdev)
|
63
|
+
logger_source = logdev.dev if logdev.respond_to?(:dev)
|
64
|
+
sources = [$stdout]
|
65
|
+
found = sources.any? { |source| source == logger_source }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Check if the rails version 3 and it's using the buffered logger
|
69
|
+
def self.check_buffered_logger
|
70
|
+
is_buffered_logger = false
|
71
|
+
is_buffered_logger = true if ::Rails.logger.is_a?(ActiveSupport::BufferedLogger)
|
72
|
+
Stackify.configuration.buffered_logger = is_buffered_logger
|
73
|
+
end
|
74
|
+
end
|
data/lib/stackify/version.rb
CHANGED
@@ -3,6 +3,14 @@ module Stackify
|
|
3
3
|
|
4
4
|
def initialize name = 'LogsSender worker'
|
5
5
|
super
|
6
|
+
case Stackify.configuration.transport
|
7
|
+
when Stackify::DEFAULT
|
8
|
+
name = 'LogsSender worker'
|
9
|
+
when Stackify::UNIX_SOCKET
|
10
|
+
name = 'UnixSocketSender worker'
|
11
|
+
when Stackify::AGENT_HTTP
|
12
|
+
name = 'AgentHTTPSender worker'
|
13
|
+
end
|
6
14
|
@name = name
|
7
15
|
@name += " ##{self.id}"
|
8
16
|
@type = :logs_send
|
data/spec/rum_spec.rb
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stackify-api-ruby'
|
3
|
+
|
4
|
+
module Stackify
|
5
|
+
RSpec.describe 'Rum - APM not loaded - Normal' do
|
6
|
+
it 'returns rum script with complete information from ENV' do
|
7
|
+
ENV['RETRACE_RUM_KEY'] = 'test-key'
|
8
|
+
ENV['RETRACE_RUM_SCRIPT_URL'] = 'https://test.com/test.js'
|
9
|
+
|
10
|
+
config = Stackify::Configuration.new
|
11
|
+
config.app_name = 'test'
|
12
|
+
config.env = 'test-env'
|
13
|
+
|
14
|
+
rum = Stackify::Rum.new(config)
|
15
|
+
reporting_url = "test reporting url"
|
16
|
+
transaction_id = "123-id"
|
17
|
+
rum_script_url = 'https://test.com/test.js'
|
18
|
+
|
19
|
+
rum_settings = {
|
20
|
+
"ID" => '123-id',
|
21
|
+
"Env" => Base64.strict_encode64('test-env'.encode('utf-8')),
|
22
|
+
"Name" => Base64.strict_encode64('test'.strip.encode('utf-8')), # TODO: Add helper function
|
23
|
+
"Trans" => Base64.strict_encode64('test reporting url'.encode('utf-8'))
|
24
|
+
}
|
25
|
+
|
26
|
+
expected_rum_script = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json()}))<\/script><script src=\"#{rum_script_url}\" data-key=\"#{config.rum_key}\" async></script>"
|
27
|
+
|
28
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
29
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
30
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
31
|
+
|
32
|
+
rum_script = rum.insert_rum_script
|
33
|
+
|
34
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
35
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
36
|
+
expect(rum_script.to_s).not_to be_empty
|
37
|
+
expect(rum_script).to eq expected_rum_script
|
38
|
+
|
39
|
+
ENV.delete('RETRACE_RUM_KEY')
|
40
|
+
ENV.delete('RETRACE_RUM_SCRIPT_URL')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns rum script with complete information from Config' do
|
44
|
+
config = Stackify::Configuration.new
|
45
|
+
config.app_name = 'test'
|
46
|
+
config.env = 'test-env'
|
47
|
+
config.rum_script_url = 'https://test.com/test.js'
|
48
|
+
config.rum_key = 'asd'
|
49
|
+
|
50
|
+
rum = Stackify::Rum.new(config)
|
51
|
+
reporting_url = "test reporting url"
|
52
|
+
transaction_id = "123-id"
|
53
|
+
rum_script_url = 'https://test.com/test.js'
|
54
|
+
rum_key = 'asd'
|
55
|
+
|
56
|
+
rum_settings = {
|
57
|
+
"ID" => '123-id',
|
58
|
+
"Env" => Base64.strict_encode64('test-env'.encode('utf-8')),
|
59
|
+
"Name" => Base64.strict_encode64('test'.strip.encode('utf-8')), # TODO: Add helper function
|
60
|
+
"Trans" => Base64.strict_encode64('test reporting url'.encode('utf-8'))
|
61
|
+
}
|
62
|
+
|
63
|
+
expected_rum_script = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json()}))<\/script><script src=\"#{rum_script_url}\" data-key=\"#{rum_key}\" async></script>"
|
64
|
+
|
65
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
66
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
67
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
68
|
+
|
69
|
+
rum_script = rum.insert_rum_script
|
70
|
+
|
71
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
72
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
73
|
+
expect(rum_script.to_s).not_to be_empty
|
74
|
+
expect(rum_script).to eq expected_rum_script
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
RSpec.describe 'Rum - APM not loaded - Invalid' do
|
79
|
+
it 'returns rum script with invalid rum script url from Config' do
|
80
|
+
config = Stackify::Configuration.new
|
81
|
+
config.app_name = 'test'
|
82
|
+
config.env = 'test-env'
|
83
|
+
config.rum_script_url = 'test.js'
|
84
|
+
config.rum_key = 'asd'
|
85
|
+
|
86
|
+
rum = Stackify::Rum.new(config)
|
87
|
+
reporting_url = "test reporting url"
|
88
|
+
transaction_id = "123-id"
|
89
|
+
rum_script_url = 'https://stckjs.stackify.com/stckjs.js'
|
90
|
+
rum_key = 'asd'
|
91
|
+
|
92
|
+
rum_settings = {
|
93
|
+
"ID" => '123-id',
|
94
|
+
"Env" => Base64.strict_encode64('test-env'.encode('utf-8')),
|
95
|
+
"Name" => Base64.strict_encode64('test'.strip.encode('utf-8')), # TODO: Add helper function
|
96
|
+
"Trans" => Base64.strict_encode64('test reporting url'.encode('utf-8'))
|
97
|
+
}
|
98
|
+
|
99
|
+
expected_rum_script = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json()}))<\/script><script src=\"#{rum_script_url}\" data-key=\"#{rum_key}\" async></script>"
|
100
|
+
|
101
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
102
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
103
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
104
|
+
|
105
|
+
rum_script = rum.insert_rum_script
|
106
|
+
|
107
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
108
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
109
|
+
expect(rum_script.to_s).not_to be_empty
|
110
|
+
expect(rum_script).to eq expected_rum_script
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'returns rum script with invalid rum key from Config' do
|
114
|
+
config = Stackify::Configuration.new
|
115
|
+
config.app_name = 'test'
|
116
|
+
config.env = 'test-env'
|
117
|
+
config.rum_script_url = 'test.js'
|
118
|
+
config.rum_key = '`asd'
|
119
|
+
|
120
|
+
rum = Stackify::Rum.new(config)
|
121
|
+
reporting_url = "test reporting url"
|
122
|
+
transaction_id = "123-id"
|
123
|
+
rum_script_url = 'https://stckjs.stackify.com/stckjs.js'
|
124
|
+
rum_key = 'asd'
|
125
|
+
|
126
|
+
rum_settings = {
|
127
|
+
"ID" => '123-id',
|
128
|
+
"Env" => Base64.strict_encode64('test-env'.encode('utf-8')),
|
129
|
+
"Name" => Base64.strict_encode64('test'.strip.encode('utf-8')), # TODO: Add helper function
|
130
|
+
"Trans" => Base64.strict_encode64('test reporting url'.encode('utf-8'))
|
131
|
+
}
|
132
|
+
|
133
|
+
expected_rum_script = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json()}))<\/script><script src=\"#{rum_script_url}\" data-key=\"#{rum_key}\" async></script>"
|
134
|
+
|
135
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
136
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
137
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
138
|
+
|
139
|
+
rum_script = rum.insert_rum_script
|
140
|
+
|
141
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
142
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
143
|
+
expect(rum_script.to_s).to be_empty
|
144
|
+
expect(rum_script).not_to eq expected_rum_script
|
145
|
+
expect(config.rum_key).to be_empty
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns rum script with no app name' do
|
149
|
+
config = Stackify::Configuration.new
|
150
|
+
config.app_name = ''
|
151
|
+
config.env = 'test-env'
|
152
|
+
config.rum_script_url = 'test.js'
|
153
|
+
config.rum_key = '`asd'
|
154
|
+
|
155
|
+
rum = Stackify::Rum.new(config)
|
156
|
+
|
157
|
+
reporting_url = "test reporting url"
|
158
|
+
transaction_id = "123-id"
|
159
|
+
|
160
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
161
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
162
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
163
|
+
|
164
|
+
rum_script = rum.insert_rum_script
|
165
|
+
|
166
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
167
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
168
|
+
expect(rum_script.to_s).to be_empty
|
169
|
+
expect(config.rum_key).to be_empty
|
170
|
+
expect(config.app_name).to be_empty
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'returns rum script with no env' do
|
174
|
+
config = Stackify::Configuration.new
|
175
|
+
config.app_name = 'test'
|
176
|
+
config.rum_script_url = 'test.js'
|
177
|
+
config.rum_key = 'asd'
|
178
|
+
|
179
|
+
rum = Stackify::Rum.new(config)
|
180
|
+
reporting_url = "test reporting url"
|
181
|
+
transaction_id = "123-id"
|
182
|
+
rum_script_url = 'https://stckjs.stackify.com/stckjs.js'
|
183
|
+
rum_key = 'asd'
|
184
|
+
|
185
|
+
rum_settings = {
|
186
|
+
"ID" => '123-id',
|
187
|
+
"Env" => Base64.strict_encode64('production'.encode('utf-8')),
|
188
|
+
"Name" => Base64.strict_encode64('test'.strip.encode('utf-8')), # TODO: Add helper function
|
189
|
+
"Trans" => Base64.strict_encode64('test reporting url'.encode('utf-8'))
|
190
|
+
}
|
191
|
+
|
192
|
+
expected_rum_script = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json()}))<\/script><script src=\"#{rum_script_url}\" data-key=\"#{rum_key}\" async></script>"
|
193
|
+
|
194
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
195
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
196
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
197
|
+
|
198
|
+
rum_script = rum.insert_rum_script
|
199
|
+
|
200
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
201
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
202
|
+
expect(rum_script.to_s).not_to be_empty
|
203
|
+
expect(rum_script).to eq expected_rum_script
|
204
|
+
expect(config.env).to eq :production
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'returns rum script with no transaction id' do
|
208
|
+
config = Stackify::Configuration.new
|
209
|
+
config.app_name = 'test'
|
210
|
+
config.env = 'test-env'
|
211
|
+
config.rum_script_url = 'test.js'
|
212
|
+
config.rum_key = 'asd'
|
213
|
+
|
214
|
+
rum = Stackify::Rum.new(config)
|
215
|
+
|
216
|
+
reporting_url = "test reporting url"
|
217
|
+
transaction_id = ""
|
218
|
+
|
219
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
220
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
221
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
222
|
+
|
223
|
+
rum_script = rum.insert_rum_script
|
224
|
+
|
225
|
+
expect(rum.get_reporting_url).to eq reporting_url
|
226
|
+
expect(rum.get_transaction_id).to eq ""
|
227
|
+
expect(rum_script.to_s).to be_empty
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'returns rum script with no reporting url' do
|
231
|
+
config = Stackify::Configuration.new
|
232
|
+
config.app_name = 'test'
|
233
|
+
config.env = 'test-env'
|
234
|
+
config.rum_script_url = 'test.js'
|
235
|
+
config.rum_key = 'asd'
|
236
|
+
|
237
|
+
rum = Stackify::Rum.new(config)
|
238
|
+
|
239
|
+
reporting_url = ""
|
240
|
+
transaction_id = "test-123"
|
241
|
+
|
242
|
+
allow(rum).to receive(:get_reporting_url).and_return(reporting_url)
|
243
|
+
allow(rum).to receive(:get_transaction_id).and_return(transaction_id)
|
244
|
+
allow(Rum).to receive(:apm_loaded).and_return(false)
|
245
|
+
|
246
|
+
rum_script = rum.insert_rum_script
|
247
|
+
|
248
|
+
expect(rum.get_reporting_url).to eq ""
|
249
|
+
expect(rum.get_transaction_id).to eq transaction_id
|
250
|
+
expect(rum_script.to_s).to be_empty
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
RSpec.describe 'Rum - APM loaded - Normal' do
|
255
|
+
it 'returns rum script with complete information from ENV' do
|
256
|
+
ENV['RETRACE_RUM_KEY'] = 'test-key'
|
257
|
+
ENV['RETRACE_RUM_SCRIPT_URL'] = 'https://test.com/test.js'
|
258
|
+
ENV['TZ'] = 'Europe/Paris' # For error
|
259
|
+
|
260
|
+
config = Stackify::Configuration.new
|
261
|
+
rum = Stackify::Rum.new(config)
|
262
|
+
reporting_url = "test reporting url"
|
263
|
+
transaction_id = "123-id"
|
264
|
+
rum_script_url = 'https://test.com/test.js'
|
265
|
+
rum_script = ""
|
266
|
+
|
267
|
+
StackifyRubyAPM.start
|
268
|
+
transaction = StackifyRubyAPM.transaction 'RUM Script Injection test' do
|
269
|
+
rum_script = rum.insert_rum_script
|
270
|
+
end.submit 200
|
271
|
+
StackifyRubyAPM.stop
|
272
|
+
|
273
|
+
rum_settings = {
|
274
|
+
"ID" => transaction.id(),
|
275
|
+
"Env" => Base64.strict_encode64('test'.encode('utf-8')),
|
276
|
+
"Name" => Base64.strict_encode64('Ruby Application'.strip.encode('utf-8')), # TODO: Add helper function
|
277
|
+
"Trans" => Base64.strict_encode64('RUM Script Injection test'.encode('utf-8'))
|
278
|
+
}
|
279
|
+
|
280
|
+
expected_rum_script = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json()}))<\/script><script src=\"#{rum_script_url}\" data-key=\"#{config.rum_key}\" async></script>"
|
281
|
+
|
282
|
+
ENV.delete('TZ')
|
283
|
+
ENV.delete('RETRACE_RUM_KEY')
|
284
|
+
ENV.delete('RETRACE_RUM_SCRIPT_URL')
|
285
|
+
|
286
|
+
expect(rum_script.to_s).not_to be_empty
|
287
|
+
expect(rum_script).to eq expected_rum_script
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
ENV['RAILS_ENV'] = ENV['RACK_ENV'] = 'test'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
# auto-require default gems + gems under test
|
5
|
+
Bundler.require :default, 'test'
|
6
|
+
|
7
|
+
require 'logger'
|
8
|
+
require 'stackify_ruby_apm'
|
9
|
+
|
1
10
|
RSpec.configure do |config|
|
2
11
|
|
3
12
|
config.filter_run :focus
|
data/stackify-api-ruby.gemspec
CHANGED
@@ -21,7 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
23
23
|
spec.add_development_dependency 'rake', '~> 0'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
25
|
+
|
26
|
+
if RUBY_PLATFORM == 'i386-mingw32'
|
27
|
+
spec.add_development_dependency 'tzinfo-data'
|
28
|
+
end
|
29
|
+
|
24
30
|
spec.add_runtime_dependency 'faraday', '~> 0.8'
|
25
|
-
spec.add_runtime_dependency 'google-protobuf', '~> 3.0'
|
26
31
|
spec.add_runtime_dependency 'net_http_unix', '~> 0.2'
|
27
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stackify-api-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stackify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,33 +39,33 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0
|
48
|
-
type: :
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0
|
54
|
+
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: faraday
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0.8'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0.8'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: net_http_unix
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +95,6 @@ files:
|
|
95
95
|
- README.md
|
96
96
|
- Rakefile
|
97
97
|
- lib/core_ext/core_ext.rb
|
98
|
-
- lib/core_ext/fixnum.rb
|
99
98
|
- lib/core_ext/object.rb
|
100
99
|
- lib/generators/stackify/stackify_generator.rb
|
101
100
|
- lib/generators/stackify/templates/stackify.rb
|
@@ -123,6 +122,7 @@ files:
|
|
123
122
|
- lib/stackify/metrics/monitor.rb
|
124
123
|
- lib/stackify/msgs_queue.rb
|
125
124
|
- lib/stackify/rack/errors_catcher.rb
|
125
|
+
- lib/stackify/rum.rb
|
126
126
|
- lib/stackify/schedule_delay.rb
|
127
127
|
- lib/stackify/schedule_task.rb
|
128
128
|
- lib/stackify/scheduler.rb
|
@@ -139,6 +139,7 @@ files:
|
|
139
139
|
- lib/stackify/workers/logs_sender_worker.rb
|
140
140
|
- lib/stackify/workers/msgs_queue_worker.rb
|
141
141
|
- lib/stackify/workers/worker.rb
|
142
|
+
- spec/rum_spec.rb
|
142
143
|
- spec/spec_helper.rb
|
143
144
|
- stackify-api-ruby.gemspec
|
144
145
|
homepage: http://www.stackify.com/
|
@@ -156,13 +157,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
157
|
version: '1.9'
|
157
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
159
|
requirements:
|
159
|
-
- - "
|
160
|
+
- - ">"
|
160
161
|
- !ruby/object:Gem::Version
|
161
|
-
version:
|
162
|
+
version: 1.3.1
|
162
163
|
requirements: []
|
163
164
|
rubygems_version: 3.0.1
|
164
165
|
signing_key:
|
165
166
|
specification_version: 4
|
166
167
|
summary: Stackify API for Ruby
|
167
168
|
test_files:
|
169
|
+
- spec/rum_spec.rb
|
168
170
|
- spec/spec_helper.rb
|
data/lib/core_ext/fixnum.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
class Fixnum
|
2
|
-
SECONDS_IN_MINUTE = 60
|
3
|
-
SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE
|
4
|
-
SECONDS_IN_DAY = 24 * SECONDS_IN_HOUR
|
5
|
-
|
6
|
-
def days
|
7
|
-
self * SECONDS_IN_DAY
|
8
|
-
end
|
9
|
-
|
10
|
-
def minutes
|
11
|
-
self * SECONDS_IN_MINUTE
|
12
|
-
end
|
13
|
-
|
14
|
-
def ago
|
15
|
-
Time.now - self
|
16
|
-
end
|
17
|
-
end
|