sinlog 0.0.1
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 +7 -0
- data/License +21 -0
- data/docs/Readme-zh.md +310 -0
- data/docs/Readme.md +313 -0
- data/lib/init.rb +90 -0
- data/lib/lambda.rb +184 -0
- data/lib/sinlog/version.rb +5 -0
- data/lib/sinlog.rb +18 -0
- metadata +45 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d3fe4df43741e8ad7d0401e9a0c60ec0d7c429f4712ad67b2a930b2f3c40c270
|
|
4
|
+
data.tar.gz: 4a79394fb547e8dc2e16f5418e80ebd170b93930fcd63c4490241e844a9cdc40
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: bb676571612ede8908f76b040756ee8b4de13be37abe2651f7a12e4e7a1b357bc5b3020be2f0631a4e91ddaf1c5b055ff35f6b3f48fcc3ebd4ae4e317cda92a2
|
|
7
|
+
data.tar.gz: e08d902583da75273357bed1c1615cafd80d128fa9cb5db6c094129ec8a40cff4ea11c2981df403e6b2cf18b260eaf520245fb7e9680874ed71f2356b613008c
|
data/License
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 2moe
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
data/docs/Readme-zh.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# Sinlog
|
|
2
|
+
|
|
3
|
+
一个非常非常简单的 ruby 单例日志记录器,其中日志级别带有彩色高亮。
|
|
4
|
+
|
|
5
|
+
> 单例(Singleton)意味着整个程序会共享同一个实例(日志记录器)。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
| Language/語言 | ID |
|
|
10
|
+
| ------------------------------- | ---------- |
|
|
11
|
+
| 简体中文 | zh-Hans-CN |
|
|
12
|
+
| [English](./Readme.md) | en-Latn-US |
|
|
13
|
+
| [繁體中文](./Readme-zh-Hant.md) | zh-Hant-TW |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<details>
|
|
18
|
+
<summary>
|
|
19
|
+
目录(点击展开)
|
|
20
|
+
</summary>
|
|
21
|
+
|
|
22
|
+
- [Learn Sinlog API By Example](#learn-sinlog-api-by-example)
|
|
23
|
+
- [include module](#include-module)
|
|
24
|
+
- [LambdaExt](#lambdaext)
|
|
25
|
+
- [LogLambdaExt](#loglambdaext)
|
|
26
|
+
- [Classic Method Call](#classic-method-call)
|
|
27
|
+
- [进阶](#进阶)
|
|
28
|
+
- [Real World Example](#real-world-example)
|
|
29
|
+
- [日志级别](#日志级别)
|
|
30
|
+
- [环境变量](#环境变量)
|
|
31
|
+
- [日志输出设备/路径](#日志输出设备路径)
|
|
32
|
+
- [其他 logger 方法](#其他-logger-方法)
|
|
33
|
+
- [注意事项](#注意事项)
|
|
34
|
+
- [题外话](#题外话)
|
|
35
|
+
- [License](#license)
|
|
36
|
+
|
|
37
|
+
</details>
|
|
38
|
+
|
|
39
|
+
## Learn Sinlog API By Example
|
|
40
|
+
|
|
41
|
+
首先,安装 sinlog。
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
gem install sinlog
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
然后,我们可以运行 `irb` 来快速体验一番。
|
|
48
|
+
|
|
49
|
+
### include module
|
|
50
|
+
|
|
51
|
+
#### LambdaExt
|
|
52
|
+
|
|
53
|
+
当出现: `irb(main):001>` 后,我们就能开始操作了。
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
irb(main):001> require 'sinlog'
|
|
57
|
+
|
|
58
|
+
irb(main):002> include Sinlog::LambdaExt
|
|
59
|
+
# 它提供了: dbg, info, warning, err, fatal, unk
|
|
60
|
+
# 我们可以用 .tap(&dbg) 或 .then(&dbg) 来调用。
|
|
61
|
+
|
|
62
|
+
irb(main):003> 'debug'.tap(&dbg)
|
|
63
|
+
irb(main):004> 'information'.tap(&info)
|
|
64
|
+
|
|
65
|
+
# 注:创建 warn 方法,会导致 irb 的补全功能出问题。
|
|
66
|
+
# 因此 LambdaExt 用的是 warning, 而不是 warn。
|
|
67
|
+
# 您如果确实需要 warn,那就调用 include Sinlog::LambdaWarnExt
|
|
68
|
+
irb(main):005> 'warning'.tap(&warning)
|
|
69
|
+
|
|
70
|
+
irb(main):006> 'error'.tap(&err)
|
|
71
|
+
irb(main):007> 'fatal'.tap(&fatal)
|
|
72
|
+
irb(main):008> 'unknown'.tap(&unk)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
<img src="../assets/img/LambdaExt.jpg" alt="LambdaExt" style="width: 50%; height: 50%">
|
|
76
|
+
|
|
77
|
+
LambdaExt 提供了:
|
|
78
|
+
|
|
79
|
+
- dbg
|
|
80
|
+
- info
|
|
81
|
+
- warning
|
|
82
|
+
- wng (与 warning 相同,只是名称不同)
|
|
83
|
+
- err
|
|
84
|
+
- fatal
|
|
85
|
+
- unk
|
|
86
|
+
|
|
87
|
+
#### LogLambdaExt
|
|
88
|
+
|
|
89
|
+
有一个与 LambdaExt 特别相似的模块,名为 LogLambdaExt。
|
|
90
|
+
它们之间最主要的区别在于 lambda 函数的名称。
|
|
91
|
+
|
|
92
|
+
- LogLambdaExt 带有 `log_` 前缀
|
|
93
|
+
- LambdaExt 没有
|
|
94
|
+
|
|
95
|
+
LambdaExt 与 LogLambdaExt 可以同时 include, 不过在一般情况下,我们引入其中一个就够用了。
|
|
96
|
+
|
|
97
|
+
至于哪一个更好呢?
|
|
98
|
+
|
|
99
|
+
我们不妨亲自上手试试,了解其中的区别,最后挑一个自己喜欢的。
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
irb(main):009> include Sinlog::LogLambdaExt
|
|
103
|
+
# 它提供了 log_dbg, log_info, log_warn, log_err, log_fatal, log_unk
|
|
104
|
+
# 我们可以用 .tap(&log_dbg) 或 .then(&log_dbg) 来调用。
|
|
105
|
+
|
|
106
|
+
irb(main):010> "debug".tap(&log_dbg)
|
|
107
|
+
irb(main):011> "information".tap(&log_info)
|
|
108
|
+
|
|
109
|
+
# 注:这里用的是 log_warn,而不是 log_warning
|
|
110
|
+
irb(main):012> "warning".tap(&log_warn)
|
|
111
|
+
|
|
112
|
+
irb(main):013> "error".tap(&log_err)
|
|
113
|
+
irb(main):014> "fatal".tap(&log_fatal)
|
|
114
|
+
irb(main):015> "unknown".tap(&log_unk)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
# 这是一个更复杂的例子
|
|
119
|
+
irb(main):016> require 'pathname'
|
|
120
|
+
|
|
121
|
+
irb(main):017> Pathname('lib/lambda.rb').tap do
|
|
122
|
+
"Filename: #{it}".then(&log_info)
|
|
123
|
+
"size: #{
|
|
124
|
+
it
|
|
125
|
+
.tap{ '⚠️ 获取文件大小可能会失败'.then(&log_warn) }
|
|
126
|
+
.size
|
|
127
|
+
}".then(&log_info)
|
|
128
|
+
end
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
<img src="../assets/img/LogLambdaExt.jpg" alt="LogLambdaExt" style="width: 90%; height: 90%">
|
|
132
|
+
|
|
133
|
+
LogLambdaExt 提供了:
|
|
134
|
+
|
|
135
|
+
- log_dbg
|
|
136
|
+
- log_info
|
|
137
|
+
- log_warn
|
|
138
|
+
- log_warning (与 log_warn 相同,只是名称不同)
|
|
139
|
+
- log_wng (与 log_warn 相同,只是名称不同)
|
|
140
|
+
- log_err
|
|
141
|
+
- log_fatal
|
|
142
|
+
- log_unk
|
|
143
|
+
|
|
144
|
+
### Classic Method Call
|
|
145
|
+
|
|
146
|
+
您如果不喜欢 lambda,那就试试经典的方法调用吧!
|
|
147
|
+
|
|
148
|
+
先运行 irb 进入 ruby repl,接着一步一步运行。
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
irb(main):001> require 'sinlog'
|
|
152
|
+
|
|
153
|
+
irb(main):002> log = Sinlog.instance.logger
|
|
154
|
+
|
|
155
|
+
irb(main):003> log.debug 'debug'
|
|
156
|
+
irb(main):004> log.info 'information'
|
|
157
|
+
irb(main):005> log.warn 'warning'
|
|
158
|
+
irb(main):006> log.error 'error'
|
|
159
|
+
irb(main):007> log.fatal 'fatal'
|
|
160
|
+
irb(main):008> log.unknown 'unknown'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Sinlog.instance.logger 提供了 ruby 标准库的 logger 的方法。
|
|
164
|
+
|
|
165
|
+
最常见的有:
|
|
166
|
+
|
|
167
|
+
- debug
|
|
168
|
+
- info
|
|
169
|
+
- warn
|
|
170
|
+
- error
|
|
171
|
+
- fatal
|
|
172
|
+
- unknown
|
|
173
|
+
|
|
174
|
+
## 进阶
|
|
175
|
+
|
|
176
|
+
在亲自上手尝试之后,我们已经对 sinlog 有了初步的了解。
|
|
177
|
+
在一般情况下,了解其基本用法就已经足够了。
|
|
178
|
+
|
|
179
|
+
您如果对此感兴趣的话,不妨与我一同继续探索。
|
|
180
|
+
|
|
181
|
+
### Real World Example
|
|
182
|
+
|
|
183
|
+
在现实世界中,我们的程序可能会是这样子的:
|
|
184
|
+
|
|
185
|
+
```ruby
|
|
186
|
+
require 'sinlog'
|
|
187
|
+
|
|
188
|
+
class EpubProcessor
|
|
189
|
+
def initialize(epub_file, logger = nil)
|
|
190
|
+
@epub = epub_file
|
|
191
|
+
@logger = logger || Sinlog.instance.tap { it.fetch_env_and_update_log_level("XX_LOG") }.logger
|
|
192
|
+
@logger.debug "EpubProcessor class 初始化完成。"
|
|
193
|
+
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
我们可能会定义类的 @logger 实例变量,并允许自定义 logger。
|
|
199
|
+
|
|
200
|
+
简单来说,我们可能会对 logger 进行更精细化的配置。
|
|
201
|
+
|
|
202
|
+
在接下来的内容中,我们将探讨如何进行“更精细化的配置”。
|
|
203
|
+
|
|
204
|
+
### 日志级别
|
|
205
|
+
|
|
206
|
+
日志级别从低到高,依次是:
|
|
207
|
+
|
|
208
|
+
- debug = 0
|
|
209
|
+
- info = 1
|
|
210
|
+
- warn = 2
|
|
211
|
+
- error = 3
|
|
212
|
+
- fatal = 4
|
|
213
|
+
- unknown = 5
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
p Sinlog::LV
|
|
217
|
+
# => {debug: 0, info: 1, warn: 2, error: 3, fatal: 4, unknown: 5}
|
|
218
|
+
|
|
219
|
+
# 将日志级别修改为 warn
|
|
220
|
+
log = Sinlog.instance.logger.tap {it.level = Sinlog::LV[:warn]}
|
|
221
|
+
# 或者是:
|
|
222
|
+
# log = Sinlog.instance.logger.tap {it.level = 2}
|
|
223
|
+
|
|
224
|
+
log.error "这条消息会显示出来!低级别 WARN(2)会显示高级别 ERROR(3) 的日志。"
|
|
225
|
+
log.info "这条消息不会显示出来!高级别 WARN(2) 不会显示低级别 INFO(1) 的日志。"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
- 日志级别越低,显示的内容越详细。
|
|
229
|
+
- 低级别 **会** 显示高级别的日志。
|
|
230
|
+
- 高级别 **不会** 显示低级别的日志。
|
|
231
|
+
|
|
232
|
+
### 环境变量
|
|
233
|
+
|
|
234
|
+
在现实世界中,对于客户端应用,最后运行程序的是普通用户。
|
|
235
|
+
为了能让普通用户直接配置 log.level,我们可以通过环境变量来配置。
|
|
236
|
+
|
|
237
|
+
> 使用环境变量足够简单也足够高效。
|
|
238
|
+
|
|
239
|
+
Sinlog 在默认情况下,会尝试读取环境变量 RUBY_LOG 的值。
|
|
240
|
+
|
|
241
|
+
本质上调用了 `fetch_env_and_update_log_level(env_name = 'RUBY_LOG')` 函数。
|
|
242
|
+
|
|
243
|
+
- 若该环境变量不存在,则使用 debug(0)。
|
|
244
|
+
- 若该环境变量存在,且其值为空,则使用 unknown(5)。
|
|
245
|
+
- 若该环境变量的值无效,则使用 unknown(5)。
|
|
246
|
+
|
|
247
|
+
我们可以用 POSIX-sh 设置环境变量,然后 logger 在初始化的时候,就会自动将日志级别设置为(RUBY_LOG的值)warn。
|
|
248
|
+
|
|
249
|
+
```sh
|
|
250
|
+
# 可选值:debug, info, warn, error, fatal
|
|
251
|
+
export RUBY_LOG=warn
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
您如果不想要默认的 RUBY_LOG 环境变量,而是想要 XX_CLI_LOG 的值,那可以这样子做:
|
|
255
|
+
|
|
256
|
+
POSIX-sh:
|
|
257
|
+
|
|
258
|
+
```sh
|
|
259
|
+
export XX_CLI_LOG=info
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
ruby:
|
|
263
|
+
|
|
264
|
+
```ruby
|
|
265
|
+
logger = Sinlog.instance.tap { it.fetch_env_and_update_log_level("XX_CLI_LOG") }.logger
|
|
266
|
+
|
|
267
|
+
logger.debug "由于当前日志级别为 INFO(1),因此不会显示此消息 DEBUG(0)。"
|
|
268
|
+
logger.info "Hello!"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 日志输出设备/路径
|
|
272
|
+
|
|
273
|
+
默认情况下,Sinlog 会输出到 STDERR。
|
|
274
|
+
|
|
275
|
+
您如果需要自定义日志输出路径的话,那可以调用 logger 的 reopen 方法。
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
# 日志会输出到 a.log 文件
|
|
279
|
+
log = Sinlog.instance.logger.tap {it.reopen("a.log")}
|
|
280
|
+
|
|
281
|
+
log.error "发生甚么事了!QuQ"
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
OR:
|
|
285
|
+
|
|
286
|
+
```ruby
|
|
287
|
+
log = Sinlog.instance.logger
|
|
288
|
+
log.reopen("a.log")
|
|
289
|
+
|
|
290
|
+
log.error "发生甚么事了!QuQ"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 其他 logger 方法
|
|
294
|
+
|
|
295
|
+
除了 `.reopen`, `.level` 外,我们还可以在 `Sinlog.instance.logger` 上调用 ruby 标准库的 logger 的其他方法。
|
|
296
|
+
|
|
297
|
+
### 注意事项
|
|
298
|
+
|
|
299
|
+
Sinlog 用的是 Singleton 单例模式,整个程序会共享同一个实例(日志记录器)。
|
|
300
|
+
|
|
301
|
+
在同一个程序的 class A 中修改 Sinlog 后,会影响到 class B 的 Sinlog。
|
|
302
|
+
|
|
303
|
+
## 题外话
|
|
304
|
+
|
|
305
|
+
这是我发布的第一个 ruby gem。
|
|
306
|
+
其中的 api 不一定符合地道的 ruby 用法,还请大家多多谅解。
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
[MIT License](../License)
|
data/docs/Readme.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Sinlog
|
|
2
|
+
|
|
3
|
+
A very, very simple Ruby singleton logger with colored log levels.
|
|
4
|
+
|
|
5
|
+
> Singleton means that the entire program will share the same instance (logger).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
| Language/語言 | ID |
|
|
10
|
+
| ------------------------------- | ---------- |
|
|
11
|
+
| English | en-Latn-US |
|
|
12
|
+
| [简体中文](./Readme-zh.md) | zh-Hans-CN |
|
|
13
|
+
| [繁體中文](./Readme-zh-Hant.md) | zh-Hant-TW |
|
|
14
|
+
|
|
15
|
+
> Want to support Mehr Sprachen/Más idiomas/Autres langues/Другие языки/...?
|
|
16
|
+
>
|
|
17
|
+
> Please feel free to send me an issue!
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<details>
|
|
22
|
+
<summary>
|
|
23
|
+
Table of Contents (click to expand)
|
|
24
|
+
</summary>
|
|
25
|
+
|
|
26
|
+
- [Learn Sinlog API By Example](#learn-sinlog-api-by-example)
|
|
27
|
+
- [include module](#include-module)
|
|
28
|
+
- [LambdaExt](#lambdaext)
|
|
29
|
+
- [LogLambdaExt](#loglambdaext)
|
|
30
|
+
- [Classic Method Call](#classic-method-call)
|
|
31
|
+
- [Advanced](#advanced)
|
|
32
|
+
- [Real World Example](#real-world-example)
|
|
33
|
+
- [Log Levels](#log-levels)
|
|
34
|
+
- [Environment Variables](#environment-variables)
|
|
35
|
+
- [Log Output Device/Path](#log-output-devicepath)
|
|
36
|
+
- [Other Logger Methods](#other-logger-methods)
|
|
37
|
+
- [Notes](#notes)
|
|
38
|
+
- [Side Note](#side-note)
|
|
39
|
+
- [License](#license)
|
|
40
|
+
|
|
41
|
+
</details>
|
|
42
|
+
|
|
43
|
+
## Learn Sinlog API By Example
|
|
44
|
+
|
|
45
|
+
First, install `sinlog`.
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
gem install sinlog
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Then, we can run `irb` to quickly try it out.
|
|
52
|
+
|
|
53
|
+
### include module
|
|
54
|
+
|
|
55
|
+
#### LambdaExt
|
|
56
|
+
|
|
57
|
+
When you see: `irb(main):001>`, we can start operating.
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
irb(main):001> require 'sinlog'
|
|
61
|
+
|
|
62
|
+
irb(main):002> include Sinlog::LambdaExt
|
|
63
|
+
# It provides: dbg, info, warning, err, fatal, unk
|
|
64
|
+
# We can call them using .tap(&dbg) or .then(&dbg).
|
|
65
|
+
|
|
66
|
+
irb(main):003> 'debug'.tap(&dbg)
|
|
67
|
+
irb(main):004> 'information'.tap(&info)
|
|
68
|
+
|
|
69
|
+
# Note: Creating a warn method will cause issues with irb's auto-completion.
|
|
70
|
+
# Therefore, LambdaExt uses warning instead of warn.
|
|
71
|
+
# If you really need warn, then call include Sinlog::LambdaWarnExt
|
|
72
|
+
irb(main):005> 'warning'.tap(&warning)
|
|
73
|
+
|
|
74
|
+
irb(main):006> 'error'.tap(&err)
|
|
75
|
+
irb(main):007> 'fatal'.tap(&fatal)
|
|
76
|
+
irb(main):008> 'unknown'.tap(&unk)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
<img src="../assets/img/LambdaExt.jpg" alt="LambdaExt" style="width: 50%; height: 50%">
|
|
80
|
+
|
|
81
|
+
LambdaExt provides:
|
|
82
|
+
|
|
83
|
+
- dbg
|
|
84
|
+
- info
|
|
85
|
+
- warning
|
|
86
|
+
- wng (same as warning, just a different name)
|
|
87
|
+
- err
|
|
88
|
+
- fatal
|
|
89
|
+
- unk
|
|
90
|
+
|
|
91
|
+
#### LogLambdaExt
|
|
92
|
+
|
|
93
|
+
There is a module very similar to LambdaExt called LogLambdaExt.
|
|
94
|
+
The main difference between them is the naming of the lambda functions.
|
|
95
|
+
|
|
96
|
+
- LogLambdaExt has a `log_` prefix
|
|
97
|
+
- LambdaExt does not
|
|
98
|
+
|
|
99
|
+
LambdaExt and LogLambdaExt can be included simultaneously, but in general, including one of them is sufficient.
|
|
100
|
+
|
|
101
|
+
Which one is better?
|
|
102
|
+
|
|
103
|
+
Let's try them out to understand the differences and choose the one we prefer.
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
irb(main):009> include Sinlog::LogLambdaExt
|
|
107
|
+
# It provides log_dbg, log_info, log_warn, log_err, log_fatal, log_unk
|
|
108
|
+
# We can call them using .tap(&log_dbg) or .then(&log_dbg).
|
|
109
|
+
|
|
110
|
+
irb(main):010> "debug".tap(&log_dbg)
|
|
111
|
+
irb(main):011> "information".tap(&log_info)
|
|
112
|
+
|
|
113
|
+
# Note: Here we use log_warn, not log_warning
|
|
114
|
+
irb(main):012> "warning".tap(&log_warn)
|
|
115
|
+
|
|
116
|
+
irb(main):013> "error".tap(&log_err)
|
|
117
|
+
irb(main):014> "fatal".tap(&log_fatal)
|
|
118
|
+
irb(main):015> "unknown".tap(&log_unk)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
# Here is a more complex example
|
|
123
|
+
irb(main):016> require 'pathname'
|
|
124
|
+
|
|
125
|
+
irb(main):017> Pathname('lib/lambda.rb').tap do
|
|
126
|
+
"Filename: #{it}".then(&log_info)
|
|
127
|
+
"size: #{
|
|
128
|
+
it
|
|
129
|
+
.tap{ '⚠️ Getting file size might fail'.then(&log_warn) }
|
|
130
|
+
.size
|
|
131
|
+
}".then(&log_info)
|
|
132
|
+
end
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
<img src="../assets/img/LogLambdaExt.jpg" alt="LogLambdaExt" style="width: 90%; height: 90%">
|
|
136
|
+
|
|
137
|
+
LogLambdaExt provides:
|
|
138
|
+
|
|
139
|
+
- log_dbg
|
|
140
|
+
- log_info
|
|
141
|
+
- log_warn
|
|
142
|
+
- log_warning (same as log_warn, just a different name)
|
|
143
|
+
- log_wng (same as log_warn, just a different name)
|
|
144
|
+
- log_err
|
|
145
|
+
- log_fatal
|
|
146
|
+
- log_unk
|
|
147
|
+
|
|
148
|
+
### Classic Method Call
|
|
149
|
+
|
|
150
|
+
If you don't like lambdas, you can try the classic method call!
|
|
151
|
+
|
|
152
|
+
First, run `irb` to enter the Ruby REPL, then follow these steps:
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
irb(main):001> require 'sinlog'
|
|
156
|
+
|
|
157
|
+
irb(main):002> log = Sinlog.instance.logger
|
|
158
|
+
|
|
159
|
+
irb(main):003> log.debug 'debug'
|
|
160
|
+
irb(main):004> log.info 'information'
|
|
161
|
+
irb(main):005> log.warn 'warning'
|
|
162
|
+
irb(main):006> log.error 'error'
|
|
163
|
+
irb(main):007> log.fatal 'fatal'
|
|
164
|
+
irb(main):008> log.unknown 'unknown'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Sinlog.instance.logger provides methods from Ruby's standard library logger.
|
|
168
|
+
|
|
169
|
+
The most common ones are:
|
|
170
|
+
|
|
171
|
+
- debug
|
|
172
|
+
- info
|
|
173
|
+
- warn
|
|
174
|
+
- error
|
|
175
|
+
- fatal
|
|
176
|
+
- unknown
|
|
177
|
+
|
|
178
|
+
## Advanced
|
|
179
|
+
|
|
180
|
+
After trying it out ourselves, we have a basic understanding of `sinlog`.
|
|
181
|
+
In most cases, knowing its basic usage is sufficient.
|
|
182
|
+
|
|
183
|
+
If you're interested, let's continue exploring together.
|
|
184
|
+
|
|
185
|
+
### Real World Example
|
|
186
|
+
|
|
187
|
+
In the real world, our program might look like this:
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
require 'sinlog'
|
|
191
|
+
|
|
192
|
+
class EpubProcessor
|
|
193
|
+
def initialize(epub_file, logger = nil)
|
|
194
|
+
@epub = epub_file
|
|
195
|
+
@logger = logger || Sinlog.instance.tap { it.fetch_env_and_update_log_level("XX_LOG") }.logger
|
|
196
|
+
@logger.debug "EpubProcessor class initialization completed."
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
We might define a class's `@logger` instance variable and allow for a custom logger.
|
|
202
|
+
|
|
203
|
+
Simply put, we might configure the logger more finely.
|
|
204
|
+
|
|
205
|
+
In the following content, we will explore how to perform "more fine-grained configuration."
|
|
206
|
+
|
|
207
|
+
### Log Levels
|
|
208
|
+
|
|
209
|
+
Log levels from low to high are:
|
|
210
|
+
|
|
211
|
+
- debug = 0
|
|
212
|
+
- info = 1
|
|
213
|
+
- warn = 2
|
|
214
|
+
- error = 3
|
|
215
|
+
- fatal = 4
|
|
216
|
+
- unknown = 5
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
p Sinlog::LV
|
|
220
|
+
# => {debug: 0, info: 1, warn: 2, error: 3, fatal: 4, unknown: 5}
|
|
221
|
+
|
|
222
|
+
# Change the log level to warn
|
|
223
|
+
log = Sinlog.instance.logger.tap { it.level = Sinlog::LV[:warn] }
|
|
224
|
+
# Or:
|
|
225
|
+
# log = Sinlog.instance.logger.tap { it.level = 2 }
|
|
226
|
+
|
|
227
|
+
log.error "This message will be displayed! Lower level WARN (2) will display higher level ERROR (3) logs."
|
|
228
|
+
log.info "This message will not be displayed! Higher level WARN (2) will not display lower level INFO (1) logs."
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
- The lower the log level, the more detailed the content displayed.
|
|
232
|
+
- Lower levels **will** display higher level logs.
|
|
233
|
+
- Higher levels **will not** display lower level logs.
|
|
234
|
+
|
|
235
|
+
### Environment Variables
|
|
236
|
+
|
|
237
|
+
In the real world, for client applications, the end users are typically regular users.
|
|
238
|
+
To allow them to configure `log.level` directly, we can use environment variables.
|
|
239
|
+
|
|
240
|
+
> Using environment variables is simple and efficient.
|
|
241
|
+
|
|
242
|
+
By default, Sinlog will attempt to read the value of the environment variable `RUBY_LOG`.
|
|
243
|
+
|
|
244
|
+
It essentially calls the function `fetch_env_and_update_log_level(env_name = 'RUBY_LOG')`.
|
|
245
|
+
|
|
246
|
+
- If the environment variable does not exist, it uses `debug(0)`.
|
|
247
|
+
- If the environment variable exists but is empty, it uses `unknown(5)`.
|
|
248
|
+
- If the environment variable's value is invalid, it uses `unknown(5)`.
|
|
249
|
+
|
|
250
|
+
We can set the environment variable using POSIX-sh, and then the logger will automatically set the log level to `warn` (the value of `RUBY_LOG`) during initialization.
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
# Possible values: debug, info, warn, error, fatal
|
|
254
|
+
export RUBY_LOG=warn
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
If you don't want to use the default `RUBY_LOG` environment variable and prefer to use the value of `XX_CLI_LOG`, you can do it like this:
|
|
258
|
+
|
|
259
|
+
POSIX-sh:
|
|
260
|
+
|
|
261
|
+
```sh
|
|
262
|
+
export XX_CLI_LOG=info
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Ruby:
|
|
266
|
+
|
|
267
|
+
```ruby
|
|
268
|
+
logger = Sinlog.instance.tap { it.fetch_env_and_update_log_level("XX_CLI_LOG") }.logger
|
|
269
|
+
|
|
270
|
+
logger.debug "This message will not be displayed because the current log level is INFO(1)."
|
|
271
|
+
logger.info "Hello!"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Log Output Device/Path
|
|
275
|
+
|
|
276
|
+
By default, Sinlog outputs to `STDERR`.
|
|
277
|
+
|
|
278
|
+
If you need to customize the log output path, you can call the logger's `reopen` method.
|
|
279
|
+
|
|
280
|
+
```ruby
|
|
281
|
+
# Logs will be output to the file a.log
|
|
282
|
+
log = Sinlog.instance.logger.tap { it.reopen("a.log") }
|
|
283
|
+
|
|
284
|
+
log.error "What happened! QuQ"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
OR:
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
log = Sinlog.instance.logger
|
|
291
|
+
log.reopen("a.log")
|
|
292
|
+
|
|
293
|
+
log.error "What happened! QuQ"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Other Logger Methods
|
|
297
|
+
|
|
298
|
+
In addition to `.reopen` and `.level`, we can also call other methods from Ruby's standard library logger on `Sinlog.instance.logger`.
|
|
299
|
+
|
|
300
|
+
### Notes
|
|
301
|
+
|
|
302
|
+
Sinlog uses the Singleton pattern, meaning the entire program will share the same instance (logger).
|
|
303
|
+
|
|
304
|
+
Modifying Sinlog in class A of the same program will affect Sinlog in class B.
|
|
305
|
+
|
|
306
|
+
## Side Note
|
|
307
|
+
|
|
308
|
+
This is the first Ruby gem I have released.
|
|
309
|
+
The API might not fully adhere to idiomatic Ruby usage, so I appreciate your understanding.
|
|
310
|
+
|
|
311
|
+
## License
|
|
312
|
+
|
|
313
|
+
[MIT License](../License)
|
data/lib/init.rb
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Logger Singleton Class
|
|
4
|
+
class Sinlog
|
|
5
|
+
include Singleton
|
|
6
|
+
attr_reader :logger
|
|
7
|
+
|
|
8
|
+
# Define colors for different log levels
|
|
9
|
+
COLORS = {
|
|
10
|
+
debug: "\e[34m", # Blue
|
|
11
|
+
info: "\e[36m", # Cyan
|
|
12
|
+
warn: "\e[33m", # Yellow
|
|
13
|
+
error: "\e[31m", # Red
|
|
14
|
+
fatal: "\e[35m", # Magenta
|
|
15
|
+
unknown: "\e[0m" # Reset
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
# log levels
|
|
19
|
+
LV = {
|
|
20
|
+
debug: Logger::DEBUG,
|
|
21
|
+
info: Logger::INFO,
|
|
22
|
+
warn: Logger::WARN,
|
|
23
|
+
error: Logger::ERROR,
|
|
24
|
+
fatal: Logger::FATAL,
|
|
25
|
+
unknown: Logger::UNKNOWN
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
# Example:
|
|
29
|
+
#
|
|
30
|
+
# logger = Sinlog.instance.logger
|
|
31
|
+
# logger.info "Information"
|
|
32
|
+
# logger.debug "This is a debug message"
|
|
33
|
+
#
|
|
34
|
+
# The log output format will be similar to:
|
|
35
|
+
#
|
|
36
|
+
# [INFO] 21:29:22.004 Information
|
|
37
|
+
# [DEBUG] 21:29:22.005 This is a debug message
|
|
38
|
+
#
|
|
39
|
+
# Where "INFO" is highlighted in cyan and "DEBUG" is highlighted in blue.
|
|
40
|
+
#
|
|
41
|
+
# The default log level is set based on the RUBY_LOG environment variable.
|
|
42
|
+
# If this variable is not set, the default level is DEBUG.
|
|
43
|
+
def initialize
|
|
44
|
+
@logger = Logger.new($stderr)
|
|
45
|
+
fetch_env_and_update_log_level
|
|
46
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
|
47
|
+
color = COLORS[severity.downcase.to_sym]
|
|
48
|
+
reset = COLORS[:unknown]
|
|
49
|
+
formatted_datetime = datetime.strftime('%H:%M:%S.%L')
|
|
50
|
+
prog = format_prog_name(progname)
|
|
51
|
+
"[#{color}#{severity}#{reset}] #{formatted_datetime} #{prog}#{msg}\n"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Set the `@logger.level` (**log level**) based on the value of an environment variable.
|
|
56
|
+
#
|
|
57
|
+
# If env_name is not specified, it reads the value of the `RUBY_LOG` environment variable.
|
|
58
|
+
#
|
|
59
|
+
# - If the value exists, it is converted to lowercase, then to a symbol, and looked up in the LV hash;
|
|
60
|
+
# - If it does not exist, the default level is DEBUG;
|
|
61
|
+
# - If the lookup result is invalid, the level is set to UNKNOWN;
|
|
62
|
+
# - If the environment variable value is empty, the lookup result will be invalid,
|
|
63
|
+
# and the level will be set to UNKNOWN.
|
|
64
|
+
#
|
|
65
|
+
# Example:
|
|
66
|
+
#
|
|
67
|
+
# ENV["XX_LOG"] = "info" # or setenv in posix-sh: export XX_LOG=info
|
|
68
|
+
#
|
|
69
|
+
# logger = Sinlog.instance.tap { it.fetch_env_and_update_log_level("XX_LOG") }.logger
|
|
70
|
+
#
|
|
71
|
+
# logger.debug "This message will not be displayed because the current log level is info"
|
|
72
|
+
# logger.info "Hello!"
|
|
73
|
+
def fetch_env_and_update_log_level(env_name = 'RUBY_LOG')
|
|
74
|
+
env_lv = ENV[env_name]&.downcase&.to_sym || :debug
|
|
75
|
+
|
|
76
|
+
(LV[env_lv] || Logger::UNKNOWN)
|
|
77
|
+
.then { @logger.level = _1 }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def format_prog_name(progname)
|
|
83
|
+
return '' if progname.to_s.empty?
|
|
84
|
+
|
|
85
|
+
green = "\e[32m"
|
|
86
|
+
reset = "\e[0m"
|
|
87
|
+
space = ' '
|
|
88
|
+
"<#{green}#{progname}#{reset}>#{space}"
|
|
89
|
+
end
|
|
90
|
+
end
|
data/lib/lambda.rb
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Lint/MissingCopEnableDirective, Style/ClassVars
|
|
4
|
+
|
|
5
|
+
class Sinlog
|
|
6
|
+
# Module to simplify logger calls using lambda expressions.
|
|
7
|
+
#
|
|
8
|
+
# The following methods define lambda expressions for different log levels.
|
|
9
|
+
# These lambdas can be used to log messages at the corresponding log level.
|
|
10
|
+
module LogLambdaExt
|
|
11
|
+
@@_sinlog_lambda_ext_logger_ = Sinlog.instance.logger
|
|
12
|
+
|
|
13
|
+
# Debug Logging
|
|
14
|
+
#
|
|
15
|
+
# Example:
|
|
16
|
+
#
|
|
17
|
+
# require 'sinlog'
|
|
18
|
+
# include Sinlog::LogLambdaExt
|
|
19
|
+
#
|
|
20
|
+
# 'Debug Message'.then(&log_dbg)
|
|
21
|
+
#
|
|
22
|
+
# cmd = %w[ls -l -h]
|
|
23
|
+
# "cmd_arr: #{cmd}".tap(&log_dbg)
|
|
24
|
+
def log_dbg
|
|
25
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.debug(msg) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Info(a.k.a. Information) Logging
|
|
29
|
+
#
|
|
30
|
+
# Example:
|
|
31
|
+
#
|
|
32
|
+
# require 'pathname'
|
|
33
|
+
#
|
|
34
|
+
# Pathname('lib/lambda.rb').tap {
|
|
35
|
+
# "Filename: #{it}".then(&log_info)
|
|
36
|
+
# "size: #{it.size}".then(&log_info)
|
|
37
|
+
# }
|
|
38
|
+
def log_info
|
|
39
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.info(msg) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Warning Logging
|
|
43
|
+
#
|
|
44
|
+
# Example:
|
|
45
|
+
#
|
|
46
|
+
# arr = (0..256).to_a
|
|
47
|
+
# 'This array is too large'.then(&log_warn) if arr.length > 128
|
|
48
|
+
def log_warn
|
|
49
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.warn(msg) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Warning Logging
|
|
53
|
+
#
|
|
54
|
+
# Same as `log_warn`
|
|
55
|
+
def log_warning
|
|
56
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.warn(msg) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Warning Logging
|
|
60
|
+
#
|
|
61
|
+
# Same as `log_warn`
|
|
62
|
+
def log_wng
|
|
63
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.warn(msg) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Error Logging
|
|
67
|
+
#
|
|
68
|
+
# Example:
|
|
69
|
+
#
|
|
70
|
+
# 'CLI error: You should pass the --url'.then(&log_err)
|
|
71
|
+
def log_err
|
|
72
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.error(msg) }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Fatal error logging
|
|
76
|
+
#
|
|
77
|
+
# Example:
|
|
78
|
+
#
|
|
79
|
+
# 'Failed to open xxx'.then(&log_fatal)
|
|
80
|
+
def log_fatal
|
|
81
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.fatal(msg) }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Example:
|
|
85
|
+
#
|
|
86
|
+
# 'Unknown'.then(&log_unk)
|
|
87
|
+
def log_unk
|
|
88
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.unknown(msg) }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Similar to LogLambdaExt, but the lambda functions do not have the `log_` prefix.
|
|
93
|
+
# One important thing to note is that LambdaExt defines the `warning` function, not `warn`.
|
|
94
|
+
#
|
|
95
|
+
# The following methods define lambda expressions for different log levels.
|
|
96
|
+
# These lambdas can be used to log messages at the corresponding log level.
|
|
97
|
+
module LambdaExt
|
|
98
|
+
@@_sinlog_lambda_ext_logger_ = Sinlog.instance.logger
|
|
99
|
+
|
|
100
|
+
# Debug Logging
|
|
101
|
+
#
|
|
102
|
+
# Example:
|
|
103
|
+
#
|
|
104
|
+
# require 'sinlog'
|
|
105
|
+
# include Sinlog::LambdaExt
|
|
106
|
+
#
|
|
107
|
+
# 'Debug Message'.then(&dbg)
|
|
108
|
+
#
|
|
109
|
+
# cmd = %w[ls -l -h]
|
|
110
|
+
# "cmd_arr: #{cmd}".tap(&dbg)
|
|
111
|
+
def dbg
|
|
112
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.debug(msg) }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Info(a.k.a. Information) Logging
|
|
116
|
+
#
|
|
117
|
+
# Example:
|
|
118
|
+
#
|
|
119
|
+
# require 'pathname'
|
|
120
|
+
#
|
|
121
|
+
# Pathname('lib/lambda.rb').tap {
|
|
122
|
+
# "Filename: #{it}".then(&info)
|
|
123
|
+
# "size: #{it.size}".then(&info)
|
|
124
|
+
# }
|
|
125
|
+
def info
|
|
126
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.info(msg) }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Warning Logging
|
|
130
|
+
#
|
|
131
|
+
# Example:
|
|
132
|
+
#
|
|
133
|
+
# arr = (0..1024).to_a
|
|
134
|
+
# 'This array is too large'.then(&warning) if arr.length > 128
|
|
135
|
+
def warning
|
|
136
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.warn(msg) }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Warning Logging
|
|
140
|
+
#
|
|
141
|
+
# Same as `warning`
|
|
142
|
+
def wng
|
|
143
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.warn(msg) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Error Logging
|
|
147
|
+
#
|
|
148
|
+
# Example:
|
|
149
|
+
#
|
|
150
|
+
# 'CLI error: You should pass the --url'.then(&err)
|
|
151
|
+
def err
|
|
152
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.error(msg) }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Fatal error logging
|
|
156
|
+
#
|
|
157
|
+
# Example:
|
|
158
|
+
#
|
|
159
|
+
# 'Failed to open xxx'.then(&fatal)
|
|
160
|
+
def fatal
|
|
161
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.fatal(msg) }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Unknown(log-level) logging
|
|
165
|
+
#
|
|
166
|
+
# Example:
|
|
167
|
+
#
|
|
168
|
+
# 'Unknown'.then(&unk)
|
|
169
|
+
def unk
|
|
170
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.unknown(msg) }
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Defines the `warn` lambda expression
|
|
175
|
+
module LambdaWarnExt
|
|
176
|
+
@@_sinlog_lambda_ext_logger_ = Sinlog.instance.logger
|
|
177
|
+
# Warning Logging
|
|
178
|
+
#
|
|
179
|
+
# Same as `LambdaExt.warning`
|
|
180
|
+
def warn
|
|
181
|
+
->(msg) { @@_sinlog_lambda_ext_logger_.warn(msg) }
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
data/lib/sinlog.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Usage:
|
|
4
|
+
#
|
|
5
|
+
# require 'sinlog'
|
|
6
|
+
#
|
|
7
|
+
# logger = Sinlog.instance.logger
|
|
8
|
+
# logger.info "Information"
|
|
9
|
+
# logger.debug "This is a debug message"
|
|
10
|
+
#
|
|
11
|
+
# Read more: https://github.com/2moe/sinlog-gem
|
|
12
|
+
|
|
13
|
+
require_relative 'sinlog/version'
|
|
14
|
+
require 'singleton'
|
|
15
|
+
require 'logger'
|
|
16
|
+
|
|
17
|
+
require_relative 'init'
|
|
18
|
+
require_relative 'lambda'
|
metadata
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sinlog
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- 2moe
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2025-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: A very, very simple singleton logger with colored log levels.
|
|
13
|
+
executables: []
|
|
14
|
+
extensions: []
|
|
15
|
+
extra_rdoc_files: []
|
|
16
|
+
files:
|
|
17
|
+
- License
|
|
18
|
+
- docs/Readme-zh.md
|
|
19
|
+
- docs/Readme.md
|
|
20
|
+
- lib/init.rb
|
|
21
|
+
- lib/lambda.rb
|
|
22
|
+
- lib/sinlog.rb
|
|
23
|
+
- lib/sinlog/version.rb
|
|
24
|
+
homepage: https://github.com/2moe/sinlog-gem
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT
|
|
27
|
+
metadata: {}
|
|
28
|
+
rdoc_options: []
|
|
29
|
+
require_paths:
|
|
30
|
+
- lib
|
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
32
|
+
requirements:
|
|
33
|
+
- - ">="
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: 3.0.0
|
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
requirements: []
|
|
42
|
+
rubygems_version: 3.6.2
|
|
43
|
+
specification_version: 4
|
|
44
|
+
summary: colorful singleton logger
|
|
45
|
+
test_files: []
|