tty-logger 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +69 -8
  4. data/lib/tty/logger.rb +14 -10
  5. data/lib/tty/logger/config.rb +34 -3
  6. data/lib/tty/logger/data_filter.rb +121 -0
  7. data/lib/tty/logger/handlers/console.rb +13 -3
  8. data/lib/tty/logger/version.rb +1 -1
  9. data/tty-logger.gemspec +4 -6
  10. metadata +4 -38
  11. data/Rakefile +0 -8
  12. data/examples/child.rb +0 -9
  13. data/examples/console.rb +0 -22
  14. data/examples/custom_type.rb +0 -27
  15. data/examples/error.rb +0 -11
  16. data/examples/handler.rb +0 -19
  17. data/examples/log.rb +0 -9
  18. data/examples/output.rb +0 -15
  19. data/examples/override.rb +0 -29
  20. data/examples/stream.rb +0 -22
  21. data/spec/perf/json_formatter_spec.rb +0 -29
  22. data/spec/perf/log_spec.rb +0 -21
  23. data/spec/perf/text_formatter_spec.rb +0 -29
  24. data/spec/spec_helper.rb +0 -31
  25. data/spec/unit/add_handler_spec.rb +0 -25
  26. data/spec/unit/config_spec.rb +0 -109
  27. data/spec/unit/copy_spec.rb +0 -27
  28. data/spec/unit/event_spec.rb +0 -22
  29. data/spec/unit/exception_spec.rb +0 -45
  30. data/spec/unit/filter_spec.rb +0 -32
  31. data/spec/unit/formatter_spec.rb +0 -70
  32. data/spec/unit/formatters/json_spec.rb +0 -41
  33. data/spec/unit/formatters/text_spec.rb +0 -82
  34. data/spec/unit/handler_spec.rb +0 -83
  35. data/spec/unit/handlers/custom_spec.rb +0 -26
  36. data/spec/unit/handlers/null_spec.rb +0 -15
  37. data/spec/unit/handlers/stream_spec.rb +0 -72
  38. data/spec/unit/levels_spec.rb +0 -40
  39. data/spec/unit/log_at_spec.rb +0 -34
  40. data/spec/unit/log_metadata_spec.rb +0 -55
  41. data/spec/unit/log_spec.rb +0 -203
  42. data/spec/unit/output_spec.rb +0 -40
  43. data/tasks/console.rake +0 -11
  44. data/tasks/coverage.rake +0 -11
  45. data/tasks/spec.rake +0 -34
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger, "#copy" do
4
- let(:output) { StringIO.new }
5
- let(:styles) { TTY::Logger::Handlers::Console::STYLES }
6
-
7
- it "copies ouptut, fields and configuration over to child logger" do
8
- logger = TTY::Logger.new(output: output, fields: {app: "parent", env: "prod"})
9
- child_logger = logger.copy(app: "child") do |config|
10
- config.filters = ["logging"]
11
- end
12
-
13
- logger.info("Parent logging")
14
- child_logger.warn("Child logging")
15
-
16
- expect(output.string).to eq([
17
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
18
- "\e[32minfo\e[0m ",
19
- "Parent logging ",
20
- "\e[32mapp\e[0m=parent \e[32menv\e[0m=prod\n",
21
- "\e[33m#{styles[:warn][:symbol]}\e[0m ",
22
- "\e[33mwarning\e[0m ",
23
- "Child [FILTERED] ",
24
- "\e[33mapp\e[0m=child \e[33menv\e[0m=prod\n"
25
- ].join)
26
- end
27
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger::Event, "event" do
4
- it "defaults backtrace to an empty array" do
5
- event = described_class.new(["message"], {}, {})
6
- expect(event.backtrace).to eq([])
7
- end
8
-
9
- it "extracts backtrace if message contains exception" do
10
- event = nil
11
- error = nil
12
-
13
- begin
14
- raise ArgumentError, "Wrong data"
15
- rescue => ex
16
- error = ex
17
- event = described_class.new(["Error", ex], {}, {})
18
- end
19
-
20
- expect(event.backtrace.join).to eq(error.backtrace.join)
21
- end
22
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger, "exception logging" do
4
- let(:output) { StringIO.new }
5
- let(:styles) { TTY::Logger::Handlers::Console::STYLES }
6
-
7
- it "handles exception type message when console" do
8
- logger = TTY::Logger.new(output: output)
9
- error = nil
10
-
11
- begin
12
- raise ArgumentError, "Wrong data"
13
- rescue => ex
14
- error = ex
15
- logger.fatal("Error:", error)
16
- end
17
-
18
- expect(output.string).to eq([
19
- "\e[31m#{styles[:fatal][:symbol]}\e[0m ",
20
- "\e[31mfatal\e[0m ",
21
- "Error: Wrong data \n",
22
- "#{error.backtrace.map {|bktrace| bktrace.to_s.insert(0, " " * 4) }.join("\n")}\n"
23
- ].join)
24
- end
25
-
26
- it "handles exception type message when stream" do
27
- logger = TTY::Logger.new(output: output) do |config|
28
- config.handlers = [:stream]
29
- end
30
-
31
- error = nil
32
-
33
- begin
34
- raise ArgumentError, "Wrong data"
35
- rescue => ex
36
- error = ex
37
- logger.fatal("Error:", error)
38
- end
39
-
40
- expect(output.string).to eq([
41
- "level=fatal message=\"Error: Wrong data\" backtrace=\"",
42
- "#{error.backtrace.map {|bktrace| bktrace }.join(",")}\"\n"
43
- ].join)
44
- end
45
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger, "filters" do
4
- let(:output) { StringIO.new }
5
- let(:styles) { TTY::Logger::Handlers::Console::STYLES }
6
-
7
- it "filters a sensitive data from a message" do
8
- logger = TTY::Logger.new(output: output) do |config|
9
- config.filters = ["secret", "password"]
10
- end
11
-
12
- logger.info("Super secret info with password")
13
-
14
- expect(output.string).to eq([
15
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
16
- "\e[32minfo\e[0m ",
17
- "Super [FILTERED] info with [FILTERED]\n"].join)
18
- end
19
-
20
- it "filters a sensitive data from a message with custom placeholder" do
21
- logger = TTY::Logger.new(output: output) do |config|
22
- config.filters = { "secret" => "<SECRET>" }
23
- end
24
-
25
- logger.info("Super secret info")
26
-
27
- expect(output.string).to eq([
28
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
29
- "\e[32minfo\e[0m ",
30
- "Super <SECRET> info \n"].join)
31
- end
32
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger, "formatter" do
4
- let(:output) { StringIO.new }
5
- let(:styles) { TTY::Logger::Handlers::Console::STYLES }
6
-
7
- it "changes default formatter to JSON as class name" do
8
- logger = TTY::Logger.new(output: output) do |config|
9
- config.formatter = TTY::Logger::Formatters::JSON
10
- end
11
-
12
- logger.info("Logging", app: "myapp", env: "prod")
13
-
14
- expect(output.string).to eq([
15
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
16
- "\e[32minfo\e[0m ",
17
- "Logging ",
18
- "{\"\e[32mapp\e[0m\":\"myapp\",\"\e[32menv\e[0m\":\"prod\"}\n"].join)
19
- end
20
-
21
- it "changes default formatter to JSON as name" do
22
- logger = TTY::Logger.new(output: output) do |config|
23
- config.formatter = :json
24
- end
25
-
26
- logger.info("Logging", app: "myapp", env: "prod")
27
-
28
- expect(output.string).to eq([
29
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
30
- "\e[32minfo\e[0m ",
31
- "Logging ",
32
- "{\"\e[32mapp\e[0m\":\"myapp\",\"\e[32menv\e[0m\":\"prod\"}\n"].join)
33
- end
34
-
35
- it "changes default formatter for only one handler" do
36
- logger = TTY::Logger.new(output: output) do |config|
37
- config.handlers = [:console,
38
- [:console, {formatter: :JSON}]]
39
- end
40
-
41
- logger.info("Logging", app: "myapp", env: "prod")
42
-
43
- expect(output.string).to eq([
44
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
45
- "\e[32minfo\e[0m ",
46
- "Logging ",
47
- "\e[32mapp\e[0m=myapp \e[32menv\e[0m=prod\n",
48
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
49
- "\e[32minfo\e[0m ",
50
- "Logging ",
51
- "{\"\e[32mapp\e[0m\":\"myapp\",\"\e[32menv\e[0m\":\"prod\"}\n"].join)
52
- end
53
-
54
- it "fails to recognize formatter object type" do
55
- expect {
56
- TTY::Logger.new(output: output) do |config|
57
- config.formatter = true
58
- end
59
- }.to raise_error(TTY::Logger::Error, "Unrecognized formatter name 'true'")
60
- end
61
-
62
- it "fails to recognize formatter name" do
63
-
64
- expect {
65
- TTY::Logger.new(output: output) do |config|
66
- config.formatter = :unknown
67
- end
68
- }.to raise_error(TTY::Logger::Error, "Unrecognized formatter name ':unknown'")
69
- end
70
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger::Formatters::JSON, "#dump" do
4
- it "dumps a log line" do
5
- formatter = described_class.new
6
- data = {
7
- app: "myapp",
8
- env: "prod",
9
- sql: "SELECT * FROM admins",
10
- at: Time.at(123456).utc
11
- }
12
-
13
- expect(formatter.dump(data)).to eq("{\"app\":\"myapp\",\"env\":\"prod\",\"sql\":\"SELECT * FROM admins\",\"at\":\"1970-01-02 10:17:36 UTC\"}")
14
- end
15
-
16
- [
17
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 3*12+2, want: "{\"a\":\"aaaaa\",\"b\":\"bbbbb\",\"c\":\"ccccc\"}"},
18
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 2*12+4, want: "{\"a\":\"aaaaa\",\"b\":\"bbbbb\",\"c\":\"...\"}"},
19
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 12+4, want: "{\"a\":\"aaaaa\",\"b\":\"...\"}"},
20
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 11, want: "{\"a\":\"...\"}"},
21
- ].each do |data|
22
- it "truncates #{data[:obj].inspect} to #{data[:want].inspect} of #{data[:bytes]} bytes" do
23
- formatter = described_class.new
24
- expect(formatter.dump(data[:obj], max_bytes: data[:bytes])).to eq(data[:want])
25
- end
26
- end
27
-
28
- [
29
- {obj: {a: {b: {c: "ccccc"}}}, depth: 1, want: "{\"a\":\"...\"}"},
30
- {obj: {a: {b: {c: "ccccc"}}}, depth: 2, want: "{\"a\":{\"b\":\"...\"}}"},
31
- {obj: {a: {b: {c: "ccccc"}}}, depth: 3, want: "{\"a\":{\"b\":{\"c\":\"ccccc\"}}}"},
32
- {obj: {a: ["b", {c: "ccccc"}]}, depth: 1, want: "{\"a\":\"...\"}"},
33
- {obj: {a: ["b", {c: "ccccc"}]}, depth: 2, want: "{\"a\":[\"b\",\"...\"]}"},
34
- {obj: {a: ["b", {c: "ccccc"}]}, depth: 3, want: "{\"a\":[\"b\",{\"c\":\"ccccc\"}]}"},
35
- ].each do |data|
36
- it "truncates nested object #{data[:obj].inspect} to #{data[:want].inspect}" do
37
- formatter = described_class.new
38
- expect(formatter.dump(data[:obj], max_depth: data[:depth])).to eq(data[:want])
39
- end
40
- end
41
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger::Formatters::Text, "#dump" do
4
-
5
- [
6
- {key: "k", value: "v", want: "k=v"},
7
- {key: "k", value: '\n', want: "k=\\n"},
8
- {key: "k", value: '\r', want: "k=\\r"},
9
- {key: "k", value: '\t', want: "k=\\t"},
10
- {key: "k", value: nil, want: "k=nil"},
11
- {key: "k", value: "nil", want: "k=\"nil\""},
12
- {key: "k", value: "", want: "k="},
13
- {key: "k", value: true, want: "k=true"},
14
- {key: "k", value: "true", want: "k=\"true\""},
15
- {key: "k", value: "false", want: "k=\"false\""},
16
- {key: "k", value: 1, want: "k=1"},
17
- {key: "k", value: 1.035, want: "k=1.035"},
18
- {key: "k", value: 1e-5, want: "k=0.00001"},
19
- {key: "k", value: Complex(2,1), want: "k=(2+1i)"},
20
- {key: "k", value: "1", want: "k=\"1\""},
21
- {key: "k", value: "1.035", want: "k=\"1.035\""},
22
- {key: "k", value: "1e-5", want: "k=\"1e-5\""},
23
- {key: "k", value: "v v", want: "k=\"v v\""},
24
- {key: "k", value: " ", want: 'k=" "'},
25
- {key: "k", value: '"', want: 'k="\""'},
26
- {key: "k", value: '=', want: 'k="="'},
27
- {key: "k", value: "\\", want: "k=\\"},
28
- {key: "k", value: "=\\", want: "k=\"=\\\\\""},
29
- {key: "k", value: "\\\"", want: "k=\"\\\\\\\"\""},
30
- {key: "", value: "", want: "="},
31
- {key: '"', value: "v", want: '"\""=v'},
32
- {key: "k", value: Time.new(2019, 7, 7, 12, 21, 35, "+02:00"), want: "k=2019-07-07T12:21:35+02:00"},
33
- {key: "k", value: {a: 1}, want: "k={a=1}"},
34
- {key: "k", value: {a: 1, b: 2}, want: "k={a=1 b=2}"},
35
- {key: "k", value: {a: {b: 2}}, want: "k={a={b=2}}"},
36
- {key: "k", value: ["a", 1], want: "k=[a 1]"},
37
- {key: "k", value: ["a", ["b", 2], 1], want: "k=[a [b 2] 1]"},
38
- ].each do |data|
39
- it "dumps {#{data[:key].inspect} => #{data[:value].inspect}} as #{data[:want].inspect}" do
40
- formatter = described_class.new
41
- expect(formatter.dump({data[:key] => data[:value]})).to eq(data[:want])
42
- end
43
- end
44
-
45
- [
46
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 24, want: "a=aaaaa b=bbbbb c=ccccc"},
47
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 20, want: "a=aaaaa b=bbbbb ..."},
48
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 15, want: "a=aaaaa ..."},
49
- {obj: {a: "aaaaa", b: "bbbbb", c: "ccccc"}, bytes: 7, want: "..."},
50
- ].each do |data|
51
- it "truncates #{data[:obj].inspect} to #{data[:want].inspect} of #{data[:bytes]} bytes" do
52
- formatter = described_class.new
53
- expect(formatter.dump(data[:obj], max_bytes: data[:bytes])).to eq(data[:want])
54
- end
55
- end
56
-
57
- [
58
- {obj: {a: {b: {c: "ccccc"}}}, depth: 1, want: "a={...}"},
59
- {obj: {a: {b: {c: "ccccc"}}}, depth: 2, want: "a={b={...}}"},
60
- {obj: {a: {b: {c: "ccccc"}}}, depth: 3, want: "a={b={c=ccccc}}"},
61
- {obj: {a: ["b", {c: "ccccc"}]}, depth: 1, want: "a=[...]"},
62
- {obj: {a: ["b", {c: "ccccc"}]}, depth: 2, want: "a=[b {...}]"},
63
- {obj: {a: ["b", {c: "ccccc"}]}, depth: 3, want: "a=[b {c=ccccc}]"},
64
- ].each do |data|
65
- it "truncates nested object #{data[:obj].inspect} to #{data[:want].inspect}" do
66
- formatter = described_class.new
67
- expect(formatter.dump(data[:obj], max_depth: data[:depth])).to eq(data[:want])
68
- end
69
- end
70
-
71
- it "dumps a log line" do
72
- formatter = described_class.new
73
- data = {
74
- app: "myapp",
75
- env: "prod",
76
- sql: "SELECT * FROM admins",
77
- at: Time.at(123456).utc
78
- }
79
-
80
- expect(formatter.dump(data)).to eq("app=myapp env=prod sql=\"SELECT * FROM admins\" at=1970-01-02T10:17:36+00:00")
81
- end
82
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger, 'handlers' do
4
- let(:output) { StringIO.new }
5
- let(:styles) { TTY::Logger::Handlers::Console::STYLES }
6
-
7
- it "coerces name into handler object" do
8
- logger = TTY::Logger.new(output: output) do |config|
9
- config.handlers = [:console]
10
- end
11
-
12
- logger.info("Logging")
13
-
14
- expect(output.string).to eq([
15
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
16
- "\e[32minfo\e[0m ",
17
- "Logging \n"].join)
18
- end
19
-
20
- it "coerces class name into handler object" do
21
- logger = TTY::Logger.new(output: output) do |config|
22
- config.handlers = [TTY::Logger::Handlers::Console]
23
- end
24
-
25
- logger.info("Logging")
26
-
27
- expect(output.string).to eq([
28
- "\e[32m#{styles[:info][:symbol]}\e[0m ",
29
- "\e[32minfo\e[0m ",
30
- "Logging \n"].join)
31
- end
32
-
33
- it "changes default handler styling" do
34
- logger = TTY::Logger.new(output: output) do |config|
35
- config.handlers = [
36
- [:console, {styles: {info: {symbol: "+", label: "INFO"}}}]
37
- ]
38
- end
39
-
40
- logger.info("Logging")
41
-
42
- expect(output.string).to eq([
43
- "\e[32m+\e[0m ",
44
- "\e[32mINFO\e[0m ",
45
- "Logging \n"].join)
46
- end
47
-
48
- it "logs different levels for each handler" do
49
- logger = TTY::Logger.new(output: output) do |config|
50
- config.handlers = [
51
- [:console, level: :error],
52
- [:console, level: :debug]
53
- ]
54
- end
55
-
56
- logger.info("Info")
57
- logger.error("Error")
58
-
59
- expect(output.string).to eq([
60
- "\e[32m#{styles[:info][:symbol]}\e[0m \e[32minfo\e[0m Info \n",
61
- "\e[31m#{styles[:error][:symbol]}\e[0m \e[31merror\e[0m Error \n",
62
- "\e[31m#{styles[:error][:symbol]}\e[0m \e[31merror\e[0m Error \n",
63
- ].join)
64
- end
65
-
66
- it "fails to coerce unknown object type into handler object" do
67
- expect {
68
- TTY::Logger.new do |config|
69
- config.handlers = [true]
70
- end
71
- }.to raise_error(TTY::Logger::Error,
72
- "Handler needs to be a class name or a symbol name")
73
- end
74
-
75
- it "fails to coerce name into handler object" do
76
- expect {
77
- TTY::Logger.new do |config|
78
- config.handlers = [:unknown]
79
- end
80
- }.to raise_error(TTY::Logger::Error,
81
- "Handler needs to be a class name or a symbol name")
82
- end
83
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger::Handlers::Null, "custom handler" do
4
- let(:output) { StringIO.new }
5
-
6
- it "logs messages with a custom handler" do
7
- stub_const("MyHandler", Class.new do
8
- def initialize(output: nil, config: nil, label: nil)
9
- @label = label
10
- @output = output
11
- end
12
-
13
- def call(event)
14
- @output.puts "(#{@label}) #{event.message.join}"
15
- end
16
- end)
17
-
18
- logger = TTY::Logger.new(output: output) do |config|
19
- config.handlers = [[MyHandler, {label: "myhandler"}]]
20
- end
21
-
22
- logger.info("Logging")
23
-
24
- expect(output.string).to eq("(myhandler) Logging\n")
25
- end
26
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Logger::Handlers::Null, "null handler" do
4
- let(:output) { StringIO.new }
5
-
6
- it "doesn't log with a null handler" do
7
- logger = TTY::Logger.new(output: output) do |config|
8
- config.handlers = [:null]
9
- end
10
-
11
- logger.info("Logging")
12
-
13
- expect(output.string).to eq("")
14
- end
15
- end