-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrsyslog-solr-search
executable file
·110 lines (93 loc) · 2.83 KB
/
rsyslog-solr-search
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env ruby
require 'net/http'
require 'uri'
require "rexml/document"
require "date"
require "time"
class Time
def to_s
strftime('%Y-%m-%dT%H:%M:%SZ')
end
end
class Doc
attr_reader :attributes
def initialize(element)
@attributes = {}
@element = element
element.elements.each("*") do |e|
if e.attributes["name"] == "timestamp"
@attributes["timestamp"] = Time.parse(e.text) rescue Time.now
else
@attributes[e.attributes["name"]] = e.text
end
end
end
def [](key)
attributes[key.to_s]
end
end
solr_url = ENV["URL"] || "http://localhost:8080/solr/select"
SOLR_URL = URI.parse(solr_url)
query = ENV["QUERY"] || ARGV.join(" ")
limit = (ENV["LIMIT"] || 15).to_i
page = (ENV["PAGE"] || 1).to_i
offset = (page - 1) * limit
sort = ENV["SORT"]
if ENV["AT"]
at = Time.parse(ENV["AT"])
timespan = (ENV["TIMESPAN"] || 120).to_i
from = at - timespan
to = at + timespan
query = "+(timestamp:[#{from} TO #{to}]) AND (#{query})"
sort = "time" unless sort
end
if ENV["BEFORE"]
before = Time.parse(ENV["BEFORE"])
query = "+(timestamp:[* TO #{before}]) AND (#{query})"
end
if ENV["AFTER"]
after = Time.parse(ENV["AFTER"])
query = "+(timestamp:[#{after} TO *]) AND (#{query})"
end
sort = (sort == "time") ? "timestamp desc" : "score desc, timestamp desc"
def search(query, options = {})
req = Net::HTTP::Get.new(SOLR_URL.path)
req.set_form_data(options.merge(:q => query))
req = Net::HTTP::Get.new(SOLR_URL.path + '?' + req.body)
res = Net::HTTP.new(SOLR_URL.host, SOLR_URL.port).start { |http| http.request(req) }
root = REXML::Document.new res.body
result = root.elements["response/result[1]"]
if result.nil?
msg = res.message
msg.gsub!('org.apache.lucene.queryParser.ParseException','')
STDERR.puts "#{res.code} #{msg[0..100]}..."
exit 1
end
docs = result.elements.collect("doc") do |e|
Doc.new(e)
end
{ :docs => docs, :total => result.attributes["numFound"] }
end
if ENV["TAIL"]
STDERR.puts "Tail for search \"#{query}\""
sort = "timestamp asc"
last_doc_ids = []
highest_timestamp = Time.now - 60
while true do
# FIXME: Adding one second here might miss some messages. Compare
# document ids to exclude duplicates instead.
r = search("+(timestamp:[#{highest_timestamp+1} TO NOW]) AND (#{query})", :start => offset, :rows => limit, :sort => sort)
docs = r[:docs]
docs.each do |doc|
highest_timestamp = doc[:timestamp] if doc[:timestamp] > highest_timestamp
puts "#{doc[:timestamp]} #{doc[:hostname]} #{doc[:program]} #{doc[:msg]}"
end
sleep 2
end
else
r = search(query, :start => offset, :rows => limit, :sort => sort)
STDERR.puts "Page #{page} of #{r[:total] } hits for search \"#{query}\""
r[:docs].each do |doc|
puts "#{doc[:generated]} #{doc[:hostname]} #{doc[:program]} #{doc[:msg]}"
end
end