/
json_prettifier.rb
131 lines (104 loc) · 2.61 KB
/
json_prettifier.rb
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
require "digest/md5"
require "set"
require "yajl"
module Steno
end
class Steno::JsonPrettifier
FIELD_ORDER = %w[
timestamp
source
process_id
thread_id
fiber_id
location
data
log_level
message
]
MIN_COL_WIDTH = 14
class ParseError < StandardError
end
def initialize(excluded_fields = [])
@time_format = "%Y-%m-%d %H:%M:%S.%6N"
@excluded_fields = Set.new(excluded_fields)
@max_src_len = MIN_COL_WIDTH
end
def prettify_line(line)
begin
json_record = Yajl::Parser.parse(line)
rescue Yajl::ParseError => e
raise ParseError, e.to_s
end
format_record(json_record)
end
protected
def format_record(record)
record ||= {}
fields = []
FIELD_ORDER.each do |field_name|
next if @excluded_fields.include?(field_name)
exists = nil
pred_meth = "check_#{field_name}".to_sym
if respond_to?(pred_meth)
exists = send(pred_meth, record)
elsif record.respond_to?(:has_key?)
exists = record.has_key?(field_name)
else
msg = "Expected the record to be a hash, but received: #{record.class}."
raise ParseError, msg
end
if exists
fields << send("format_#{field_name}".to_sym, record)
else
fields << "-"
end
end
fields.join(" ") + "\n"
end
def format_timestamp(record)
Time.at(record["timestamp"]).strftime(@time_format)
end
def format_source(record)
@max_src_len = [@max_src_len, record["source"].length].max
record["source"].ljust(@max_src_len)
end
def format_process_id(record)
"pid=%-5s" % [record["process_id"]]
end
def format_thread_id(record)
"tid=%s" % [shortid(record["thread_id"])]
end
def format_fiber_id(record)
"fid=%s" % [shortid(record["fiber_id"])]
end
def check_location(record)
%w[file lineno method].reduce(true) { |ok, k| ok && record.has_key?(k) }
end
def format_location(record)
parts = record["file"].split("/")
trimmed_filename = nil
if parts.size == 1
trimmed_filename = parts[0]
else
trimmed_filename = parts.slice(-2, 2).join("/")
end
"%s/%s:%s" % [trimmed_filename, record["method"], record["lineno"]]
end
def check_data(record)
record["data"].is_a?(Hash)
end
def format_data(record)
record["data"].map { |k, v| "#{k}=#{v}" }.join(",")
end
def format_log_level(record)
"%7s" % [record["log_level"].upcase]
end
def format_message(record)
"-- %s" % [record["message"]]
end
def shortid(data)
return "-" if data.nil?
digest = Digest::MD5.hexdigest(data.to_s)
digest[0, 4]
end
end