Skip to content

Commit 3aef371

Browse files
authored
Merge pull request #40 from homiedopie/feature/LNX-330-rum-v2
LNX-330 - Initial commit for RUMv2 support
2 parents eaf92da + 8f1b00a commit 3aef371

File tree

9 files changed

+501
-6
lines changed

9 files changed

+501
-6
lines changed

Gemfile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
source 'https://rubygems.org'
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
28

9+
source 'https://rubygems.org'
310
# Specify your gem's dependencies in stackify.gemspec
411
gemspec

Gemfile.lock

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,62 @@
11
PATH
22
remote: .
33
specs:
4-
stackify-api-ruby (1.1.0)
4+
stackify-api-ruby (1.2.10)
55
faraday (~> 0.8)
6+
net_http_unix (~> 0.2)
67

78
GEM
89
remote: https://rubygems.org/
910
specs:
10-
faraday (0.15.4)
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)
1116
multipart-post (>= 1.2, < 3)
12-
multipart-post (2.0.0)
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)
1323
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)
1448

1549
PLATFORMS
1650
ruby
51+
x86-mingw32
1752

1853
DEPENDENCIES
1954
bundler (~> 1.6)
2055
rake (~> 0)
56+
rspec (~> 3.0)
2157
stackify-api-ruby!
58+
stackify-ruby-apm (~> 1.15)
59+
tzinfo-data
2260

2361
BUNDLED WITH
24-
1.17.3
62+
1.17.13

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ We can configure every metric with settings:
124124

125125
Note, "autoreport_last_value_if_nothing_reported" property has influence only on "average" metric.
126126

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+
127144
## Troubleshooting
128145

129146
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:

lib/stackify-api-ruby.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module Stackify
3737
autoload :StringException, 'stackify/error'
3838
autoload :ErrorsGovernor, 'stackify/errors_governor'
3939
autoload :Metrics, 'stackify/metrics/metrics'
40+
autoload :Rum, 'stackify/rum'
4041

4142
include Authorizable
4243

@@ -48,6 +49,10 @@ def configuration
4849
@config ||= Stackify::Configuration.new
4950
end
5051

52+
def rum
53+
@rum ||= Stackify::Rum.new(configuration)
54+
end
55+
5156
def setup
5257
@workers = []
5358
yield(configuration) if block_given?

lib/stackify/rum.rb

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

lib/stackify/utils/configuration.rb

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ class Configuration
55
attr_accessor :api_key, :app_name, :app_location, :env, :log_level, :logger,
66
:proxy, :mode, :base_api_url, :api_enabled, :transport, :errors, :http_endpoint, :stdout_output, :buffered_logger
77

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
910

1011
def initialize
1112
@base_api_url = 'https://api.stackify.com'
@@ -27,6 +28,11 @@ def initialize
2728
@http_endpoint = get_env 'STACKIFY_TRANSPORT_HTTP_ENDPOINT', 'https://localhost:10601'
2829
@stdout_output = false
2930
@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
3036
end
3137

3238
def get_env env_key, default
@@ -52,6 +58,28 @@ def validate_transport_type
5258
@errors << 'Transport should be one of these values: [agent_socket, agent_http, default]. Should be a String.'
5359
end
5460

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+
5583
private
5684

5785
def validate_config_types
@@ -110,5 +138,27 @@ def validate_mode
110138
return true if MODES.has_value? @mode
111139
@errors << 'Mode should be one of these values: [:both, :logging, :metrics]'
112140
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
113163
end
114164
end

0 commit comments

Comments
 (0)