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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78512899f0c19ab34bc36d7058c9481cc04dbd5362a82b11a3c02af9e2a541e7
4
- data.tar.gz: 414d246d14e327b23737655c77709b1d788297604c41e67b8a4cac5c333b3c7e
3
+ metadata.gz: 9d9944b03c4974a63ee62fdbb1337b0e230022a300a9f9ddb21c7966ac5917fa
4
+ data.tar.gz: 9c331cb21f94f2ab6a00cd196dd1a014a449e629be8d8920d7113f5ed41ec930
5
5
  SHA512:
6
- metadata.gz: 6bc9550cc2825150c00536f739552967dba5aca43530c860ea1b4000899ac37b4dd4f3ab1227a88897ba2ec7d74d4e6345ab61d6f71c9724cfa52e1a4dd4fab8
7
- data.tar.gz: e998ce6330b33e8ec74e4952032b6e8213e264ccb7fefc6299b8e0c7e3a09a553fe579566e20b92d558bb1ffe6d0ed24c1c9190d51f8a6853bf27962f921a743
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.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
- # Separate audit logs from other logs
130
-
131
- audit_logs_exist = @pos_info.keys.any? { |log_file_name| log_file_name =~ AUDIT_LOG_PATTERN }
132
-
133
- file_last_written = if audit_logs_exist
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
- # Use default timestamp for other logs
138
- @pos_last_written_timestamp
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.nil?
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
- # save got line's marker
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
- log_file_data: "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,,",
137
- marker: 'marker',
138
- additional_data_pending: false
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(events[0][2]["log_file_name"], 'server_audit.log')
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
- assert_operator events[0][1].to_i, :>=, (test_start_time - (buffer_time))
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.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-05 00:00:00.000000000 Z
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