hq-log-monitor-server 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/features/event-page.feature +67 -0
- data/features/{overview.feature → overview-page.feature} +2 -2
- data/features/support/env.rb +28 -0
- data/features/support/steps.rb +51 -27
- data/features/support/ui-steps.rb +50 -0
- data/lib/hq/log-monitor-server/do-checks.rb +116 -0
- data/lib/hq/log-monitor-server/event-page.rb +174 -0
- data/lib/hq/log-monitor-server/logic.rb +89 -0
- data/lib/hq/log-monitor-server/overview-page.rb +100 -0
- data/lib/hq/log-monitor-server/script.rb +12 -628
- data/lib/hq/log-monitor-server/service-host-page.rb +109 -0
- data/lib/hq/log-monitor-server/service-page.rb +112 -0
- data/lib/hq/log-monitor-server/submit-log-event.rb +58 -0
- metadata +70 -33
- checksums.yaml +0 -7
@@ -0,0 +1,89 @@
|
|
1
|
+
module HQ
|
2
|
+
module LogMonitorServer
|
3
|
+
|
4
|
+
class Script
|
5
|
+
|
6
|
+
def get_event event_id
|
7
|
+
|
8
|
+
return @db["events"].find({
|
9
|
+
"_id" => BSON::ObjectId.from_string(event_id),
|
10
|
+
}).first
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def mark_event_as_seen event_id
|
15
|
+
|
16
|
+
event = get_event event_id
|
17
|
+
|
18
|
+
return if event["status"] == "seen"
|
19
|
+
|
20
|
+
event["status"] = "seen"
|
21
|
+
|
22
|
+
@db["events"].save event
|
23
|
+
|
24
|
+
# update summary
|
25
|
+
|
26
|
+
@db["summaries"].update(
|
27
|
+
{ "_id" => event["source"] },
|
28
|
+
{ "$inc" => {
|
29
|
+
"combined.new" => -1,
|
30
|
+
"types.#{event["type"]}.new" => -1,
|
31
|
+
} }
|
32
|
+
)
|
33
|
+
|
34
|
+
# notify icinga checks
|
35
|
+
|
36
|
+
do_checks
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_summaries_by_service
|
41
|
+
|
42
|
+
summaries_by_service = {}
|
43
|
+
|
44
|
+
@db["summaries"].find.each do
|
45
|
+
|summary|
|
46
|
+
|
47
|
+
service =
|
48
|
+
summary["_id"]["service"]
|
49
|
+
|
50
|
+
summary_by_service =
|
51
|
+
summaries_by_service[service] ||= {
|
52
|
+
"service" => service,
|
53
|
+
"combined" => { "new" => 0, "total" => 0 },
|
54
|
+
"types" => {},
|
55
|
+
}
|
56
|
+
|
57
|
+
summary_by_service["combined"]["new"] +=
|
58
|
+
summary["combined"]["new"]
|
59
|
+
|
60
|
+
summary_by_service["combined"]["total"] +=
|
61
|
+
summary["combined"]["total"]
|
62
|
+
|
63
|
+
summary["types"].each do
|
64
|
+
|type, type_summary|
|
65
|
+
|
66
|
+
type_summary_by_service =
|
67
|
+
summary_by_service["types"][type] ||= {
|
68
|
+
"new" => 0,
|
69
|
+
"total" => 0,
|
70
|
+
}
|
71
|
+
|
72
|
+
type_summary_by_service["new"] +=
|
73
|
+
type_summary["new"]
|
74
|
+
|
75
|
+
type_summary_by_service["total"] +=
|
76
|
+
type_summary["total"]
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
return summaries_by_service
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module HQ
|
2
|
+
module LogMonitorServer
|
3
|
+
|
4
|
+
class Script
|
5
|
+
|
6
|
+
def overview_page env
|
7
|
+
|
8
|
+
summaries_by_service =
|
9
|
+
get_summaries_by_service
|
10
|
+
|
11
|
+
headers = {}
|
12
|
+
html = []
|
13
|
+
|
14
|
+
headers["content-type"] = "text/html; charset=utf-8"
|
15
|
+
|
16
|
+
html << "<! DOCTYPE html>\n"
|
17
|
+
html << "<html>\n"
|
18
|
+
html << "<head>\n"
|
19
|
+
|
20
|
+
title =
|
21
|
+
"Overview \u2014 Log monitor"
|
22
|
+
|
23
|
+
html << "<title>%s</title>\n" % [
|
24
|
+
esc_ht(title),
|
25
|
+
]
|
26
|
+
|
27
|
+
html << "</head>\n"
|
28
|
+
html << "<body>\n"
|
29
|
+
|
30
|
+
html << "<h1>%s</h1>\n" % [
|
31
|
+
esc_ht(title),
|
32
|
+
]
|
33
|
+
|
34
|
+
if summaries_by_service.empty?
|
35
|
+
html << "<p>No events have been logged</p>\n"
|
36
|
+
else
|
37
|
+
|
38
|
+
html << "<table id=\"summaries\">\n"
|
39
|
+
html << "<thead>\n"
|
40
|
+
|
41
|
+
html << "<tr>\n"
|
42
|
+
html << "<th>Service</th>\n"
|
43
|
+
html << "<th>Alerts</th>\n"
|
44
|
+
html << "<th>Details</th>\n"
|
45
|
+
html << "<th>View</th>\n"
|
46
|
+
html << "</tr>\n"
|
47
|
+
|
48
|
+
html << "</thead>\n"
|
49
|
+
html << "<tbody>\n"
|
50
|
+
|
51
|
+
summaries_by_service.each do
|
52
|
+
|service, summary|
|
53
|
+
|
54
|
+
html << "<tr class=\"summary\">\n"
|
55
|
+
|
56
|
+
html << "<td class=\"service\">%s</td>\n" % [
|
57
|
+
esc_ht(summary["service"]),
|
58
|
+
]
|
59
|
+
|
60
|
+
html << "<td class=\"alerts\">%s</td>\n" % [
|
61
|
+
esc_ht(summary["combined"]["new"].to_s),
|
62
|
+
]
|
63
|
+
|
64
|
+
html << "<td class=\"detail\">%s</td>\n" % [
|
65
|
+
esc_ht(
|
66
|
+
summary["types"].map {
|
67
|
+
|type, counts|
|
68
|
+
"%s %s" % [ counts["new"], type ]
|
69
|
+
}.join ", "
|
70
|
+
),
|
71
|
+
]
|
72
|
+
|
73
|
+
html << "<td class=\"view\">%s</td>\n" % [
|
74
|
+
"<a href=\"%s\">view</a>" % [
|
75
|
+
"/service/%s" % [
|
76
|
+
esc_ue(summary["service"]),
|
77
|
+
],
|
78
|
+
],
|
79
|
+
]
|
80
|
+
|
81
|
+
html << "</tr>\n"
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
html << "</tbody>\n"
|
86
|
+
html << "</table>\n"
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
html << "</body>\n"
|
91
|
+
html << "</html>\n"
|
92
|
+
|
93
|
+
return 200, headers, html
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -9,6 +9,7 @@ require "hq/tools/getopt"
|
|
9
9
|
|
10
10
|
module HQ
|
11
11
|
module LogMonitorServer
|
12
|
+
|
12
13
|
class Script
|
13
14
|
|
14
15
|
include Tools::Escape
|
@@ -67,113 +68,6 @@ class Script
|
|
67
68
|
|
68
69
|
end
|
69
70
|
|
70
|
-
def do_checks
|
71
|
-
@mutex.synchronize do
|
72
|
-
|
73
|
-
File.open @icinga_elem["command-file"], "a" do
|
74
|
-
|command_io|
|
75
|
-
|
76
|
-
summaries_by_service =
|
77
|
-
get_summaries_by_service
|
78
|
-
|
79
|
-
@icinga_elem.find("service").each do
|
80
|
-
|service_elem|
|
81
|
-
|
82
|
-
service_name = service_elem["name"]
|
83
|
-
|
84
|
-
critical_count = 0
|
85
|
-
warning_count = 0
|
86
|
-
unknown_count = 0
|
87
|
-
|
88
|
-
summaries =
|
89
|
-
summaries_by_service[service_name]
|
90
|
-
|
91
|
-
if summaries
|
92
|
-
summaries["types"].each do
|
93
|
-
|type_name, type_info|
|
94
|
-
|
95
|
-
type_elem =
|
96
|
-
service_elem.find_first("
|
97
|
-
type [@name = #{esc_xp type_name}]
|
98
|
-
")
|
99
|
-
|
100
|
-
if ! type_elem
|
101
|
-
unknown_count += 1
|
102
|
-
elsif type_elem["level"] == "critical"
|
103
|
-
critical_count += 1
|
104
|
-
elsif type_elem["level"] == "warning"
|
105
|
-
warning_count += 1
|
106
|
-
else
|
107
|
-
unknown_count += 1
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
status_int =
|
113
|
-
if critical_count > 0
|
114
|
-
2
|
115
|
-
elsif warning_count > 0
|
116
|
-
1
|
117
|
-
elsif unknown_count > 0
|
118
|
-
3
|
119
|
-
else
|
120
|
-
0
|
121
|
-
end
|
122
|
-
|
123
|
-
status_str =
|
124
|
-
if critical_count > 0
|
125
|
-
"CRITICAL"
|
126
|
-
elsif warning_count > 0
|
127
|
-
"WARNING"
|
128
|
-
elsif unknown_count > 0
|
129
|
-
"UNKNOWN"
|
130
|
-
else
|
131
|
-
"OK"
|
132
|
-
end
|
133
|
-
|
134
|
-
parts = []
|
135
|
-
|
136
|
-
if critical_count > 0
|
137
|
-
parts << "%d critical" % critical_count
|
138
|
-
end
|
139
|
-
|
140
|
-
if warning_count > 0
|
141
|
-
parts << "%d warning" % warning_count
|
142
|
-
end
|
143
|
-
|
144
|
-
if unknown_count > 0
|
145
|
-
parts << "%d unknown" % unknown_count
|
146
|
-
end
|
147
|
-
|
148
|
-
if parts.empty?
|
149
|
-
parts << "no new events"
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
command_io.print "[%s] %s\n" % [
|
154
|
-
Time.now.to_i,
|
155
|
-
[
|
156
|
-
"PROCESS_SERVICE_CHECK_RESULT",
|
157
|
-
service_elem["icinga-host"],
|
158
|
-
service_elem["icinga-service"],
|
159
|
-
status_int,
|
160
|
-
"%s %s" % [
|
161
|
-
status_str,
|
162
|
-
parts.join(", "),
|
163
|
-
]
|
164
|
-
].join(";"),
|
165
|
-
]
|
166
|
-
|
167
|
-
end
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
@next_check = Time.now + 60
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
end
|
176
|
-
|
177
71
|
def process_args
|
178
72
|
|
179
73
|
@opts, @args =
|
@@ -274,527 +168,6 @@ class Script
|
|
274
168
|
|
275
169
|
end
|
276
170
|
|
277
|
-
def submit_log_event env
|
278
|
-
|
279
|
-
# decode it
|
280
|
-
|
281
|
-
event = MultiJson.load env["rack.input"].read
|
282
|
-
|
283
|
-
# add a timestamp
|
284
|
-
|
285
|
-
event["timestamp"] = Time.now
|
286
|
-
|
287
|
-
# insert it
|
288
|
-
|
289
|
-
@db["events"].insert event
|
290
|
-
|
291
|
-
# update summary
|
292
|
-
|
293
|
-
summary =
|
294
|
-
@db["summaries"].find({
|
295
|
-
"_id" => event["source"],
|
296
|
-
}).first
|
297
|
-
|
298
|
-
summary ||= {
|
299
|
-
"_id" => event["source"],
|
300
|
-
"combined" => { "new" => 0, "total" => 0 },
|
301
|
-
"types" => {},
|
302
|
-
}
|
303
|
-
|
304
|
-
summary["types"][event["type"]] ||=
|
305
|
-
{ "new" => 0, "total" => 0 }
|
306
|
-
|
307
|
-
summary["types"][event["type"]]["new"] += 1
|
308
|
-
summary["types"][event["type"]]["total"] += 1
|
309
|
-
|
310
|
-
summary["combined"]["new"] += 1
|
311
|
-
summary["combined"]["total"] += 1
|
312
|
-
|
313
|
-
@db["summaries"].save summary
|
314
|
-
|
315
|
-
# perform checks
|
316
|
-
|
317
|
-
do_checks
|
318
|
-
|
319
|
-
# respond successfully
|
320
|
-
|
321
|
-
return 202, {}, []
|
322
|
-
|
323
|
-
end
|
324
|
-
|
325
|
-
def get_summaries_by_service
|
326
|
-
|
327
|
-
summaries_by_service = {}
|
328
|
-
|
329
|
-
@db["summaries"].find.each do
|
330
|
-
|summary|
|
331
|
-
|
332
|
-
service =
|
333
|
-
summary["_id"]["service"]
|
334
|
-
|
335
|
-
summary_by_service =
|
336
|
-
summaries_by_service[service] ||= {
|
337
|
-
"service" => service,
|
338
|
-
"combined" => { "new" => 0, "total" => 0 },
|
339
|
-
"types" => {},
|
340
|
-
}
|
341
|
-
|
342
|
-
summary_by_service["combined"]["new"] +=
|
343
|
-
summary["combined"]["new"]
|
344
|
-
|
345
|
-
summary_by_service["combined"]["total"] +=
|
346
|
-
summary["combined"]["total"]
|
347
|
-
|
348
|
-
summary["types"].each do
|
349
|
-
|type, type_summary|
|
350
|
-
|
351
|
-
type_summary_by_service =
|
352
|
-
summary_by_service["types"][type] ||= {
|
353
|
-
"new" => 0,
|
354
|
-
"total" => 0,
|
355
|
-
}
|
356
|
-
|
357
|
-
type_summary_by_service["new"] +=
|
358
|
-
type_summary["new"]
|
359
|
-
|
360
|
-
type_summary_by_service["total"] +=
|
361
|
-
type_summary["total"]
|
362
|
-
|
363
|
-
end
|
364
|
-
|
365
|
-
end
|
366
|
-
|
367
|
-
return summaries_by_service
|
368
|
-
|
369
|
-
end
|
370
|
-
|
371
|
-
def overview_page env
|
372
|
-
|
373
|
-
summaries_by_service =
|
374
|
-
get_summaries_by_service
|
375
|
-
|
376
|
-
headers = {}
|
377
|
-
html = []
|
378
|
-
|
379
|
-
headers["content-type"] = "text/html; charset=utf-8"
|
380
|
-
|
381
|
-
html << "<! DOCTYPE html>\n"
|
382
|
-
html << "<html>\n"
|
383
|
-
html << "<head>\n"
|
384
|
-
|
385
|
-
title =
|
386
|
-
"Overview \u2014 Log monitor"
|
387
|
-
|
388
|
-
html << "<title>%s</title>\n" % [
|
389
|
-
esc_ht(title),
|
390
|
-
]
|
391
|
-
|
392
|
-
html << "</head>\n"
|
393
|
-
html << "<body>\n"
|
394
|
-
|
395
|
-
html << "<h1>%s</h1>\n" % [
|
396
|
-
esc_ht(title),
|
397
|
-
]
|
398
|
-
|
399
|
-
if summaries_by_service.empty?
|
400
|
-
html << "<p>No events have been logged</p>\n"
|
401
|
-
else
|
402
|
-
|
403
|
-
html << "<table id=\"summaries\">\n"
|
404
|
-
html << "<thead>\n"
|
405
|
-
|
406
|
-
html << "<tr>\n"
|
407
|
-
html << "<th>Service</th>\n"
|
408
|
-
html << "<th>Alerts</th>\n"
|
409
|
-
html << "<th>Details</th>\n"
|
410
|
-
html << "<th>View</th>\n"
|
411
|
-
html << "</tr>\n"
|
412
|
-
|
413
|
-
html << "</thead>\n"
|
414
|
-
html << "<tbody>\n"
|
415
|
-
|
416
|
-
summaries_by_service.each do
|
417
|
-
|service, summary|
|
418
|
-
|
419
|
-
html << "<tr class=\"summary\">\n"
|
420
|
-
|
421
|
-
html << "<td class=\"service\">%s</td>\n" % [
|
422
|
-
esc_ht(summary["service"]),
|
423
|
-
]
|
424
|
-
|
425
|
-
html << "<td class=\"alerts\">%s</td>\n" % [
|
426
|
-
esc_ht(summary["combined"]["new"].to_s),
|
427
|
-
]
|
428
|
-
|
429
|
-
html << "<td class=\"detail\">%s</td>\n" % [
|
430
|
-
esc_ht(
|
431
|
-
summary["types"].map {
|
432
|
-
|type, counts|
|
433
|
-
"%s %s" % [ counts["new"], type ]
|
434
|
-
}.join ", "
|
435
|
-
),
|
436
|
-
]
|
437
|
-
|
438
|
-
html << "<td class=\"view\">%s</td>\n" % [
|
439
|
-
"<a href=\"%s\">view</a>" % [
|
440
|
-
"/service/%s" % [
|
441
|
-
esc_ue(summary["service"]),
|
442
|
-
],
|
443
|
-
],
|
444
|
-
]
|
445
|
-
|
446
|
-
html << "</tr>\n"
|
447
|
-
|
448
|
-
end
|
449
|
-
|
450
|
-
html << "</tbody>\n"
|
451
|
-
html << "</table>\n"
|
452
|
-
|
453
|
-
end
|
454
|
-
|
455
|
-
html << "</body>\n"
|
456
|
-
html << "</html>\n"
|
457
|
-
|
458
|
-
return 200, headers, html
|
459
|
-
|
460
|
-
end
|
461
|
-
|
462
|
-
def service_page env, context
|
463
|
-
|
464
|
-
summaries =
|
465
|
-
@db["summaries"]
|
466
|
-
.find({
|
467
|
-
"_id.service" => context[:service]
|
468
|
-
})
|
469
|
-
.to_a
|
470
|
-
|
471
|
-
title =
|
472
|
-
"%s - Log monitor" % [
|
473
|
-
context[:service],
|
474
|
-
]
|
475
|
-
|
476
|
-
headers = {}
|
477
|
-
html = []
|
478
|
-
|
479
|
-
headers["content-type"] = "text/html; charset=utf-8"
|
480
|
-
|
481
|
-
html << "<!DOCTYPE html>\n"
|
482
|
-
html << "<html>\n"
|
483
|
-
html << "<head>\n"
|
484
|
-
|
485
|
-
html << "<title>%s</title>\n" % [
|
486
|
-
esc_ht(title),
|
487
|
-
]
|
488
|
-
|
489
|
-
html << "</head>\n"
|
490
|
-
html << "<body>\n"
|
491
|
-
|
492
|
-
html << "<h1>%s</h1>\n" % [
|
493
|
-
esc_ht(title),
|
494
|
-
]
|
495
|
-
|
496
|
-
if summaries.empty?
|
497
|
-
html << "<p>No events have been logged for this service</p>\n"
|
498
|
-
else
|
499
|
-
|
500
|
-
html << "<table id=\"summaries\">\n"
|
501
|
-
html << "<thead>\n"
|
502
|
-
|
503
|
-
html << "<tr>\n"
|
504
|
-
html << "<th>Host</th>\n"
|
505
|
-
html << "<th>Class</th>\n"
|
506
|
-
html << "<th>Alerts</th>\n"
|
507
|
-
html << "<th>Details</th>\n"
|
508
|
-
html << "<th>View</th>\n"
|
509
|
-
html << "</tr>\n"
|
510
|
-
|
511
|
-
html << "</thead>\n"
|
512
|
-
html << "<tbody>\n"
|
513
|
-
|
514
|
-
summaries.each do
|
515
|
-
|summary|
|
516
|
-
|
517
|
-
html << "<tr class=\"summary\">\n"
|
518
|
-
|
519
|
-
html << "<td class=\"host\">%s</td>\n" % [
|
520
|
-
esc_ht(summary["_id"]["host"]),
|
521
|
-
]
|
522
|
-
|
523
|
-
html << "<td class=\"service\">%s</td>\n" % [
|
524
|
-
esc_ht(summary["_id"]["class"]),
|
525
|
-
]
|
526
|
-
|
527
|
-
html << "<td class=\"alerts\">%s</td>\n" % [
|
528
|
-
esc_ht(summary["combined"]["new"].to_s),
|
529
|
-
]
|
530
|
-
|
531
|
-
html << "<td class=\"detail\">%s</td>\n" % [
|
532
|
-
esc_ht(
|
533
|
-
summary["types"].map {
|
534
|
-
|type, counts|
|
535
|
-
"%s %s" % [ counts["new"], type ]
|
536
|
-
}.join ", "
|
537
|
-
),
|
538
|
-
]
|
539
|
-
|
540
|
-
html << "<td class=\"view\">%s</td>\n" % [
|
541
|
-
"<a href=\"%s\">view</a>" % [
|
542
|
-
"/service/%s/host/%s" % [
|
543
|
-
esc_ue(summary["_id"]["service"]),
|
544
|
-
esc_ue(summary["_id"]["host"]),
|
545
|
-
],
|
546
|
-
],
|
547
|
-
]
|
548
|
-
|
549
|
-
html << "</tr>\n"
|
550
|
-
|
551
|
-
end
|
552
|
-
|
553
|
-
html << "</tbody>\n"
|
554
|
-
html << "</table>\n"
|
555
|
-
|
556
|
-
end
|
557
|
-
|
558
|
-
html << "</body>\n"
|
559
|
-
html << "</html>\n"
|
560
|
-
|
561
|
-
return 200, headers, html
|
562
|
-
|
563
|
-
end
|
564
|
-
|
565
|
-
def service_host_page env, context
|
566
|
-
|
567
|
-
events =
|
568
|
-
@db["events"]
|
569
|
-
.find({
|
570
|
-
"source.service" => context[:service],
|
571
|
-
"source.host" => context[:host],
|
572
|
-
})
|
573
|
-
.to_a
|
574
|
-
|
575
|
-
title =
|
576
|
-
"%s %s \u2014 Log monitor" % [
|
577
|
-
context[:host],
|
578
|
-
context[:service],
|
579
|
-
]
|
580
|
-
|
581
|
-
headers = {}
|
582
|
-
html = []
|
583
|
-
|
584
|
-
headers["content-type"] = "text/html; charset=utf-8"
|
585
|
-
|
586
|
-
html << "<!DOCTYPE html>\n"
|
587
|
-
html << "<html>\n"
|
588
|
-
html << "<head>\n"
|
589
|
-
|
590
|
-
html << "<title>%s</title>\n" % [
|
591
|
-
esc_ht(title),
|
592
|
-
]
|
593
|
-
|
594
|
-
html << "</head>\n"
|
595
|
-
html << "<body>\n"
|
596
|
-
|
597
|
-
html << "<h1>%s</h1>\n" % [
|
598
|
-
esc_ht(title),
|
599
|
-
]
|
600
|
-
|
601
|
-
if events.empty?
|
602
|
-
html << "<p>No events have been logged for this service on this " +
|
603
|
-
"host</p>\n"
|
604
|
-
else
|
605
|
-
|
606
|
-
html << "<table id=\"events\">\n"
|
607
|
-
html << "<thead>\n"
|
608
|
-
|
609
|
-
html << "<tr>\n"
|
610
|
-
html << "<th>Timestamp</th>\n"
|
611
|
-
html << "<th>File</th>\n"
|
612
|
-
html << "<th>Line</th>\n"
|
613
|
-
html << "<th>Type</th>\n"
|
614
|
-
html << "<th>View</th>\n"
|
615
|
-
html << "</tr>\n"
|
616
|
-
|
617
|
-
html << "</thead>\n"
|
618
|
-
html << "<tbody>\n"
|
619
|
-
|
620
|
-
events.each do
|
621
|
-
|event|
|
622
|
-
|
623
|
-
html << "<tr class=\"event\">\n"
|
624
|
-
|
625
|
-
html << "<td class=\"timestamp\">%s</td>\n" % [
|
626
|
-
esc_ht(event["timestamp"].to_s),
|
627
|
-
]
|
628
|
-
|
629
|
-
html << "<td class=\"file\">%s</td>\n" % [
|
630
|
-
esc_ht(event["location"]["file"]),
|
631
|
-
]
|
632
|
-
|
633
|
-
html << "<td class=\"line\">%s</td>\n" % [
|
634
|
-
esc_ht(event["location"]["line"].to_s),
|
635
|
-
]
|
636
|
-
|
637
|
-
html << "<td class=\"type\">%s</td>\n" % [
|
638
|
-
esc_ht(event["type"]),
|
639
|
-
]
|
640
|
-
|
641
|
-
html << "<td class=\"view\">%s</td>\n" % [
|
642
|
-
"<a href=\"%s\">view</a>" % [
|
643
|
-
"/event/%s" % [
|
644
|
-
esc_ue(event["_id"].to_s),
|
645
|
-
],
|
646
|
-
],
|
647
|
-
]
|
648
|
-
|
649
|
-
html << "</tr>\n"
|
650
|
-
|
651
|
-
end
|
652
|
-
|
653
|
-
html << "</tbody>\n"
|
654
|
-
html << "</table>\n"
|
655
|
-
|
656
|
-
end
|
657
|
-
|
658
|
-
html << "</body>\n"
|
659
|
-
html << "</html>\n"
|
660
|
-
|
661
|
-
return 200, headers, html
|
662
|
-
|
663
|
-
end
|
664
|
-
|
665
|
-
def event_page env, context
|
666
|
-
|
667
|
-
event =
|
668
|
-
@db["events"]
|
669
|
-
.find_one({
|
670
|
-
"_id" => BSON::ObjectId.from_string(context[:event_id]),
|
671
|
-
})
|
672
|
-
|
673
|
-
title =
|
674
|
-
"Event %s \u2014 Log monitor" % [
|
675
|
-
context[:event_id],
|
676
|
-
]
|
677
|
-
|
678
|
-
headers = {}
|
679
|
-
html = []
|
680
|
-
|
681
|
-
headers["content-type"] = "text/html; charset=utf-8"
|
682
|
-
|
683
|
-
html << "<!DOCTYPE html>\n"
|
684
|
-
html << "<html>\n"
|
685
|
-
html << "<head>\n"
|
686
|
-
|
687
|
-
html << "<title>%s</title>\n" % [
|
688
|
-
esc_ht(title),
|
689
|
-
]
|
690
|
-
|
691
|
-
html << "</head>\n"
|
692
|
-
html << "<body>\n"
|
693
|
-
|
694
|
-
html << "<h1>%s</h1>\n" % [
|
695
|
-
esc_ht(title),
|
696
|
-
]
|
697
|
-
|
698
|
-
unless event
|
699
|
-
|
700
|
-
html << "<p>Event id not recognised</p>\n"
|
701
|
-
|
702
|
-
else
|
703
|
-
|
704
|
-
html << "<table id=\"event\">\n"
|
705
|
-
html << "<tbody>\n"
|
706
|
-
|
707
|
-
html << "<tr>\n"
|
708
|
-
html << "<th>ID</th>\n"
|
709
|
-
html << "<td>%s</td>\n" % [
|
710
|
-
esc_ht(event["_id"].to_s),
|
711
|
-
]
|
712
|
-
html << "</tr>\n"
|
713
|
-
|
714
|
-
html << "<tr>\n"
|
715
|
-
html << "<th>Timestamp</th>\n"
|
716
|
-
html << "<td>%s</td>\n" % [
|
717
|
-
esc_ht(event["timestamp"].to_s),
|
718
|
-
]
|
719
|
-
html << "</tr>\n"
|
720
|
-
|
721
|
-
html << "<tr>\n"
|
722
|
-
html << "<th>Service</th>\n"
|
723
|
-
html << "<td>%s</td>\n" % [
|
724
|
-
esc_ht(event["source"]["service"]),
|
725
|
-
]
|
726
|
-
html << "</tr>\n"
|
727
|
-
|
728
|
-
html << "<tr>\n"
|
729
|
-
html << "<th>Host</th>\n"
|
730
|
-
html << "<td>%s</td>\n" % [
|
731
|
-
esc_ht(event["source"]["host"]),
|
732
|
-
]
|
733
|
-
html << "</tr>\n"
|
734
|
-
|
735
|
-
html << "<tr>\n"
|
736
|
-
html << "<th>Class</th>\n"
|
737
|
-
html << "<td>%s</td>\n" % [
|
738
|
-
esc_ht(event["source"]["class"]),
|
739
|
-
]
|
740
|
-
html << "</tr>\n"
|
741
|
-
|
742
|
-
html << "<tr>\n"
|
743
|
-
html << "<th>Filename</th>\n"
|
744
|
-
html << "<td>%s</td>\n" % [
|
745
|
-
esc_ht(event["location"]["file"]),
|
746
|
-
]
|
747
|
-
html << "</tr>\n"
|
748
|
-
|
749
|
-
html << "<tr>\n"
|
750
|
-
html << "<th>Line number</th>\n"
|
751
|
-
html << "<td>%s</td>\n" % [
|
752
|
-
esc_ht((event["location"]["line"] + 1).to_s),
|
753
|
-
]
|
754
|
-
html << "</tr>\n"
|
755
|
-
|
756
|
-
unless event["lines"]["before"].empty?
|
757
|
-
|
758
|
-
html << "<tr>\n"
|
759
|
-
html << "<th>Before</th>\n"
|
760
|
-
html << "<td>%s</td>\n" % [
|
761
|
-
event["lines"]["before"]
|
762
|
-
.map { |line| esc_ht(line) }
|
763
|
-
.join("<br>")
|
764
|
-
]
|
765
|
-
|
766
|
-
end
|
767
|
-
|
768
|
-
html << "<tr>\n"
|
769
|
-
html << "<th>Matching</th>\n"
|
770
|
-
html << "<td>%s</td>\n" % [
|
771
|
-
esc_ht(event["lines"]["matching"]),
|
772
|
-
]
|
773
|
-
|
774
|
-
unless event["lines"]["after"].empty?
|
775
|
-
|
776
|
-
html << "<tr>\n"
|
777
|
-
html << "<th>Before</th>\n"
|
778
|
-
html << "<td>%s</td>\n" % [
|
779
|
-
event["lines"]["after"]
|
780
|
-
.map { |line| esc_ht(line) }
|
781
|
-
.join("<br>")
|
782
|
-
]
|
783
|
-
|
784
|
-
end
|
785
|
-
|
786
|
-
html << "</tbody>\n"
|
787
|
-
html << "</table>\n"
|
788
|
-
|
789
|
-
end
|
790
|
-
|
791
|
-
html << "</body>\n"
|
792
|
-
html << "</html>\n"
|
793
|
-
|
794
|
-
return 200, headers, html
|
795
|
-
|
796
|
-
end
|
797
|
-
|
798
171
|
def sf format, *args
|
799
172
|
|
800
173
|
ret = []
|
@@ -825,5 +198,16 @@ class Script
|
|
825
198
|
end
|
826
199
|
|
827
200
|
end
|
201
|
+
|
828
202
|
end
|
829
203
|
end
|
204
|
+
|
205
|
+
# extra bits
|
206
|
+
|
207
|
+
require "hq/log-monitor-server/do-checks"
|
208
|
+
require "hq/log-monitor-server/event-page"
|
209
|
+
require "hq/log-monitor-server/logic"
|
210
|
+
require "hq/log-monitor-server/overview-page"
|
211
|
+
require "hq/log-monitor-server/service-host-page"
|
212
|
+
require "hq/log-monitor-server/service-page"
|
213
|
+
require "hq/log-monitor-server/submit-log-event"
|