vigilant-ruby 0.0.1
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 +7 -0
- data/README.md +3 -0
- data/lib/logger.rb +170 -0
- data/lib/version.rb +5 -0
- data/lib/vigilant.rb +39 -0
- metadata +132 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 566350402bd00065cebbcc1e5da5bf587dc4be324f9fa313a7b7f5d9719cb837
|
4
|
+
data.tar.gz: 83eccb0b3bd2f73257387ced365a23c0e1b1c0a9e75fb2ccd95144537147783d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 14b68b0e635d54639104bcb4ed8de3eafb262aec287cf69a17a6fc9ddde3f4d0106db08b58ef80f4c85a522e4c0d2f557928d952b22af3744bb4f90d54336582
|
7
|
+
data.tar.gz: 5a4ca0ee07974027fc5ef68f63c9e1e1dcb96707458520475c9cb113b9c0e619653681b3a6993e3b98955343d7514bf7acc58225dd23941b67da9f71367359bb
|
data/README.md
ADDED
data/lib/logger.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'time'
|
6
|
+
require 'vigilant/version'
|
7
|
+
|
8
|
+
module Vigilant
|
9
|
+
TRACE = 'TRACE'
|
10
|
+
DEBUG = 'DEBUG'
|
11
|
+
INFO = 'INFO'
|
12
|
+
WARNING = 'WARNING'
|
13
|
+
ERROR = 'ERROR'
|
14
|
+
FATAL = 'FATAL'
|
15
|
+
|
16
|
+
DEFAULT_BATCH_SIZE = 10
|
17
|
+
DEFAULT_FLUSH_INTERVAL = 5
|
18
|
+
|
19
|
+
# A thread-safe logger that batches logs and sends them to Vigilant asynchronously
|
20
|
+
class Logger
|
21
|
+
# Initialize a Vigilant::Logger instance.
|
22
|
+
#
|
23
|
+
# @param endpoint [String] The base endpoint for the Vigilant API (e.g. "ingress.vigilant.run").
|
24
|
+
# @param token [String] The authentication token for the Vigilant API.
|
25
|
+
# @param insecure [Boolean] Whether to use HTTP instead of HTTPS (optional, defaults to false).
|
26
|
+
def initialize(endpoint:, token:, insecure: false)
|
27
|
+
@token = token
|
28
|
+
protocol = insecure ? 'http://' : 'https://'
|
29
|
+
endpoint = endpoint.sub(%r{^https?://}, '') # Remove any existing protocol
|
30
|
+
@endpoint = URI.parse("#{protocol}#{endpoint}/api/message")
|
31
|
+
@insecure = insecure
|
32
|
+
|
33
|
+
@batch_size = DEFAULT_BATCH_SIZE
|
34
|
+
@flush_interval = DEFAULT_FLUSH_INTERVAL
|
35
|
+
|
36
|
+
@queue = Queue.new
|
37
|
+
@mutex = Mutex.new
|
38
|
+
@batch = []
|
39
|
+
|
40
|
+
start_dispatcher
|
41
|
+
end
|
42
|
+
|
43
|
+
# Logs a TRACE message.
|
44
|
+
#
|
45
|
+
# @param body [String] The main text of the trace message.
|
46
|
+
# @param attributes [Hash] Additional attributes for the log (optional).
|
47
|
+
def trace(body, attributes = {})
|
48
|
+
enqueue_log(TRACE, body, attributes)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Logs a DEBUG message.
|
52
|
+
#
|
53
|
+
# @param body [String] The main text of the debug message.
|
54
|
+
# @param attributes [Hash] Additional attributes for the log (optional).
|
55
|
+
def debug(body, attributes = {})
|
56
|
+
enqueue_log(DEBUG, body, attributes)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Logs an INFO message.
|
60
|
+
#
|
61
|
+
# @param body [String] The main text of the log message.
|
62
|
+
# @param attributes [Hash] Additional attributes for the log (optional).
|
63
|
+
def info(body, attributes = {})
|
64
|
+
enqueue_log(INFO, body, attributes)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Logs a WARNING message.
|
68
|
+
#
|
69
|
+
# @param body [String] The main text of the warning message.
|
70
|
+
# @param attributes [Hash] Additional attributes for the log (optional).
|
71
|
+
def warn(body, attributes = {})
|
72
|
+
enqueue_log(WARNING, body, attributes)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Logs an ERROR message.
|
76
|
+
#
|
77
|
+
# @param body [String] The main text of the error message.
|
78
|
+
# @param error [Exception] The error object.
|
79
|
+
# @param attributes [Hash] Additional attributes for the log (optional).
|
80
|
+
def error(body, error = nil, attributes = {})
|
81
|
+
if error.nil?
|
82
|
+
enqueue_log(ERROR, body, attributes)
|
83
|
+
else
|
84
|
+
attributes_with_error = { error: error.message, **attributes }
|
85
|
+
enqueue_log(ERROR, body, attributes_with_error)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Logs a FATAL message.
|
90
|
+
#
|
91
|
+
# @param body [String] The main text of the fatal message.
|
92
|
+
# @param attributes [Hash] Additional attributes for the log (optional).
|
93
|
+
def fatal(body, attributes = {})
|
94
|
+
enqueue_log(FATAL, body, attributes)
|
95
|
+
end
|
96
|
+
|
97
|
+
def shutdown
|
98
|
+
flush_if_needed(true)
|
99
|
+
|
100
|
+
@mutex.synchronize do
|
101
|
+
@shutdown = true
|
102
|
+
end
|
103
|
+
|
104
|
+
@dispatcher_thread&.join
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def enqueue_log(level, body, attributes)
|
110
|
+
string_attributes = attributes.transform_values(&:to_s)
|
111
|
+
log_msg = {
|
112
|
+
timestamp: Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S.%9NZ'),
|
113
|
+
body: body.to_s,
|
114
|
+
level: level.to_s,
|
115
|
+
attributes: string_attributes
|
116
|
+
}
|
117
|
+
@queue << log_msg
|
118
|
+
end
|
119
|
+
|
120
|
+
def start_dispatcher
|
121
|
+
@shutdown = false
|
122
|
+
@dispatcher_thread = Thread.new do
|
123
|
+
until @mutex.synchronize { @shutdown }
|
124
|
+
flush_if_needed
|
125
|
+
sleep @flush_interval
|
126
|
+
end
|
127
|
+
flush_if_needed(true)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def flush_if_needed(force = false)
|
132
|
+
until @queue.empty?
|
133
|
+
msg = @queue.pop
|
134
|
+
@mutex.synchronize { @batch << msg }
|
135
|
+
end
|
136
|
+
|
137
|
+
@mutex.synchronize do
|
138
|
+
flush! if force || @batch.size >= @batch_size || !@batch.empty?
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def flush!
|
143
|
+
return if @batch.empty?
|
144
|
+
|
145
|
+
logs_to_send = @batch.dup
|
146
|
+
@batch.clear
|
147
|
+
|
148
|
+
request_body = {
|
149
|
+
token: @token,
|
150
|
+
type: 'logs',
|
151
|
+
logs: logs_to_send
|
152
|
+
}
|
153
|
+
|
154
|
+
post_logs(request_body)
|
155
|
+
rescue StandardError => e
|
156
|
+
warn("Failed to send logs: #{e.message}")
|
157
|
+
end
|
158
|
+
|
159
|
+
def post_logs(batch_data)
|
160
|
+
http = Net::HTTP.new(@endpoint.host, @endpoint.port)
|
161
|
+
http.use_ssl = !@insecure
|
162
|
+
|
163
|
+
request = Net::HTTP::Post.new(@endpoint)
|
164
|
+
request['Content-Type'] = 'application/json'
|
165
|
+
request.body = JSON.dump(batch_data)
|
166
|
+
|
167
|
+
http.request(request)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/lib/version.rb
ADDED
data/lib/vigilant.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'version'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# Vigilant is a logging service that provides structured logging capabilities
|
7
|
+
# with asynchronous batch processing and thread-safe operations.
|
8
|
+
module Vigilant
|
9
|
+
class Error < StandardError; end
|
10
|
+
|
11
|
+
# Configuration for the Vigilant logging service.
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :endpoint, :token, :insecure
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@endpoint = 'ingress.vigilant.run'
|
17
|
+
@insecure = false
|
18
|
+
@token = 'tk_1234567890'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def configuration
|
24
|
+
@configuration ||= Configuration.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def configure
|
28
|
+
yield(configuration) if block_given?
|
29
|
+
end
|
30
|
+
|
31
|
+
def logger
|
32
|
+
@logger ||= Vigilant::Logger.new(
|
33
|
+
endpoint: configuration.endpoint,
|
34
|
+
insecure: configuration.insecure,
|
35
|
+
token: configuration.token
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vigilant-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vigilant
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-27 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: json
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '2.0'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '2.0'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: rake
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '13.0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '13.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rspec
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rubocop
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: yard
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.9'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.9'
|
96
|
+
description: Official Ruby SDK for interacting with the Vigilant API
|
97
|
+
email:
|
98
|
+
- izak@vigilant.run
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- README.md
|
104
|
+
- lib/logger.rb
|
105
|
+
- lib/version.rb
|
106
|
+
- lib/vigilant.rb
|
107
|
+
homepage: https://vigilant.run
|
108
|
+
licenses:
|
109
|
+
- MIT
|
110
|
+
metadata:
|
111
|
+
homepage_uri: https://vigilant.run
|
112
|
+
source_code_uri: https://github.com/vigilant-run/vigilant-ruby
|
113
|
+
changelog_uri: https://vigilant.run/changelog
|
114
|
+
rubygems_mfa_required: 'true'
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 2.6.0
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubygems_version: 3.6.2
|
130
|
+
specification_version: 4
|
131
|
+
summary: Ruby SDK for Vigilant
|
132
|
+
test_files: []
|