pretty_logs 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cdc491297eaf5042da0ed4b0ff4034442a07c4b6652f8512d53bd4efd71bc9f0
4
+ data.tar.gz: e877065fdd4cb65d9588a49ec5fe500ae5183c8cd3960d4150809f85783baa33
5
+ SHA512:
6
+ metadata.gz: 07ff6f04a9396dddb22c983e0894cc56bebb6a92e5f322454c0a90e22676b3bc22bacd2b699da094a754fc1885afcd32a41e9d2213427af42831e64aec65e8d4
7
+ data.tar.gz: 55b7ef4541a3ca8d0e0b41a4eb204b622731fc74610e4f62b3a759f91abee7a8e44157d2b4707f1c442b69de2ae731141f596685d1b8483e74d81439e6f7f216
data/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to `pretty_logs` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-06-30
11
+
12
+ ### Added
13
+ - Initial release of `pretty_logs`
14
+ - JSON log parsing via `PrettyLogs::Parsers::JsonParser`
15
+ - Plain-text log parsing via `PrettyLogs::Parsers::PlainTextParser` (supports ISO 8601 timestamps with timezone offsets and milliseconds)
16
+ - Colorized output with per-level colors: DEBUG (cyan), INFO (green), WARN (yellow), ERROR (red), FATAL (magenta)
17
+ - Structured multi-line output mode (default) โ€” timestamp/level header + indented fields
18
+ - Simple single-line output mode (`--simple`)
19
+ - Auto-detection of log format (`--format auto`, `json`, or `plain`)
20
+ - `--no-color` flag to disable colorized output
21
+ - CLI tool `log-pretty` for piping log streams
22
+ - Ruby library API (`PrettyLogs::Formatter`, parsers)
23
+ - Full RSpec test suite (14 examples)
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Brijesh S A
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,264 @@
1
+ <div align="center">
2
+
3
+ # ๐ŸŒˆ log-pretty
4
+
5
+ **Transform raw logs into beautiful, human-readable output โ€” instantly.**
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/log_pretty.svg)](https://badge.fury.io/rb/log_pretty)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.txt)
9
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%202.7.0-red.svg)](https://www.ruby-lang.org)
10
+ [![Tests](https://img.shields.io/badge/tests-14%20passing-brightgreen.svg)](spec/)
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ ```
17
+ # Before โ€” raw JSON log
18
+ {"timestamp":"2026-04-24T22:38:51Z","level":"error","message":"DB timeout","code":503,"retry":true}
19
+
20
+ # After โ€” log-pretty output
21
+ 2026-04-24T22:38:51Z [ERROR]
22
+ Message: DB timeout
23
+ Code: 503
24
+ Retry: true
25
+ ```
26
+
27
+ ---
28
+
29
+ ## โœจ Features
30
+
31
+ | | Feature | Description |
32
+ |---|---------|-------------|
33
+ | ๐ŸŽจ | **Colorized levels** | `DEBUG`=cyan ยท `INFO`=green ยท `WARN`=yellow ยท `ERROR`=red ยท `FATAL`=magenta |
34
+ | ๐Ÿ“‹ | **Structured output** | Indented, field-by-field display โ€” scan logs at a glance |
35
+ | ๐Ÿ”„ | **Auto-detect format** | Parses JSON and plain-text logs automatically |
36
+ | ๐Ÿ”ง | **CLI pipe tool** | `tail -f app.log \| log-pretty` โ€” works anywhere |
37
+ | ๐Ÿ“š | **Ruby library** | Embed directly in your Ruby app or Rack middleware |
38
+ | โšก | **Minimal footprint** | Only one runtime dependency: [rainbow](https://github.com/nicholaides/rainbow) |
39
+
40
+ ---
41
+
42
+ ## ๐Ÿ“ฆ Installation
43
+
44
+ ### Via RubyGems (recommended)
45
+
46
+ ```bash
47
+ gem install pretty_logs
48
+ ```
49
+
50
+ ### Via Bundler
51
+
52
+ Add to your `Gemfile`:
53
+
54
+ ```ruby
55
+ gem 'pretty_logs'
56
+ ```
57
+
58
+ Then:
59
+
60
+ ```bash
61
+ bundle install
62
+ ```
63
+
64
+ ### From Source
65
+
66
+ ```bash
67
+ git clone https://github.com/brijeshsajeev/log-pretty
68
+ cd log-pretty/log_pretty
69
+ bundle install
70
+ bundle exec rake install
71
+ ```
72
+
73
+ ---
74
+
75
+ ## ๐Ÿš€ CLI Usage
76
+
77
+ `log-pretty` reads from **stdin** and writes prettified output to **stdout**.
78
+
79
+ ```bash
80
+ # Pipe a file
81
+ log-pretty < app.log
82
+
83
+ # Tail live logs
84
+ tail -f production.log | log-pretty
85
+
86
+ # Pipe from a running process
87
+ docker logs -f my-container | log-pretty
88
+ rails server 2>&1 | log-pretty
89
+ ```
90
+
91
+ ### Options
92
+
93
+ | Flag | Description |
94
+ |------|-------------|
95
+ | `-f`, `--format FORMAT` | Force format: `auto` (default), `json`, `plain` |
96
+ | `-s`, `--simple` | Single-line output instead of structured |
97
+ | `-c`, `--[no-]color` | Enable/disable colors (default: enabled) |
98
+ | `-h`, `--help` | Show help |
99
+
100
+ ### Examples
101
+
102
+ **JSON log:**
103
+ ```bash
104
+ echo '{"timestamp":"2026-04-24T22:38:51Z","level":"info","message":"User logged in","user_id":123}' | log-pretty
105
+ # 2026-04-24T22:38:51Z [INFO]
106
+ # Message: User logged in
107
+ # User_id: 123
108
+ ```
109
+
110
+ **Plain-text log:**
111
+ ```bash
112
+ echo '2026-04-24T22:38:51Z [ERROR] Connection timeout' | log-pretty
113
+ # 2026-04-24T22:38:51Z [ERROR]
114
+ # Message: Connection timeout
115
+ ```
116
+
117
+ **Simple single-line output:**
118
+ ```bash
119
+ tail -f app.log | log-pretty --simple
120
+ # 2026-04-24T22:38:51Z [INFO] Application started
121
+ # 2026-04-24T22:38:52Z [WARN] High memory usage
122
+ ```
123
+
124
+ **No colors (for log files / CI):**
125
+ ```bash
126
+ log-pretty --no-color < app.log > cleaned.log
127
+ ```
128
+
129
+ ---
130
+
131
+ ## ๐Ÿ“š Ruby Library Usage
132
+
133
+ ```ruby
134
+ require 'pretty_logs'
135
+
136
+ formatter = PrettyLogs::Formatter.new(structured: true)
137
+
138
+ # Format a hash directly
139
+ entry = {
140
+ timestamp: "2026-04-24T22:38:51Z",
141
+ level: "info",
142
+ message: "Processing request",
143
+ request_id: "abc123",
144
+ duration_ms: 42
145
+ }
146
+ puts formatter.format(entry)
147
+ # 2026-04-24T22:38:51Z [INFO]
148
+ # Message: Processing request
149
+ # Request_id: abc123
150
+ # Duration_ms: 42
151
+
152
+ # Parse and format a JSON log line
153
+ json_line = '{"level":"error","message":"Database error","code":500}'
154
+ parsed = PrettyLogs::Parsers::JsonParser.parse(json_line)
155
+ puts formatter.format(parsed)
156
+
157
+ # Parse and format a plain-text log line
158
+ plain_line = "2026-04-24T22:38:51Z [WARN] High memory usage"
159
+ parsed = PrettyLogs::Parsers::PlainTextParser.parse(plain_line)
160
+ puts formatter.format(parsed)
161
+ ```
162
+
163
+ ---
164
+
165
+ ## ๐Ÿ“‹ Supported Log Formats
166
+
167
+ ### JSON Logs
168
+
169
+ Any valid JSON object. Recognized fields:
170
+
171
+ | Field | Description |
172
+ |-------|-------------|
173
+ | `timestamp` | ISO 8601 timestamp |
174
+ | `level` | Log level (`debug`, `info`, `warn`, `error`, `fatal`) |
175
+ | `message` | Log message |
176
+ | *any other field* | Displayed as additional structured data |
177
+
178
+ ### Plain-Text Logs
179
+
180
+ ```
181
+ YYYY-MM-DDTHH:MM:SS[.mmm][Z|ยฑHH:MM] [LEVEL] Message text
182
+ ```
183
+
184
+ Examples:
185
+ ```
186
+ 2026-04-24T22:38:51Z [INFO] Application started
187
+ 2026-04-24T22:38:51.123Z [ERROR] Connection failed
188
+ 2026-04-24T22:38:51.000+05:30 [DEBUG] Cache miss for key=user:42
189
+ ```
190
+
191
+ ---
192
+
193
+ ## ๐ŸŽจ Log Level Colors
194
+
195
+ | Level | Color | Example use |
196
+ |-------|-------|-------------|
197
+ | `DEBUG` | Cyan | Low-level diagnostics |
198
+ | `INFO` | Green | Normal operations |
199
+ | `WARN` / `WARNING` | Yellow | Something may need attention |
200
+ | `ERROR` | Red | Something failed |
201
+ | `FATAL` | Magenta | Critical failure |
202
+
203
+ ---
204
+
205
+ ## ๐Ÿ”ง CI / Automation Usage
206
+
207
+ Disable colors for clean output in CI pipelines:
208
+
209
+ ```bash
210
+ # GitHub Actions, Jenkins, etc.
211
+ cat build.log | log-pretty --no-color
212
+
213
+ # Or via env (Rainbow respects NO_COLOR)
214
+ NO_COLOR=1 log-pretty < app.log
215
+ ```
216
+
217
+ ---
218
+
219
+ ## ๐Ÿ›  Development
220
+
221
+ ```bash
222
+ git clone https://github.com/brijeshsajeev/log-pretty
223
+ cd log-pretty/log_pretty
224
+ bundle install
225
+
226
+ bundle exec rspec # Run test suite
227
+ bundle exec log-pretty # Test CLI manually
228
+ ```
229
+
230
+ ---
231
+
232
+ ## ๐Ÿงช Testing
233
+
234
+ ```bash
235
+ bundle exec rspec
236
+ ```
237
+
238
+ ```
239
+ 14 examples, 0 failures โœ…
240
+ ```
241
+
242
+ ---
243
+
244
+ ## ๐Ÿ“„ License
245
+
246
+ [MIT License](LICENSE.txt) ยฉ 2026 [Brijesh S A](https://github.com/brijeshsajeev)
247
+
248
+ ---
249
+
250
+ ## ๐Ÿค Contributing
251
+
252
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/brijeshsajeev/log-pretty/issues).
253
+
254
+ 1. Fork the repository
255
+ 2. Create your branch: `git checkout -b feature/my-feature`
256
+ 3. Add tests for your changes
257
+ 4. Run `bundle exec rspec` โ€” all tests must pass
258
+ 5. Submit a Pull Request
259
+
260
+ ---
261
+
262
+ <div align="center">
263
+ Made with โค๏ธ by <a href="https://github.com/brijeshsajeev">Brijesh S A</a>
264
+ </div>
data/bin/log-pretty ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "optparse"
5
+ require_relative "../lib/pretty_logs"
6
+
7
+ options = {
8
+ format: :auto,
9
+ output: :structured,
10
+ color: true
11
+ }
12
+
13
+ OptionParser.new do |opts|
14
+ opts.banner = "Usage: log-pretty [options]"
15
+
16
+ opts.on("-f", "--format FORMAT", "Log format: auto, json, plain (default: auto)") do |f|
17
+ options[:format] = f.to_sym
18
+ end
19
+
20
+ opts.on("-s", "--simple", "Use simple output format") do
21
+ options[:output] = :simple
22
+ end
23
+
24
+ opts.on("-c", "--[no-]color", "Enable/disable colorized output (default: enabled)") do |c|
25
+ options[:color] = c
26
+ end
27
+
28
+ opts.on("-h", "--help", "Show this help message") do
29
+ puts opts
30
+ exit
31
+ end
32
+ end.parse!
33
+
34
+ formatter = PrettyLogs::Formatter.new(structured: options[:output] == :structured)
35
+
36
+ STDIN.each_line do |line|
37
+ line.chomp!
38
+ next if line.empty?
39
+
40
+ # Try to parse JSON first, then plain text
41
+ entry = if options[:format] == :json
42
+ PrettyLogs::Parsers::JsonParser.parse(line)
43
+ elsif options[:format] == :plain
44
+ PrettyLogs::Parsers::PlainTextParser.parse(line)
45
+ else
46
+ PrettyLogs::Parsers::JsonParser.parse(line) ||
47
+ PrettyLogs::Parsers::PlainTextParser.parse(line) ||
48
+ { message: line }
49
+ end
50
+
51
+ next if entry.nil?
52
+
53
+ puts formatter.format(entry)
54
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rainbow"
4
+
5
+ module PrettyLogs
6
+ class Formatter
7
+ LEVEL_COLORS = {
8
+ debug: :cyan,
9
+ info: :green,
10
+ warn: :yellow,
11
+ error: :red,
12
+ fatal: :magenta,
13
+ warning: :yellow,
14
+ unknown: :white
15
+ }.freeze
16
+
17
+ def initialize(structured: true)
18
+ @structured = structured
19
+ end
20
+
21
+ def format(log_entry)
22
+ return format_structured(log_entry) if @structured
23
+
24
+ format_simple(log_entry)
25
+ end
26
+
27
+ private
28
+
29
+ def format_simple(entry)
30
+ timestamp = entry[:timestamp] || ""
31
+ level = entry[:level] || "UNKNOWN"
32
+ message = entry[:message] || ""
33
+
34
+ color = level_color(level)
35
+ formatted_level = Rainbow(level.upcase).color(color).bright
36
+
37
+ "#{timestamp} [#{formatted_level}] #{message}"
38
+ end
39
+
40
+ def format_structured(entry)
41
+ lines = []
42
+
43
+ # Header with timestamp and level
44
+ timestamp = entry[:timestamp] || ""
45
+ level = entry[:level] || "UNKNOWN"
46
+ color = level_color(level)
47
+ formatted_level = Rainbow(level.upcase).color(color).bright
48
+ header = "#{timestamp} [#{formatted_level}]"
49
+ lines << header
50
+
51
+ # Message
52
+ message = entry[:message] || ""
53
+ lines << " Message: #{message}" if message.to_s.length > 0
54
+
55
+ # Additional fields
56
+ entry.each do |key, value|
57
+ next if %i[timestamp level message].include?(key)
58
+ next if value.nil?
59
+
60
+ key_str = Rainbow(key.to_s.capitalize).color(:blue)
61
+ lines << " #{key_str}: #{value}"
62
+ end
63
+
64
+ lines.join("\n")
65
+ end
66
+
67
+ def level_color(level)
68
+ LEVEL_COLORS[level.to_s.downcase.to_sym] || :white
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module PrettyLogs
6
+ module Parsers
7
+ class JsonParser
8
+ def self.parse(line)
9
+ JSON.parse(line, symbolize_names: true)
10
+ rescue JSON::ParserError
11
+ nil
12
+ end
13
+
14
+ def self.parse?(line)
15
+ !parse(line).nil?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrettyLogs
4
+ module Parsers
5
+ class PlainTextParser
6
+ # Matches standard log format: TIMESTAMP [LEVEL] message
7
+ LOG_PATTERN = /^(\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)\s*\[(\w+)\]\s+(.*)$/
8
+
9
+ def self.parse(line)
10
+ match = line.match(LOG_PATTERN)
11
+ return nil unless match
12
+
13
+ {
14
+ timestamp: match[1],
15
+ level: match[2],
16
+ message: match[3]
17
+ }
18
+ end
19
+
20
+ def self.parse?(line)
21
+ !parse(line).nil?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrettyLogs
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "pretty_logs/version"
4
+ require_relative "pretty_logs/formatter"
5
+ require_relative "pretty_logs/parsers/json_parser"
6
+ require_relative "pretty_logs/parsers/plain_text_parser"
7
+
8
+ module PrettyLogs
9
+ class Error < StandardError; end
10
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pretty_logs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brijesh S A
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rainbow
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ description: PrettyLogs transforms raw JSON and plain-text logs into beautiful, human-readable,
56
+ colorized output. Use it as a CLI pipe tool or embed it directly in your Ruby application.
57
+ email:
58
+ - brijesh00300@gmail.com
59
+ executables:
60
+ - log-pretty
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - CHANGELOG.md
65
+ - LICENSE.txt
66
+ - README.md
67
+ - bin/log-pretty
68
+ - lib/pretty_logs.rb
69
+ - lib/pretty_logs/formatter.rb
70
+ - lib/pretty_logs/parsers/json_parser.rb
71
+ - lib/pretty_logs/parsers/plain_text_parser.rb
72
+ - lib/pretty_logs/version.rb
73
+ homepage: https://github.com/BrijeshSajeev/log_pretty
74
+ licenses:
75
+ - MIT
76
+ metadata:
77
+ homepage_uri: https://github.com/BrijeshSajeev/log_pretty
78
+ source_code_uri: https://github.com/BrijeshSajeev/log_pretty
79
+ changelog_uri: https://github.com/BrijeshSajeev/log_pretty/blob/main/log_pretty/CHANGELOG.md
80
+ bug_tracker_uri: https://github.com/BrijeshSajeev/log_pretty/issues
81
+ rubygems_mfa_required: 'true'
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 2.7.0
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubygems_version: 3.3.26
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Prettify logs with colorized output and structured formatting.
101
+ test_files: []