tty-logger 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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