fluent-plugin-rds-mysql-log 0.1.1 → 0.1.5
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/fluent-plugin-rds-mysql-log.gemspec +2 -2
- data/lib/fluent/plugin/in_rds_mysql_log.rb +50 -43
- data/test/plugin/test_in_rds_mysql_log.rb +25 -23
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d9944b03c4974a63ee62fdbb1337b0e230022a300a9f9ddb21c7966ac5917fa
|
4
|
+
data.tar.gz: 9c331cb21f94f2ab6a00cd196dd1a014a449e629be8d8920d7113f5ed41ec930
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad22c2ee1f23446bfbe0d19dc9a6a4e4de121d43b7eae3a0c945009019f1adf2d77190a8564039e58f28bd57223be20a44f7f41cbb22ca07371989c9cbccfca4
|
7
|
+
data.tar.gz: f76bf589f490c1e9dd81ba5da40bbf587d53c0a89da1147586f015021fb7dc4a7c00f7aef534451a64bbd07e0976a9150c69fbbef420434f39369428cb67ac02
|
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'fluent-plugin-rds-mysql-log'
|
8
|
-
spec.version = '0.1.
|
8
|
+
spec.version = '0.1.5'
|
9
9
|
spec.authors = ['Junaid Ali']
|
10
10
|
spec.email = ['jonnie36@yahoo.com']
|
11
11
|
spec.summary = 'Amazon RDS Mysql logs input plugin'
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = 'https://github.com/iamjunaidali/fluent-plugin-rds-mysql-log.git'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
spec.required_ruby_version = '>= 2.7.0'
|
16
|
-
|
16
|
+
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
@@ -75,6 +75,18 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
75
75
|
log.warn "EC2 Client error occurred: #{e.message}"
|
76
76
|
end
|
77
77
|
end
|
78
|
+
|
79
|
+
def is_audit_logs?
|
80
|
+
@pos_info.keys.any? { |log_file_name| log_file_name =~ AUDIT_LOG_PATTERN }
|
81
|
+
end
|
82
|
+
|
83
|
+
def should_track_marker?(log_file_name)
|
84
|
+
return true if log_file_name == "audit/server_audit.log"
|
85
|
+
return true if log_file_name == "general/mysql-general.log"
|
86
|
+
return true if log_file_name == "error/mysql-error-running.log"
|
87
|
+
|
88
|
+
false
|
89
|
+
end
|
78
90
|
|
79
91
|
def get_and_parse_posfile
|
80
92
|
begin
|
@@ -83,21 +95,23 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
83
95
|
|
84
96
|
pos_last_written_timestamp = 0
|
85
97
|
pos_info = {}
|
98
|
+
|
86
99
|
File.open(@pos_file, File::RDONLY) do |file|
|
87
100
|
file.each_line do |line|
|
101
|
+
|
88
102
|
pos_match = /^(\d+)$/.match(line)
|
89
103
|
if pos_match
|
90
|
-
pos_last_written_timestamp = pos_match[1].to_i
|
104
|
+
pos_last_written_timestamp = pos_match[1].to_i
|
91
105
|
log.debug "pos_last_written_timestamp: #{pos_last_written_timestamp}"
|
92
106
|
end
|
93
107
|
|
94
108
|
pos_match = /^(.+)\t(.+)$/.match(line)
|
95
109
|
if pos_match
|
96
110
|
pos_info[pos_match[1]] = pos_match[2]
|
97
|
-
p pos_info
|
98
111
|
log.debug "log_file: #{pos_match[1]}, marker: #{pos_match[2]}"
|
99
112
|
end
|
100
113
|
end
|
114
|
+
|
101
115
|
@pos_last_written_timestamp = pos_last_written_timestamp
|
102
116
|
@pos_info = pos_info
|
103
117
|
end
|
@@ -106,43 +120,22 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
106
120
|
end
|
107
121
|
end
|
108
122
|
|
109
|
-
def put_posfile
|
110
|
-
# pos file write
|
111
|
-
begin
|
112
|
-
log.debug "pos file write"
|
113
|
-
File.open(@pos_file, File::WRONLY|File::TRUNC) do |file|
|
114
|
-
file.puts @pos_last_written_timestamp.to_s
|
115
|
-
|
116
|
-
@pos_info.each do |log_file_name, marker|
|
117
|
-
file.puts "#{log_file_name}\t#{marker}"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
rescue => e
|
121
|
-
log.warn "pos file write error occurred: #{e.message}"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
123
|
def get_logfile_list
|
126
124
|
begin
|
127
125
|
log.debug "get logfile-list from rds: db_instance_identifier=#{@db_instance_identifier}, pos_last_written_timestamp=#{@pos_last_written_timestamp}"
|
128
126
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
# Use custom interval for audit logs
|
135
|
-
(Time.now.to_i - @refresh_interval) * 1000
|
127
|
+
if is_audit_logs?
|
128
|
+
@rds.describe_db_log_files(
|
129
|
+
db_instance_identifier: @db_instance_identifier,
|
130
|
+
max_records: 10
|
131
|
+
)
|
136
132
|
else
|
137
|
-
|
138
|
-
|
133
|
+
@rds.describe_db_log_files(
|
134
|
+
db_instance_identifier: @db_instance_identifier,
|
135
|
+
file_last_written: @pos_last_written_timestamp,
|
136
|
+
max_records: 10,
|
137
|
+
)
|
139
138
|
end
|
140
|
-
|
141
|
-
@rds.describe_db_log_files(
|
142
|
-
db_instance_identifier: @db_instance_identifier,
|
143
|
-
file_last_written: file_last_written,
|
144
|
-
max_records: 10,
|
145
|
-
)
|
146
139
|
rescue => e
|
147
140
|
log.warn "RDS Client describe_db_log_files error occurred: #{e.message}"
|
148
141
|
end
|
@@ -155,9 +148,8 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
155
148
|
# save maximum written timestamp value
|
156
149
|
@pos_last_written_timestamp = item[:last_written] if @pos_last_written_timestamp < item[:last_written]
|
157
150
|
|
158
|
-
# log file download
|
159
151
|
log_file_name = item[:log_file_name]
|
160
|
-
marker = @pos_info[log_file_name] || "0"
|
152
|
+
marker = should_track_marker?(log_file_name) ? @pos_info[log_file_name] || "0" : "0"
|
161
153
|
|
162
154
|
log.debug "download log from rds: log_file_name=#{log_file_name}, marker=#{marker}"
|
163
155
|
logs = @rds.download_db_log_file_portion(
|
@@ -169,12 +161,7 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
169
161
|
raw_records = get_logdata(logs)
|
170
162
|
|
171
163
|
#emit
|
172
|
-
parse_and_emit(raw_records, log_file_name) unless raw_records
|
173
|
-
|
174
|
-
# Save new last_written timestamp **only for non-audit logs**
|
175
|
-
unless log_file_name =~ AUDIT_LOG_PATTERN
|
176
|
-
@pos_last_written_timestamp = item[:last_written] if @pos_last_written_timestamp < item[:last_written]
|
177
|
-
end
|
164
|
+
parse_and_emit(raw_records, log_file_name) unless raw_records&.empty?
|
178
165
|
end
|
179
166
|
end
|
180
167
|
rescue => e
|
@@ -187,10 +174,12 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
187
174
|
raw_records = []
|
188
175
|
begin
|
189
176
|
logs.each do |log|
|
190
|
-
|
191
|
-
@pos_info[log_file_name] = log.marker
|
177
|
+
next if log.log_file_data.nil? || log.log_file_data.empty?
|
192
178
|
|
193
179
|
raw_records += log.log_file_data.split("\n")
|
180
|
+
|
181
|
+
# Update marker only if we actually got some data
|
182
|
+
@pos_info[log_file_name] = log.marker if should_track_marker?(log_file_name)
|
194
183
|
end
|
195
184
|
rescue => e
|
196
185
|
log.warn e.message
|
@@ -252,6 +241,24 @@ class Fluent::Plugin::RdsMysqlLogInput < Fluent::Plugin::Input
|
|
252
241
|
log.warn e.message
|
253
242
|
end
|
254
243
|
end
|
244
|
+
|
245
|
+
def put_posfile
|
246
|
+
# pos file write
|
247
|
+
begin
|
248
|
+
log.debug "pos file write"
|
249
|
+
File.open(@pos_file, File::WRONLY|File::TRUNC) do |file|
|
250
|
+
log.debug "Writing pos file with timestamp=#{@pos_last_written_timestamp} and pos_info=#{@pos_info.inspect}"
|
251
|
+
@pos_info.delete_if { |file, _| !should_track_marker?(file) }
|
252
|
+
file.puts @pos_last_written_timestamp.to_s
|
253
|
+
|
254
|
+
@pos_info.each do |log_file_name, marker|
|
255
|
+
file.puts "#{log_file_name}\t#{marker}"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
rescue => e
|
259
|
+
log.warn "pos file write error occurred: #{e.message}"
|
260
|
+
end
|
261
|
+
end
|
255
262
|
|
256
263
|
class TimerWatcher < Coolio::TimerWatcher
|
257
264
|
def initialize(interval, repeat, &callback)
|
@@ -56,7 +56,7 @@ class RdsMysqlLogInputTest < Test::Unit::TestCase
|
|
56
56
|
aws_client_stub = Aws::RDS::Client.new(stub_responses: {
|
57
57
|
describe_db_log_files: {
|
58
58
|
describe_db_log_files: [
|
59
|
-
{ log_file_name: 'server_audit.log', last_written: 123456789, size: 123 }
|
59
|
+
{ log_file_name: 'audit/server_audit.log', last_written: 123456789, size: 123 }
|
60
60
|
],
|
61
61
|
marker: 'old_marker'
|
62
62
|
},
|
@@ -73,10 +73,8 @@ class RdsMysqlLogInputTest < Test::Unit::TestCase
|
|
73
73
|
d.run(timeout: 3, expect_emits: 1)
|
74
74
|
events = d.events
|
75
75
|
|
76
|
-
assert_equal(events[0][2]["log_file_name"], 'server_audit.log')
|
76
|
+
assert_equal(events[0][2]["log_file_name"], 'audit/server_audit.log')
|
77
77
|
assert_equal(events[0][2]["message"], "UPDATE table SET id=123, updated_at=\'2025-04-03 19:38:08.681797\', is_weight_saved=1 WHERE table.id = 1234")
|
78
|
-
|
79
|
-
# assert_equal(d.instance.instance_variable_get(:@pos_info)['server_audit.log'], 'new_marker')
|
80
78
|
end
|
81
79
|
|
82
80
|
def test_get_non_audit_log_files
|
@@ -87,7 +85,7 @@ class RdsMysqlLogInputTest < Test::Unit::TestCase
|
|
87
85
|
describe_db_log_files: {
|
88
86
|
describe_db_log_files: [
|
89
87
|
{
|
90
|
-
log_file_name: 'error.log',
|
88
|
+
log_file_name: 'error/mysql-error-running.log',
|
91
89
|
last_written: 123456789,
|
92
90
|
size: 123
|
93
91
|
}
|
@@ -110,7 +108,7 @@ class RdsMysqlLogInputTest < Test::Unit::TestCase
|
|
110
108
|
|
111
109
|
events = d.events
|
112
110
|
|
113
|
-
assert_equal(events[0][2]["log_file_name"], 'error.log')
|
111
|
+
assert_equal(events[0][2]["log_file_name"], 'error/mysql-error-running.log')
|
114
112
|
assert_equal(events[0][2]["message"], "IP address '1.2.3.4' could not be resolved: Name or service not known")
|
115
113
|
|
116
114
|
# Ensure non-audit logs used `pos_last_written_timestamp`
|
@@ -120,38 +118,42 @@ class RdsMysqlLogInputTest < Test::Unit::TestCase
|
|
120
118
|
def test_get_audit_log_files
|
121
119
|
use_iam_role
|
122
120
|
d = create_driver
|
123
|
-
|
121
|
+
first_log_line = "20250403 19:41:01,ip-1-1-1-1,service,1.2.3.4,12345678,1234567890,QUERY,test_db,'UPDATE table SET id=123, updated_at=\'2025-04-03 19:38:08.681797\', is_weight_saved=1 WHERE table.id = 1234',0,,"
|
122
|
+
second_log_line = "20250403 19:42:01,ip-1-1-1-1,service,1.2.3.4,12345678,1234567890,QUERY,test_db,'UPDATE table SET id=456, updated_at=\'2025-04-03 19:38:08.681797\', is_weight_saved=1 WHERE table.id = 5678',0,,"
|
123
|
+
|
124
124
|
aws_client_stub = Aws::RDS::Client.new(stub_responses: {
|
125
125
|
describe_db_log_files: {
|
126
126
|
describe_db_log_files: [
|
127
127
|
{
|
128
|
-
log_file_name: 'server_audit.log',
|
128
|
+
log_file_name: 'audit/server_audit.log',
|
129
129
|
last_written: Time.now.to_i,
|
130
130
|
size: 123
|
131
131
|
}
|
132
132
|
],
|
133
133
|
marker: 'marker'
|
134
134
|
},
|
135
|
-
download_db_log_file_portion:
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
135
|
+
download_db_log_file_portion: [
|
136
|
+
{
|
137
|
+
log_file_data: first_log_line,
|
138
|
+
marker: 'marker',
|
139
|
+
additional_data_pending: false
|
140
|
+
},
|
141
|
+
{
|
142
|
+
log_file_data: second_log_line,
|
143
|
+
marker: 'marker',
|
144
|
+
additional_data_pending: false
|
145
|
+
}
|
146
|
+
]
|
140
147
|
})
|
141
148
|
|
142
149
|
d.instance.instance_variable_set(:@rds, aws_client_stub)
|
143
|
-
|
144
|
-
d.instance.instance_variable_set(:@pos_last_written_timestamp, (Time.now.to_i - (2*2000)))
|
145
|
-
|
146
|
-
test_start_time = Time.now.to_i
|
147
|
-
buffer_time = 5 * d.instance.refresh_interval * 20000
|
148
|
-
|
149
|
-
d.run(timeout: 3, expect_emits: 1)
|
150
|
+
d.run(timeout: 3, expect_emits: 2)
|
150
151
|
|
151
152
|
events = d.events
|
152
|
-
assert_equal(
|
153
|
+
assert_equal(2, events.size)
|
154
|
+
assert_equal(events[0][2]["log_file_name"], 'audit/server_audit.log')
|
153
155
|
assert_equal(events[0][2]["message"], "UPDATE table SET id=123, updated_at=\'2025-04-03 19:38:08.681797\', is_weight_saved=1 WHERE table.id = 1234")
|
154
|
-
|
155
|
-
|
156
|
+
assert_equal(events[1][2]["log_file_name"], 'audit/server_audit.log')
|
157
|
+
assert_equal(events[1][2]["message"], "UPDATE table SET id=456, updated_at=\'2025-04-03 19:38:08.681797\', is_weight_saved=1 WHERE table.id = 5678")
|
156
158
|
end
|
157
159
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-rds-mysql-log
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Junaid Ali
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-08 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: aws-sdk-ec2
|