r7insight 2.7.6 → 3.0.0
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/.gitignore +7 -0
- data/.travis.yml +13 -0
- data/CONTRIBUTING.md +31 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +2 -2
- data/Makefile +34 -0
- data/README.md +25 -18
- data/Rakefile +9 -7
- data/lib/{le.rb → r7_insight.rb} +19 -28
- data/lib/{le → r7_insight}/host.rb +11 -7
- data/lib/r7_insight/host/connection.rb +300 -0
- data/r7insight.gemspec +31 -0
- data/test/host_spec.rb +18 -14
- data/test/http_spec.rb +42 -23
- data/test/r7insight_spec.rb +312 -0
- data/test/region.rb +47 -26
- data/test/spec_helper.rb +3 -1
- metadata +45 -27
- data/LE.gemspec +0 -29
- data/lib/le/host/connection.rb +0 -315
- data/test/le_spec.rb +0 -142
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a2c177685e8729322134332c2600df2f39128bc
|
4
|
+
data.tar.gz: 60f673c54746ce17be74ed6519b60940646d11d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc374752238269cf845c8d624389c9e37b37323bb6ceab803afe3ade0246c5194333aeec9b68da18e5d57b3c25dc0a93db7714c438a0579aed00fe8581c78838
|
7
|
+
data.tar.gz: 13b808f2ada9e6e8385cb9331febba3aa496956261a9854833c7d4dbbf2ad16a890fab590ff2e225feef23d692bb1b60ed70b0a261578f4d38cd96c5e70444b3
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Contributing to r7insight_ruby
|
2
|
+
|
3
|
+
:+1::tada: Thanks for taking the time to contribute! :tada::+1:
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
In order to work on this repository you will require:
|
8
|
+
- ruby version `2.6.5`
|
9
|
+
- bundle version `2.0.2`
|
10
|
+
- gem version `3.0.6`
|
11
|
+
- rvm version `1.29.9`
|
12
|
+
|
13
|
+
## Workflow
|
14
|
+
|
15
|
+
- Fork repository in GitHub
|
16
|
+
- Clone your repository fork
|
17
|
+
- Implement functionality
|
18
|
+
- `make test` for testing
|
19
|
+
- Add extra tests and documentation if required
|
20
|
+
- Push into your fork and create a pull request into the main Rapid7 repository
|
21
|
+
- Once pull request is approved `make bump-(major|minor|patch)` for bumping versions (use [SemVer](https://semver.org/))
|
22
|
+
- Push again into the branch
|
23
|
+
- Pull request should get approved and merged
|
24
|
+
|
25
|
+
### Deployment information for Rapid7 developers
|
26
|
+
- Pull down the merged master which includes the Pull request changes
|
27
|
+
- `make build`
|
28
|
+
- `gem push r7insight<VERSION>.gem`
|
29
|
+
- Create a new release in GitHub with the correct version tag
|
30
|
+
|
31
|
+
JetBrains RubyMine was used to develop this gem.
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
r7insight (3.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (6.0.0)
|
10
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
|
+
i18n (>= 0.7, < 2)
|
12
|
+
minitest (~> 5.1)
|
13
|
+
tzinfo (~> 1.1)
|
14
|
+
zeitwerk (~> 2.1, >= 2.1.8)
|
15
|
+
concurrent-ruby (1.1.5)
|
16
|
+
i18n (1.7.0)
|
17
|
+
concurrent-ruby (~> 1.0)
|
18
|
+
minitest (5.12.2)
|
19
|
+
rake (13.0.0)
|
20
|
+
thread_safe (0.3.6)
|
21
|
+
tzinfo (1.2.5)
|
22
|
+
thread_safe (~> 0.1)
|
23
|
+
zeitwerk (2.2.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
activesupport (~> 6.0.0)
|
30
|
+
bundler (~> 2.0.0)
|
31
|
+
minitest (~> 5.12.2)
|
32
|
+
r7insight!
|
33
|
+
rake (~> 13.0.0)
|
34
|
+
|
35
|
+
BUNDLED WITH
|
36
|
+
2.0.2
|
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License
|
2
2
|
|
3
|
-
Copyright (c)
|
3
|
+
Copyright (c) 2019 Rapid7
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
21
|
+
THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
.PHONY: test build bump-major bump-minor bump-patch help
|
2
|
+
.DEFAULT_GOAL := help
|
3
|
+
|
4
|
+
test: ## Run the unit tests
|
5
|
+
bundle exec rake --trace
|
6
|
+
|
7
|
+
build: ## Build the ruby gem
|
8
|
+
gem build r7insight.gemspec
|
9
|
+
|
10
|
+
bump-major: ## Bump the major version (1.0.0 -> 2.0.0)
|
11
|
+
@which bump || (echo "You do not have 'bump' installed or in your PATH.\n" \
|
12
|
+
"Please run 'gem install bump'\n" "GitHub: https://github.com/gregorym/bump" && false)
|
13
|
+
@bump major
|
14
|
+
|
15
|
+
bump-minor: ## Bump the minor version (0.1.0 -> 0.2.0)
|
16
|
+
@which bump || (echo "You do not have 'bump' installed or in your PATH.\n" \
|
17
|
+
"Please run 'gem install bump'\n" "GitHub: https://github.com/gregorym/bump" && false)
|
18
|
+
@bump minor
|
19
|
+
|
20
|
+
bump-patch: ## Bump the patch version (0.0.1 -> 0.0.2)
|
21
|
+
@which bump || (echo "You do not have 'bump' installed or in your PATH.\n" \
|
22
|
+
"Please run 'gem install bump'\n" "GitHub: https://github.com/gregorym/bump" && false)
|
23
|
+
@bump patch
|
24
|
+
|
25
|
+
help: ## Shows help
|
26
|
+
@IFS=$$'\n' ; \
|
27
|
+
help_lines=(`fgrep -h "##" ${MAKEFILE_LIST} | fgrep -v fgrep | sed -e 's/\\$$//'`); \
|
28
|
+
for help_line in $${help_lines[@]}; do \
|
29
|
+
IFS=$$'#' ; \
|
30
|
+
help_split=($$help_line) ; \
|
31
|
+
help_command=`echo $${help_split[0]} | sed -e 's/^ *//' -e 's/ *$$//'` ; \
|
32
|
+
help_info=`echo $${help_split[2]} | sed -e 's/^ *//' -e 's/ *$$//'` ; \
|
33
|
+
printf "%-30s %s\n" $$help_command $$help_info ; \
|
34
|
+
done
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
Logging to
|
2
|
-
|
1
|
+
Logging to Rapid7 Insight Platform in Ruby
|
2
|
+
==========================================
|
3
3
|
|
4
4
|
[](https://travis-ci.org/rapid7/r7insight_ruby)
|
5
|
-
This is a
|
5
|
+
This is a library for logging from Ruby platforms to the Rapid7 Insight Platform, including Heroku.
|
6
6
|
|
7
7
|
It is available on github <https://github.com/rapid7/r7insight_ruby/> and rubygems
|
8
8
|
<http://rubygems.org/>.
|
@@ -15,13 +15,12 @@ Example
|
|
15
15
|
Rails.logger.warn("warning message")
|
16
16
|
Rails.logger.debug("debug message")
|
17
17
|
|
18
|
-
|
19
18
|
Howto
|
20
19
|
-----
|
21
20
|
|
22
|
-
You must first register your account
|
21
|
+
You must first register your account on the Rapid7 Insight Platform.
|
23
22
|
|
24
|
-
Once you have logged
|
23
|
+
Once you have logged into the platform, create a new host with a name of your choice.
|
25
24
|
Inside this host, create a new logfile, selecting `Token TCP` (or `Plain TCP/UDP` if using UDP)
|
26
25
|
as the source type.
|
27
26
|
|
@@ -40,43 +39,51 @@ Then from the cmd line run the following command:
|
|
40
39
|
|
41
40
|
This will install the gem on your local environment.
|
42
41
|
|
43
|
-
The next step is to configure the default rails logger to use the
|
42
|
+
The next step is to configure the default rails logger to use the Rapid7 Insight Platform logger.
|
43
|
+
Ensure you add a `require` to load in the package:
|
44
44
|
|
45
|
+
require 'r7_insight.rb'
|
45
46
|
|
46
47
|
In your environment configuration file ( for production : `config/environments/production.rb`), add the following:
|
47
48
|
|
48
|
-
Rails.logger =
|
49
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION')
|
49
50
|
|
50
51
|
If you want to keep logging locally in addition to sending logs to in, just add local parameter after the key.
|
51
52
|
By default, this will write to the standard Rails log or to STDOUT if not using Rails:
|
52
53
|
|
53
|
-
Rails.logger =
|
54
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION', :local => true)
|
54
55
|
|
55
56
|
You may specify the local log device by providing a filename (String) or IO object (typically STDOUT, STDERR, or an open file):
|
56
57
|
|
57
|
-
Rails.logger =
|
58
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION', :local => 'log/my_custom_log.log')
|
58
59
|
|
59
|
-
If you want the gem to use SSL when streaming logs to
|
60
|
+
If you want the gem to use SSL when streaming logs to the Rapid7 Insight Platform, add the ssl parameter and set it to true:
|
60
61
|
|
61
|
-
Rails.logger =
|
62
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION', :ssl => true)
|
62
63
|
|
63
64
|
If you want to print debug messages for the gem to a file called r7insightGem.log, add this:
|
64
65
|
|
65
|
-
Rails.logger =
|
66
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION', :debug => true)
|
66
67
|
|
67
68
|
If you want to use ActiveSupport::TaggedLogging logging, add this:
|
68
69
|
|
69
|
-
Rails.logger =
|
70
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION', :tag => true)
|
70
71
|
|
71
72
|
You can also specify the default level of the logger by adding a :
|
72
73
|
|
73
|
-
Rails.logger =
|
74
|
+
Rails.logger = R7Insight.new('LOG_TOKEN', 'REGION', :log_level => Logger::<level>)
|
74
75
|
|
75
|
-
For the `LOG_TOKEN` argument, paste the token for the logfile you created earlier in the
|
76
|
+
For the `LOG_TOKEN` argument, paste the token for the logfile you created earlier in the Rapid7 Insight UI or empty string for
|
76
77
|
a UDP connection.
|
77
78
|
|
78
|
-
For the `REGION` argument, provide the region of your account, e.g: 'eu', 'us'.
|
79
|
+
For the `REGION` argument, provide the region of your account, e.g: 'eu', 'us' etc.
|
79
80
|
|
80
81
|
Additionally, when connecting via UDP, be sure to specify a port using the udp_port parameter:
|
81
82
|
|
82
|
-
Rails.logger =
|
83
|
+
Rails.logger = R7Insight.new('', 'REGION' :udp_port => 13287)
|
84
|
+
|
85
|
+
|
86
|
+
Contact Support
|
87
|
+
------
|
88
|
+
|
89
|
+
Please email our support team at support@rapid7.com if you need any help.
|
data/Rakefile
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
2
4
|
require 'rake/testtask'
|
3
5
|
|
4
6
|
Rake::TestTask.new do |t|
|
5
|
-
t.libs = [
|
6
|
-
t.test_files = Dir.glob(
|
7
|
+
t.libs = %w[lib test]
|
8
|
+
t.test_files = Dir.glob('test/**/*_spec.rb').sort
|
7
9
|
t.verbose = true
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
11
|
-
task :
|
12
|
+
task default: [:test]
|
13
|
+
task spec: [:test]
|
12
14
|
|
13
|
-
desc
|
15
|
+
desc 'Open an irb session preloaded with this library'
|
14
16
|
task :console do
|
15
|
-
sh
|
17
|
+
sh 'irb -rubygems -I lib -r r7_insight.rb'
|
16
18
|
end
|
data/lib/{le.rb → r7_insight.rb}
RENAMED
@@ -1,11 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
module Le
|
3
|
+
require File.join(File.dirname(__FILE__), 'r7_insight', 'host')
|
6
4
|
|
7
|
-
|
5
|
+
require 'logger'
|
8
6
|
|
7
|
+
# Rapid7 Insight Platform Ruby Logging functionality
|
8
|
+
module R7Insight
|
9
|
+
def self.new(token, region, options = {})
|
9
10
|
opt_local = options[:local] || false
|
10
11
|
opt_debug = options[:debug] || false
|
11
12
|
opt_ssl = !options.include?(:ssl) ? true : options[:ssl]
|
@@ -13,21 +14,18 @@ module Le
|
|
13
14
|
opt_log_level = options[:log_level] || Logger::DEBUG
|
14
15
|
|
15
16
|
opt_datahub_enabled = options[:datahub_enabled] || false
|
16
|
-
opt_datahub_endpoint = options[:datahub_endpoint] || ['',
|
17
|
-
opt_datahub_ip = options[:datahub_ip] || ''
|
18
|
-
opt_datahub_port = options[:datahub_port] || 10000
|
17
|
+
opt_datahub_endpoint = options[:datahub_endpoint] || ['', 10_000]
|
19
18
|
opt_host_id = options[:host_id] || ''
|
20
|
-
opt_host_name_enabled = options[:host_name_enabled] || false
|
21
|
-
opt_host_name = options[:host_name] || ''
|
22
19
|
opt_custom_host = options[:custom_host] || [false, '']
|
23
20
|
|
24
21
|
opt_udp_port = options[:udp_port] || nil
|
25
22
|
opt_use_data_endpoint = options[:data_endpoint] || false
|
26
23
|
|
27
|
-
|
24
|
+
check_params(token, region, opt_datahub_enabled, opt_udp_port)
|
28
25
|
|
29
|
-
|
30
|
-
|
26
|
+
host = R7Insight::Host.new(token, region, opt_local, opt_debug, opt_ssl,
|
27
|
+
opt_datahub_endpoint, opt_host_id, opt_custom_host,
|
28
|
+
opt_udp_port, opt_use_data_endpoint)
|
31
29
|
|
32
30
|
if defined?(ActiveSupport::TaggedLogging) && opt_tag
|
33
31
|
logger = ActiveSupport::TaggedLogging.new(Logger.new(host))
|
@@ -44,22 +42,15 @@ module Le
|
|
44
42
|
logger
|
45
43
|
end
|
46
44
|
|
47
|
-
def self.
|
48
|
-
#
|
45
|
+
def self.check_params(token, region, opt_datahub_enabled, opt_udp_port)
|
46
|
+
# test Token only when DataHub and UDP are not enabled
|
47
|
+
return unless !opt_datahub_enabled && !opt_udp_port
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
(token="")
|
55
|
-
end
|
56
|
-
|
57
|
-
# This checks if region is valid. So far we have Europe and US
|
58
|
-
if !region
|
59
|
-
puts "\nLE: You need to specify region. Options: eu, us"
|
60
|
-
end
|
49
|
+
# Check if the key is valid UUID format
|
50
|
+
if (token =~ /\A(urn:uuid:)?[\da-f]{8}-([\da-f]{4}-){3}[\da-f]{12}\z/i).nil?
|
51
|
+
puts "\nLE: It appears the R7INSIGHT_TOKEN you entered is invalid!\n"
|
52
|
+
end
|
61
53
|
|
62
|
-
|
54
|
+
puts "\nLE: You need to specify region, such as 'eu'" unless region
|
63
55
|
end
|
64
|
-
|
65
56
|
end
|
@@ -1,15 +1,20 @@
|
|
1
|
-
|
2
|
-
module Host
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
module R7Insight
|
4
|
+
# Rapid7 Insight Platform Logging Host
|
5
|
+
module Host
|
6
|
+
def self.new(token, region, local, debug, ssl, datahub_endpoint, host_id,
|
7
|
+
custom_host, udp_port, use_data_endpoint)
|
8
|
+
R7Insight::Host::CONNECTION.new(token, region, local, debug, ssl,
|
9
|
+
datahub_endpoint, host_id, custom_host,
|
10
|
+
udp_port, use_data_endpoint)
|
6
11
|
end
|
7
12
|
|
13
|
+
# Log formatter
|
8
14
|
module InstanceMethods
|
9
15
|
def formatter
|
10
16
|
proc do |severity, datetime, _, msg|
|
11
|
-
|
12
|
-
message << format_message(msg, severity)
|
17
|
+
"#{datetime} #{format_message(msg, severity)}"
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
@@ -19,7 +24,6 @@ module Le
|
|
19
24
|
"severity=#{severity}, #{message_in.lstrip}"
|
20
25
|
end
|
21
26
|
end
|
22
|
-
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
@@ -0,0 +1,300 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'openssl'
|
5
|
+
require 'timeout'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
module R7Insight
|
9
|
+
module Host
|
10
|
+
# Class for connecting to the Rapid7 Insight Platform and handling the
|
11
|
+
# connection
|
12
|
+
class CONNECTION
|
13
|
+
DATA_ENDPOINT = '.data.logs.insight.rapid7.com'
|
14
|
+
DATA_PORT_UNSECURE = 80
|
15
|
+
DATA_PORT_SECURE = 443
|
16
|
+
API_SSL_PORT = 20_000
|
17
|
+
SHUTDOWN_COMMAND = 'DIE!DIE!' # magic shutdown command string for worker
|
18
|
+
SHUTDOWN_MAX_WAIT = 10 # max seconds to wait for queue shutdown clearing
|
19
|
+
SHUTDOWN_WAIT_STEP = 0.2 # sleep duration (seconds) while shutting down
|
20
|
+
CONNECTION_EXCEPTIONS = [
|
21
|
+
Timeout::Error,
|
22
|
+
Errno::EHOSTUNREACH,
|
23
|
+
Errno::ECONNREFUSED,
|
24
|
+
Errno::ECONNRESET,
|
25
|
+
Errno::ETIMEDOUT,
|
26
|
+
EOFError,
|
27
|
+
Errno::EPIPE
|
28
|
+
].freeze
|
29
|
+
|
30
|
+
include R7Insight::Host::InstanceMethods
|
31
|
+
attr_accessor :token, :region, :queue, :started, :thread, :conn, :local,
|
32
|
+
:debug, :ssl, :datahub_enabled, :datahub_ip, :datahub_port,
|
33
|
+
:datahub_endpoint, :host_id, :host_name_enabled, :host_name,
|
34
|
+
:custom_host, :udp_port, :use_data_endpoint
|
35
|
+
|
36
|
+
def initialize(token, region, local, debug, ssl, datahub_endpoint,
|
37
|
+
host_id, custom_host, udp_port, use_data_endpoint)
|
38
|
+
if local
|
39
|
+
device = if local.class <= TrueClass
|
40
|
+
if defined?(Rails)
|
41
|
+
Rails.root.join('log', "#{Rails.env}.log")
|
42
|
+
else
|
43
|
+
STDOUT
|
44
|
+
end
|
45
|
+
else
|
46
|
+
local
|
47
|
+
end
|
48
|
+
@logger_console = Logger.new(device)
|
49
|
+
end
|
50
|
+
|
51
|
+
@region = region
|
52
|
+
@local = local.nil? || local == false ? false : true # Replace "!!"
|
53
|
+
@debug = debug
|
54
|
+
@ssl = ssl
|
55
|
+
@udp_port = udp_port
|
56
|
+
@use_data_endpoint = use_data_endpoint
|
57
|
+
|
58
|
+
@datahub_endpoint = datahub_endpoint
|
59
|
+
if !@datahub_endpoint[0].empty?
|
60
|
+
@datahub_enabled = true
|
61
|
+
@datahub_ip = (@datahub_endpoint[0]).to_s
|
62
|
+
@datahub_port = @datahub_endpoint[1]
|
63
|
+
else
|
64
|
+
@datahub_enabled = false
|
65
|
+
end
|
66
|
+
|
67
|
+
if @datahub_enabled && @ssl
|
68
|
+
puts("\n\nYou Cannot have DataHub and SSL enabled at the same time.
|
69
|
+
Please set SSL value to false in your environment.rb file or used Token-Based
|
70
|
+
logging by leaving the Datahub IP address blank. Exiting application. \n\n")
|
71
|
+
exit
|
72
|
+
end
|
73
|
+
|
74
|
+
# Check if region was specified
|
75
|
+
puts("\n\nYou need to specify a region, such as 'eu'") if region.empty?
|
76
|
+
|
77
|
+
# Check if DataHub is enabled
|
78
|
+
# If datahub is not enabled, set the token to the token's parameter
|
79
|
+
# If DH is enabled, make the token empty.
|
80
|
+
if !datahub_enabled
|
81
|
+
@token = token
|
82
|
+
else
|
83
|
+
@token = ''
|
84
|
+
|
85
|
+
# !NOTE THIS @datahub_port conditional MAY NEED TO BE CHANGED IF SSL
|
86
|
+
# CAN'T WORK WITH DH
|
87
|
+
@datahub_port = @datahub_port.empty? ? API_SSL_PORT : datahub_port
|
88
|
+
@datahub_ip = datahub_ip
|
89
|
+
end
|
90
|
+
|
91
|
+
@host_name_enabled = custom_host[0]
|
92
|
+
@host_name = custom_host[1]
|
93
|
+
|
94
|
+
if !host_id.empty?
|
95
|
+
@host_id = host_id
|
96
|
+
@host_id = "host_id=#{host_id}"
|
97
|
+
else
|
98
|
+
@host_id = ''
|
99
|
+
end
|
100
|
+
|
101
|
+
# If no host name is given but required, assign the machine name
|
102
|
+
if @host_name_enabled
|
103
|
+
@host_name = Socket.gethostname if host_name.empty?
|
104
|
+
|
105
|
+
@host_name = "host_name=#{@host_name}"
|
106
|
+
end
|
107
|
+
|
108
|
+
@queue = Queue.new
|
109
|
+
@started = false
|
110
|
+
@thread = nil
|
111
|
+
|
112
|
+
init_debug if @debug
|
113
|
+
at_exit { shutdown! }
|
114
|
+
end
|
115
|
+
|
116
|
+
def init_debug
|
117
|
+
file_path = 'r7insightGem.log'
|
118
|
+
file_path = 'log/r7insightGem.log' if File.exist?('log/')
|
119
|
+
@debug_logger = Logger.new(file_path)
|
120
|
+
end
|
121
|
+
|
122
|
+
def dbg(message)
|
123
|
+
@debug_logger.add(Logger::Severity::DEBUG, message) if @debug
|
124
|
+
end
|
125
|
+
|
126
|
+
def write(message)
|
127
|
+
message = "#{message} #{host_id}" unless host_id.empty?
|
128
|
+
message = "#{message} #{host_name}" if host_name_enabled
|
129
|
+
|
130
|
+
@logger_console.add(Logger::Severity::UNKNOWN, message) if @local
|
131
|
+
|
132
|
+
@queue << if message.scan(/\n/).empty?
|
133
|
+
"#{@token} #{message} \n"
|
134
|
+
else
|
135
|
+
"#{message.gsub(/^/, "#{@token} [#{random_message_id}]")}\n"
|
136
|
+
end
|
137
|
+
|
138
|
+
if @started
|
139
|
+
check_async_thread
|
140
|
+
else
|
141
|
+
start_async_thread
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def start_async_thread
|
146
|
+
@thread = Thread.new { run }
|
147
|
+
dbg 'R7Insight: Asynchronous socket writer started'
|
148
|
+
@started = true
|
149
|
+
end
|
150
|
+
|
151
|
+
def check_async_thread
|
152
|
+
@thread = Thread.new { run } unless @thread&.alive?
|
153
|
+
end
|
154
|
+
|
155
|
+
def close
|
156
|
+
dbg 'R7Insight: Closing asynchronous socket writer'
|
157
|
+
@started = false
|
158
|
+
end
|
159
|
+
|
160
|
+
def open_connection
|
161
|
+
dbg 'R7Insight: Reopening connection to R7Insight API server'
|
162
|
+
|
163
|
+
if @use_data_endpoint
|
164
|
+
host = @region + DATA_ENDPOINT
|
165
|
+
|
166
|
+
port = @ssl ? DATA_PORT_SECURE : DATA_PORT_UNSECURE
|
167
|
+
elsif @udp_port
|
168
|
+
host = @region + DATA_ENDPOINT
|
169
|
+
port = @udp_port
|
170
|
+
elsif @datahub_enabled
|
171
|
+
host = @datahub_ip
|
172
|
+
port = @datahub_port
|
173
|
+
else
|
174
|
+
host = @region + DATA_ENDPOINT
|
175
|
+
port = @ssl ? DATA_PORT_SECURE : DATA_PORT_UNSECURE
|
176
|
+
end
|
177
|
+
|
178
|
+
if @udp_port
|
179
|
+
@conn = UDPSocket.new
|
180
|
+
@conn.connect(host, port)
|
181
|
+
else
|
182
|
+
socket = TCPSocket.new(host, port)
|
183
|
+
|
184
|
+
if @ssl
|
185
|
+
cert_store = OpenSSL::X509::Store.new
|
186
|
+
cert_store.set_default_paths
|
187
|
+
|
188
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
189
|
+
ssl_context.cert_store = cert_store
|
190
|
+
|
191
|
+
ssl_context.min_version = OpenSSL::SSL::TLS1_1_VERSION
|
192
|
+
ssl_context.max_version = OpenSSL::SSL::TLS1_3_VERSION
|
193
|
+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
194
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
|
195
|
+
ssl_socket.hostname = host if ssl_socket.respond_to?(:hostname=)
|
196
|
+
ssl_socket.sync_close = true
|
197
|
+
Timeout.timeout(10) do
|
198
|
+
ssl_socket.connect
|
199
|
+
end
|
200
|
+
@conn = ssl_socket
|
201
|
+
else
|
202
|
+
@conn = socket
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
dbg 'R7Insight: Connection established'
|
207
|
+
end
|
208
|
+
|
209
|
+
def reopen_connection
|
210
|
+
close_connection
|
211
|
+
root_delay = 0.1
|
212
|
+
loop do
|
213
|
+
begin
|
214
|
+
open_connection
|
215
|
+
break
|
216
|
+
rescue *CONNECTION_EXCEPTIONS
|
217
|
+
dbg "R7Insight: Unable to connect to R7Insight due to timeout
|
218
|
+
(#{$ERROR_INFO})"
|
219
|
+
rescue StandardError
|
220
|
+
dbg "R7Insight: Got exception in reopenConnection - #{$ERROR_INFO}"
|
221
|
+
raise
|
222
|
+
end
|
223
|
+
root_delay *= 2
|
224
|
+
root_delay = 10 if root_delay >= 10
|
225
|
+
wait_for = (root_delay + rand(root_delay)).to_i
|
226
|
+
dbg "R7Insight: Waiting for #{wait_for}ms"
|
227
|
+
sleep(wait_for)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def close_connection
|
232
|
+
begin
|
233
|
+
if @conn.respond_to?(:sysclose)
|
234
|
+
@conn.sysclose
|
235
|
+
elsif @conn.respond_to?(:close)
|
236
|
+
@conn.close
|
237
|
+
end
|
238
|
+
rescue StandardError
|
239
|
+
dbg "R7Insight: couldn't close connection, close with exception -
|
240
|
+
#{$ERROR_INFO}"
|
241
|
+
ensure
|
242
|
+
@conn = nil
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def run
|
247
|
+
reopen_connection
|
248
|
+
|
249
|
+
loop do
|
250
|
+
data = @queue.pop
|
251
|
+
break if data == SHUTDOWN_COMMAND
|
252
|
+
|
253
|
+
loop do
|
254
|
+
begin
|
255
|
+
@conn.write(data)
|
256
|
+
rescue *CONNECTION_EXCEPTIONS
|
257
|
+
dbg "R7Insight: Connection timeout(#{$ERROR_INFO}), try to reopen
|
258
|
+
connection"
|
259
|
+
reopen_connection
|
260
|
+
next
|
261
|
+
rescue StandardError
|
262
|
+
dbg "R7Insight: Got exception in run loop - #{$ERROR_INFO}"
|
263
|
+
raise
|
264
|
+
end
|
265
|
+
break
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
dbg 'R7Insight: Closing Asynchronous socket writer'
|
270
|
+
|
271
|
+
close_connection
|
272
|
+
end
|
273
|
+
|
274
|
+
private
|
275
|
+
|
276
|
+
def random_message_id
|
277
|
+
@random_message_id_sample_space ||= ('0'..'9').to_a.concat(('A'..'Z')
|
278
|
+
.to_a)
|
279
|
+
(0..5).map { @random_message_id_sample_space.sample }.join
|
280
|
+
end
|
281
|
+
|
282
|
+
# at_exit handler.
|
283
|
+
# Attempts to clear the queue and terminate the async worker cleanly
|
284
|
+
# before process ends.
|
285
|
+
def shutdown!
|
286
|
+
return unless @started
|
287
|
+
|
288
|
+
dbg "R7Insight: commencing shutdown, queue has #{queue.size} entries to clear"
|
289
|
+
queue << SHUTDOWN_COMMAND
|
290
|
+
SHUTDOWN_MAX_WAIT.div(SHUTDOWN_WAIT_STEP).times do
|
291
|
+
break if queue.empty?
|
292
|
+
|
293
|
+
sleep SHUTDOWN_WAIT_STEP
|
294
|
+
end
|
295
|
+
dbg "R7Insight: shutdown complete, queue is #{queue.empty? ? '' : 'not '}
|
296
|
+
empty with #{queue.size} entries"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|