systemd-journal 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/README.md +25 -2
- data/Rakefile +6 -6
- data/lib/systemd/id128.rb +9 -0
- data/lib/systemd/journal.rb +33 -246
- data/lib/systemd/journal/filterable.rb +102 -0
- data/lib/systemd/journal/native.rb +9 -6
- data/lib/systemd/journal/navigable.rb +112 -0
- data/lib/systemd/journal/version.rb +1 -1
- data/lib/systemd/journal/waitable.rb +74 -0
- data/lib/systemd/journal/{compat.rb → writable.rb} +4 -3
- data/lib/systemd/journal_entry.rb +27 -2
- data/spec/no_ffi.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/systemd/id128_spec.rb +5 -5
- data/spec/systemd/journal_entry_spec.rb +69 -15
- data/spec/systemd/journal_spec.rb +206 -125
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df7fe5c76f75b85e1c6ae332b5dc4db8268956c9
|
4
|
+
data.tar.gz: ddb32ec9f34855f7fe8ae5bfef85f5c8606b9295
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1aa3dd8871ac3b44fe9e063a5fef7ed300f2580a76ebb0a122951dd1136fe86c99322f5342515fafcaf723c337b90ccc59a4a89c47cb02fe007912ba9e493b6f
|
7
|
+
data.tar.gz: 30018c03c4cc3178e2798c9f7edf60d290cdef165ee41bccc5a9256f0fe922b5f9473a6f6fb6d3fe8662f56111eef6878729874b05bc69b06729c4e521a1c6b5
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Systemd::Journal [![Gem Version](https://badge.fury.io/rb/systemd-journal.png)](http://badge.fury.io/rb/systemd-journal) [![Build Status](https://travis-ci.org/ledbettj/systemd-journal.png?branch=master)](https://travis-ci.org/ledbettj/systemd-journal)
|
1
|
+
# Systemd::Journal [![Gem Version](https://badge.fury.io/rb/systemd-journal.png)](http://badge.fury.io/rb/systemd-journal) [![Build Status](https://travis-ci.org/ledbettj/systemd-journal.png?branch=master)](https://travis-ci.org/ledbettj/systemd-journal) [![Code Climate](https://codeclimate.com/github/ledbettj/systemd-journal.png)](https://codeclimate.com/github/ledbettj/systemd-journal)
|
2
2
|
|
3
3
|
Ruby bindings for reading from the systemd journal.
|
4
4
|
|
@@ -9,7 +9,7 @@ Ruby bindings for reading from the systemd journal.
|
|
9
9
|
|
10
10
|
Add this line to your application's Gemfile:
|
11
11
|
|
12
|
-
gem 'systemd-journal', '~> 1.
|
12
|
+
gem 'systemd-journal', '~> 1.1.0'
|
13
13
|
|
14
14
|
And then execute:
|
15
15
|
|
@@ -62,6 +62,27 @@ Moving around the journal:
|
|
62
62
|
# seek the entry that occured closest to this time
|
63
63
|
j.seek(Time.parse("2013-10-31T12:00:00+04:00:00"))
|
64
64
|
|
65
|
+
Waiting for things to happen:
|
66
|
+
|
67
|
+
j = Systemd::Journal.new
|
68
|
+
j.seek(:tail)
|
69
|
+
# wait up to one second for something to happen
|
70
|
+
if j.wait(1_000_000)
|
71
|
+
puts 'something changed!'
|
72
|
+
# same as above, but can be interrupted with Control+C.
|
73
|
+
if j.wait(1_000_000, select: true)
|
74
|
+
puts 'something changed!'
|
75
|
+
|
76
|
+
Accessing the catalog:
|
77
|
+
|
78
|
+
j = Systemd::Journal.new
|
79
|
+
j.move_next
|
80
|
+
j.move_next while !j.current_entry.catalog?
|
81
|
+
|
82
|
+
puts j.current_entry.catalog
|
83
|
+
# or if you have a message id:
|
84
|
+
puts Systemd::Journal.catalog_for(j.current_entry.message_id)
|
85
|
+
|
65
86
|
|
66
87
|
See the documentation for more examples.
|
67
88
|
|
@@ -78,3 +99,5 @@ If you run into problems or have questions, please open an
|
|
78
99
|
4. Push to the branch (`git push origin my-new-feature`)
|
79
100
|
5. Create new Pull Request, targeting the __develop__ branch.
|
80
101
|
6. Wipe hands on pants, you're done.
|
102
|
+
|
103
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/ledbettj/systemd-journal/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
data/Rakefile
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'yard'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'rubocop/rake_task'
|
5
5
|
|
6
|
-
desc
|
6
|
+
desc 'open a console with systemd/journal required'
|
7
7
|
task :console do
|
8
8
|
exec 'pry -I./lib -r systemd/journal'
|
9
9
|
end
|
10
10
|
|
11
11
|
Rubocop::RakeTask.new(:rubocop) do |task|
|
12
|
-
task.patterns = ['lib/**/*.rb']
|
12
|
+
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
|
13
13
|
task.fail_on_error = false
|
14
14
|
end
|
15
15
|
|
data/lib/systemd/id128.rb
CHANGED
data/lib/systemd/journal.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'systemd/journal/native'
|
2
2
|
require 'systemd/journal/flags'
|
3
|
-
require 'systemd/journal/
|
3
|
+
require 'systemd/journal/writable'
|
4
4
|
require 'systemd/journal/fields'
|
5
|
+
require 'systemd/journal/navigable'
|
6
|
+
require 'systemd/journal/filterable'
|
7
|
+
require 'systemd/journal/waitable'
|
5
8
|
require 'systemd/journal_error'
|
6
9
|
require 'systemd/journal_entry'
|
7
10
|
require 'systemd/id128'
|
@@ -12,11 +15,14 @@ module Systemd
|
|
12
15
|
# Class to allow interacting with the systemd journal.
|
13
16
|
# To read from the journal, instantiate a new {Systemd::Journal}; to write to
|
14
17
|
# the journal, use
|
15
|
-
# {Systemd::Journal::
|
16
|
-
# {Systemd::Journal::
|
18
|
+
# {Systemd::Journal::Writable::ClassMethods#message Journal.message} or
|
19
|
+
# {Systemd::Journal::Writable::ClassMethods#print Journal.print}.
|
17
20
|
class Journal
|
18
21
|
include Enumerable
|
19
|
-
include Systemd::Journal::
|
22
|
+
include Systemd::Journal::Writable
|
23
|
+
include Systemd::Journal::Navigable
|
24
|
+
include Systemd::Journal::Filterable
|
25
|
+
include Systemd::Journal::Waitable
|
20
26
|
|
21
27
|
# Returns a new instance of a Journal, opened with the provided options.
|
22
28
|
# @param [Hash] opts optional initialization parameters.
|
@@ -60,115 +66,6 @@ module Systemd
|
|
60
66
|
yield current_entry while move_next
|
61
67
|
end
|
62
68
|
|
63
|
-
# Move the read pointer by `offset` entries.
|
64
|
-
# @param [Integer] offset how many entries to move the read pointer by. If
|
65
|
-
# this value is positive, the read pointer moves forward. Otherwise, it
|
66
|
-
# moves backwards.
|
67
|
-
# @return [Integer] the number of entries the read pointer actually moved.
|
68
|
-
def move(offset)
|
69
|
-
offset > 0 ? move_next_skip(offset) : move_previous_skip(-offset)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Filter the journal at a high level.
|
73
|
-
# Takes any number of arguments; each argument should be a hash representing
|
74
|
-
# a condition to filter based on. Fields inside the hash will be ANDed
|
75
|
-
# together. Each hash will be ORed with the others. Fields in hashes with
|
76
|
-
# Arrays as values are treated as an OR statement, since otherwise they
|
77
|
-
# would never match.
|
78
|
-
# @example
|
79
|
-
# j = Systemd::Journal.filter(
|
80
|
-
# {_systemd_unit: 'session-4.scope'},
|
81
|
-
# {priority: [4, 6]},
|
82
|
-
# {_exe: '/usr/bin/sshd', priority: 1}
|
83
|
-
# )
|
84
|
-
# # equivalent to
|
85
|
-
# (_systemd_unit == 'session-4.scope') ||
|
86
|
-
# (priority == 4 || priority == 6) ||
|
87
|
-
# (_exe == '/usr/bin/sshd' && priority == 1)
|
88
|
-
def filter(*conditions)
|
89
|
-
clear_filters
|
90
|
-
|
91
|
-
last_index = conditions.length - 1
|
92
|
-
|
93
|
-
conditions.each_with_index do |condition, index|
|
94
|
-
add_filters(condition)
|
95
|
-
add_disjunction unless index == last_index
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Move the read pointer to the next entry in the journal.
|
100
|
-
# @return [Boolean] True if moving to the next entry was successful.
|
101
|
-
# @return [Boolean] False if unable to move to the next entry, indicating
|
102
|
-
# that the pointer has reached the end of the journal.
|
103
|
-
def move_next
|
104
|
-
rc = Native.sd_journal_next(@ptr)
|
105
|
-
raise JournalError.new(rc) if rc < 0
|
106
|
-
rc > 0
|
107
|
-
end
|
108
|
-
|
109
|
-
# Move the read pointer forward by `amount` entries.
|
110
|
-
# @return [Integer] the actual number of entries by which the read pointer
|
111
|
-
# moved. If this number is less than the requested amount, the read
|
112
|
-
# pointer has reached the end of the journal.
|
113
|
-
def move_next_skip(amount)
|
114
|
-
rc = Native.sd_journal_next_skip(@ptr, amount)
|
115
|
-
raise JournalError.new(rc) if rc < 0
|
116
|
-
rc
|
117
|
-
end
|
118
|
-
|
119
|
-
# Move the read pointer to the previous entry in the journal.
|
120
|
-
# @return [Boolean] True if moving to the previous entry was successful.
|
121
|
-
# @return [Boolean] False if unable to move to the previous entry,
|
122
|
-
# indicating that the pointer has reached the beginning of the journal.
|
123
|
-
def move_previous
|
124
|
-
rc = Native.sd_journal_previous(@ptr)
|
125
|
-
raise JournalError.new(rc) if rc < 0
|
126
|
-
rc > 0
|
127
|
-
end
|
128
|
-
|
129
|
-
# Move the read pointer backwards by `amount` entries.
|
130
|
-
# @return [Integer] the actual number of entries by which the read pointer
|
131
|
-
# was moved. If this number is less than the requested amount, the read
|
132
|
-
# pointer has reached the beginning of the journal.
|
133
|
-
def move_previous_skip(amount)
|
134
|
-
rc = Native.sd_journal_previous_skip(@ptr, amount)
|
135
|
-
raise JournalError.new(rc) if rc < 0
|
136
|
-
rc
|
137
|
-
end
|
138
|
-
|
139
|
-
# Seek to a position in the journal.
|
140
|
-
# Note: after seeking, you must call {#move_next} or {#move_previous}
|
141
|
-
# before you can call {#read_field} or {#current_entry}.
|
142
|
-
#
|
143
|
-
# @param [Symbol, Time] whence one of :head, :tail, or a Time instance.
|
144
|
-
# `:head` (or `:start`) will seek to the beginning of the journal.
|
145
|
-
# `:tail` (or `:end`) will seek to the end of the journal. When a `Time`
|
146
|
-
# is provided, seek to the journal entry logged closest to that time. When
|
147
|
-
# a String is provided, assume it is a cursor from {#cursor} and seek to
|
148
|
-
# that entry.
|
149
|
-
# @return [True]
|
150
|
-
def seek(whence)
|
151
|
-
rc = case whence
|
152
|
-
when :head, :start
|
153
|
-
Native.sd_journal_seek_head(@ptr)
|
154
|
-
when :tail, :end
|
155
|
-
Native.sd_journal_seek_tail(@ptr)
|
156
|
-
else
|
157
|
-
if whence.is_a?(Time)
|
158
|
-
# TODO: is this right? who knows.
|
159
|
-
Native.sd_journal_seek_realtime_usec(@ptr, whence.to_i * 1_000_000)
|
160
|
-
elsif whence.is_a?(String)
|
161
|
-
Native.sd_journal_seek_cursor(@ptr, whence)
|
162
|
-
else
|
163
|
-
raise ArgumentError.new("Unknown seek type: #{whence.class}")
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
raise JournalErrornew(rc) if rc < 0
|
168
|
-
|
169
|
-
true
|
170
|
-
end
|
171
|
-
|
172
69
|
# Read the contents of the provided field from the current journal entry.
|
173
70
|
# {#move_next} or {#move_previous} must be called at least once after
|
174
71
|
# initialization or seeking prior to attempting to read data.
|
@@ -215,6 +112,27 @@ module Systemd
|
|
215
112
|
JournalEntry.new(results)
|
216
113
|
end
|
217
114
|
|
115
|
+
def current_catalog
|
116
|
+
out_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
117
|
+
|
118
|
+
rc = Native.sd_journal_get_catalog(@ptr, out_ptr)
|
119
|
+
raise JournalError.new(rc) if rc < 0
|
120
|
+
|
121
|
+
Journal.read_and_free_outstr(out_ptr.read_pointer)
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.catalog_for(message_id)
|
125
|
+
out_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
126
|
+
|
127
|
+
rc = Native.sd_journal_get_catalog_for_message_id(
|
128
|
+
Systemd::Id128::Native::Id128.from_s(message_id),
|
129
|
+
out_ptr
|
130
|
+
)
|
131
|
+
raise JournalError.new(rc) if rc < 0
|
132
|
+
|
133
|
+
read_and_free_outstr(out_ptr.read_pointer)
|
134
|
+
end
|
135
|
+
|
218
136
|
# Get the list of unique values stored in the journal for the given field.
|
219
137
|
# If passed a block, each possible value will be yielded.
|
220
138
|
# @return [Array] the list of possible values.
|
@@ -241,112 +159,6 @@ module Systemd
|
|
241
159
|
results
|
242
160
|
end
|
243
161
|
|
244
|
-
# Block until the journal is changed.
|
245
|
-
# @param timeout_usec [Integer] the maximum number of microseconds to wait
|
246
|
-
# or `-1` to wait indefinitely.
|
247
|
-
# @example Wait for an event for a maximum of 3 seconds
|
248
|
-
# j = Systemd::Journal.new
|
249
|
-
# j.seek(:tail)
|
250
|
-
# if j.wait(3 * 1_000_000)
|
251
|
-
# # event occurred
|
252
|
-
# end
|
253
|
-
# @return [Nil] if the wait time was reached (no events occured).
|
254
|
-
# @return [Symbol] :append if new entries were appened to the journal.
|
255
|
-
# @return [Symbol] :invalidate if journal files were added/removed/rotated.
|
256
|
-
def wait(timeout_usec = -1)
|
257
|
-
rc = Native.sd_journal_wait(@ptr, timeout_usec)
|
258
|
-
raise JournalError.new(rc) if rc.is_a?(Fixnum) && rc < 0
|
259
|
-
rc == :nop ? nil : rc
|
260
|
-
end
|
261
|
-
|
262
|
-
# Blocks and waits for new entries to be appended to the journal. When new
|
263
|
-
# entries are written, yields them in turn. Note that this function does
|
264
|
-
# not automatically seek to the end of the journal prior to waiting.
|
265
|
-
# This method Does not return.
|
266
|
-
# @example Print out events as they happen
|
267
|
-
# j = Systemd::Journal.new
|
268
|
-
# j.seek(:tail)
|
269
|
-
# j.watch do |event|
|
270
|
-
# puts event.message
|
271
|
-
# end
|
272
|
-
def watch
|
273
|
-
loop do
|
274
|
-
if wait
|
275
|
-
yield current_entry while move_next
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
# Add a filter to journal, such that only entries where the given filter
|
281
|
-
# matches are returned.
|
282
|
-
# {#move_next} or {#move_previous} must be invoked after adding a filter
|
283
|
-
# before attempting to read from the journal.
|
284
|
-
# @param [String] field the column to filter on, e.g. _PID, _EXE.
|
285
|
-
# @param [String] value the match to search for, e.g. '/usr/bin/sshd'
|
286
|
-
# @return [nil]
|
287
|
-
def add_filter(field, value)
|
288
|
-
match = "#{field.to_s.upcase}=#{value}"
|
289
|
-
rc = Native.sd_journal_add_match(@ptr, match, match.length)
|
290
|
-
raise JournalError.new(rc) if rc < 0
|
291
|
-
end
|
292
|
-
|
293
|
-
# Add a set of filters to the journal, such that only entries where the
|
294
|
-
# given filters match are returned.
|
295
|
-
# @param [Hash] filters a set of field/filter value pairs.
|
296
|
-
# If the filter value is an array, each value in the array is added
|
297
|
-
# and entries where the specified field matches any of the values is
|
298
|
-
# returned.
|
299
|
-
# @example Filter by PID and EXE
|
300
|
-
# j.add_filters(_pid: 6700, _exe: '/usr/bin/sshd')
|
301
|
-
def add_filters(filters)
|
302
|
-
filters.each do |field, value|
|
303
|
-
Array(value).each{ |v| add_filter(field, v) }
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
# Add an OR condition to the filter. All previously added matches
|
308
|
-
# will be ORed with the terms following the disjunction.
|
309
|
-
# {#move_next} or {#move_previous} must be invoked after adding a match
|
310
|
-
# before attempting to read from the journal.
|
311
|
-
# @return [nil]
|
312
|
-
# @example Filter entries returned using an OR condition
|
313
|
-
# j = Systemd::Journal.new
|
314
|
-
# j.add_filter('PRIORITY', 5)
|
315
|
-
# j.add_disjunction
|
316
|
-
# j.add_filter('_EXE', '/usr/bin/sshd')
|
317
|
-
# while j.move_next
|
318
|
-
# # current_entry is either an sshd event or
|
319
|
-
# # has priority 5
|
320
|
-
# end
|
321
|
-
def add_disjunction
|
322
|
-
rc = Native.sd_journal_add_disjunction(@ptr)
|
323
|
-
raise JournalError.new(rc) if rc < 0
|
324
|
-
end
|
325
|
-
|
326
|
-
# Add an AND condition to the filter. All previously added terms will be
|
327
|
-
# ANDed together with terms following the conjunction.
|
328
|
-
# {#move_next} or {#move_previous} must be invoked after adding a match
|
329
|
-
# before attempting to read from the journal.
|
330
|
-
# @return [nil]
|
331
|
-
# @example Filter entries returned using an AND condition
|
332
|
-
# j = Systemd::Journal.new
|
333
|
-
# j.add_filter('PRIORITY', 5)
|
334
|
-
# j.add_conjunction
|
335
|
-
# j.add_filter('_EXE', '/usr/bin/sshd')
|
336
|
-
# while j.move_next
|
337
|
-
# # current_entry is an sshd event with priority 5
|
338
|
-
# end
|
339
|
-
def add_conjunction
|
340
|
-
rc = Native.sd_journal_add_conjunction(@ptr)
|
341
|
-
raise JournalError.new(rc) if rc < 0
|
342
|
-
end
|
343
|
-
|
344
|
-
# Remove all filters and conjunctions/disjunctions.
|
345
|
-
# @return [nil]
|
346
|
-
def clear_filters
|
347
|
-
Native.sd_journal_flush_matches(@ptr)
|
348
|
-
end
|
349
|
-
|
350
162
|
# Get the number of bytes the Journal is currently using on disk.
|
351
163
|
# If {Systemd::Journal::Flags::LOCAL_ONLY} was passed when opening the
|
352
164
|
# journal, this value will only reflect the size of journal files of the
|
@@ -380,35 +192,10 @@ module Systemd
|
|
380
192
|
end
|
381
193
|
end
|
382
194
|
|
383
|
-
# returns a string representing the current read position.
|
384
|
-
# This string can be passed to {#seek} or {#cursor?}.
|
385
|
-
# @return [String] a cursor token.
|
386
|
-
def cursor
|
387
|
-
out_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
388
|
-
if (rc = Native.sd_journal_get_cursor(@ptr, out_ptr)) < 0
|
389
|
-
raise JournalError.new(rc)
|
390
|
-
end
|
391
|
-
|
392
|
-
read_and_free_outstr(out_ptr.read_pointer)
|
393
|
-
end
|
394
|
-
|
395
|
-
# Check if the read position is currently at the entry represented by the
|
396
|
-
# provided cursor value.
|
397
|
-
# @param c [String] a cursor token returned from {#cursor}.
|
398
|
-
# @return [Boolean] True if the current entry is the one represented by the
|
399
|
-
# provided cursor, False otherwise.
|
400
|
-
def cursor?(c)
|
401
|
-
if (rc = Native.sd_journal_test_cursor(@ptr, c)) < 0
|
402
|
-
raise JournalError.new(rc)
|
403
|
-
end
|
404
|
-
|
405
|
-
rc > 0
|
406
|
-
end
|
407
|
-
|
408
195
|
private
|
409
196
|
|
410
197
|
def self.finalize(ptr)
|
411
|
-
proc{ Native.sd_journal_close(ptr) unless ptr.nil? }
|
198
|
+
proc { Native.sd_journal_close(ptr) unless ptr.nil? }
|
412
199
|
end
|
413
200
|
|
414
201
|
def enumerate_helper(enum_function)
|
@@ -430,7 +217,7 @@ module Systemd
|
|
430
217
|
# some sd_journal_* functions return strings that we're expected to free
|
431
218
|
# ourselves. This function copies the string from a char* to a ruby string,
|
432
219
|
# frees the char*, and returns the ruby string.
|
433
|
-
def read_and_free_outstr(ptr)
|
220
|
+
def self.read_and_free_outstr(ptr)
|
434
221
|
str = ptr.read_string
|
435
222
|
LibC.free(ptr)
|
436
223
|
str
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Systemd
|
2
|
+
class Journal
|
3
|
+
module Filterable
|
4
|
+
# Filter the journal at a high level.
|
5
|
+
# Takes any number of arguments; each argument should be a hash
|
6
|
+
# representing a condition to filter based on. Fields inside the hash
|
7
|
+
# will be ANDed together. Each hash will be ORed with the others.
|
8
|
+
# Fields in hashes with Arrays as values are treated as an OR statement,
|
9
|
+
# since otherwise they would never match.
|
10
|
+
# @example
|
11
|
+
# j = Systemd::Journal.filter(
|
12
|
+
# {_systemd_unit: 'session-4.scope'},
|
13
|
+
# {priority: [4, 6]},
|
14
|
+
# {_exe: '/usr/bin/sshd', priority: 1}
|
15
|
+
# )
|
16
|
+
# # equivalent to
|
17
|
+
# (_systemd_unit == 'session-4.scope') ||
|
18
|
+
# (priority == 4 || priority == 6) ||
|
19
|
+
# (_exe == '/usr/bin/sshd' && priority == 1)
|
20
|
+
def filter(*conditions)
|
21
|
+
clear_filters
|
22
|
+
|
23
|
+
last_index = conditions.length - 1
|
24
|
+
|
25
|
+
conditions.each_with_index do |condition, index|
|
26
|
+
add_filters(condition)
|
27
|
+
add_disjunction unless index == last_index
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add a filter to journal, such that only entries where the given filter
|
32
|
+
# matches are returned.
|
33
|
+
# {#move_next} or {#move_previous} must be invoked after adding a filter
|
34
|
+
# before attempting to read from the journal.
|
35
|
+
# @param [String] field the column to filter on, e.g. _PID, _EXE.
|
36
|
+
# @param [String] value the match to search for, e.g. '/usr/bin/sshd'
|
37
|
+
# @return [nil]
|
38
|
+
def add_filter(field, value)
|
39
|
+
match = "#{field.to_s.upcase}=#{value}"
|
40
|
+
rc = Native.sd_journal_add_match(@ptr, match, match.length)
|
41
|
+
raise JournalError.new(rc) if rc < 0
|
42
|
+
end
|
43
|
+
|
44
|
+
# Add a set of filters to the journal, such that only entries where the
|
45
|
+
# given filters match are returned.
|
46
|
+
# @param [Hash] filters a set of field/filter value pairs.
|
47
|
+
# If the filter value is an array, each value in the array is added
|
48
|
+
# and entries where the specified field matches any of the values is
|
49
|
+
# returned.
|
50
|
+
# @example Filter by PID and EXE
|
51
|
+
# j.add_filters(_pid: 6700, _exe: '/usr/bin/sshd')
|
52
|
+
def add_filters(filters)
|
53
|
+
filters.each do |field, value|
|
54
|
+
Array(value).each { |v| add_filter(field, v) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Add an OR condition to the filter. All previously added matches
|
59
|
+
# will be ORed with the terms following the disjunction.
|
60
|
+
# {#move_next} or {#move_previous} must be invoked after adding a match
|
61
|
+
# before attempting to read from the journal.
|
62
|
+
# @return [nil]
|
63
|
+
# @example Filter entries returned using an OR condition
|
64
|
+
# j = Systemd::Journal.new
|
65
|
+
# j.add_filter('PRIORITY', 5)
|
66
|
+
# j.add_disjunction
|
67
|
+
# j.add_filter('_EXE', '/usr/bin/sshd')
|
68
|
+
# while j.move_next
|
69
|
+
# # current_entry is either an sshd event or
|
70
|
+
# # has priority 5
|
71
|
+
# end
|
72
|
+
def add_disjunction
|
73
|
+
rc = Native.sd_journal_add_disjunction(@ptr)
|
74
|
+
raise JournalError.new(rc) if rc < 0
|
75
|
+
end
|
76
|
+
|
77
|
+
# Add an AND condition to the filter. All previously added terms will be
|
78
|
+
# ANDed together with terms following the conjunction.
|
79
|
+
# {#move_next} or {#move_previous} must be invoked after adding a match
|
80
|
+
# before attempting to read from the journal.
|
81
|
+
# @return [nil]
|
82
|
+
# @example Filter entries returned using an AND condition
|
83
|
+
# j = Systemd::Journal.new
|
84
|
+
# j.add_filter('PRIORITY', 5)
|
85
|
+
# j.add_conjunction
|
86
|
+
# j.add_filter('_EXE', '/usr/bin/sshd')
|
87
|
+
# while j.move_next
|
88
|
+
# # current_entry is an sshd event with priority 5
|
89
|
+
# end
|
90
|
+
def add_conjunction
|
91
|
+
rc = Native.sd_journal_add_conjunction(@ptr)
|
92
|
+
raise JournalError.new(rc) if rc < 0
|
93
|
+
end
|
94
|
+
|
95
|
+
# Remove all filters and conjunctions/disjunctions.
|
96
|
+
# @return [nil]
|
97
|
+
def clear_filters
|
98
|
+
Native.sd_journal_flush_matches(@ptr)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|