v / vlib / log
Raw file | 159 loc (139 sloc) | 5.67 KB | Latest commit hash 017ace6ea
1// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module log
5
6import os
7import time
8
9// Log represents a logging object
10pub struct Log {
11mut:
12 level Level
13 output_label string
14 ofile os.File
15 output_target LogTarget // output to console (stdout/stderr) or file or both.
16pub mut:
17 output_file_name string // log output to this file
18}
19
20// get_level gets the internal logging level.
21pub fn (l &Log) get_level() Level {
22 return l.level
23}
24
25// set_level sets the logging level to `level`. Messges for levels above it will skipped.
26// For example, after calling log.set_level(.info), log.debug('message') will produce nothing.
27// Call log.set_level(.disabled) to turn off the logging of all messages.
28pub fn (mut l Log) set_level(level Level) {
29 l.level = level
30}
31
32// set_output_level sets the internal logging output to `level`.
33[deprecated: 'use .set_level(level) instead']
34[deprecated_after: '2023-09-30']
35pub fn (mut l Log) set_output_level(level Level) {
36 l.level = level
37}
38
39// set_full_logpath sets the output label and output path from `full_log_path`.
40pub fn (mut l Log) set_full_logpath(full_log_path string) {
41 rlog_file := os.real_path(full_log_path)
42 l.set_output_label(os.file_name(rlog_file))
43 l.set_output_path(os.dir(rlog_file))
44}
45
46// set_output_label sets the `label` for the output.
47pub fn (mut l Log) set_output_label(label string) {
48 l.output_label = label
49}
50
51// set_output_path sets the file to which output is logged to.
52pub fn (mut l Log) set_output_path(output_file_path string) {
53 if l.ofile.is_opened {
54 l.ofile.close()
55 }
56 l.output_target = .file
57 l.output_file_name = os.join_path(os.real_path(output_file_path), l.output_label)
58 ofile := os.open_append(l.output_file_name) or {
59 panic('error while opening log file ${l.output_file_name} for appending')
60 }
61 l.ofile = ofile
62}
63
64// log_to_console_too turns on logging to the console too, in addition to logging to a file.
65// You have to call it *after* calling .set_output_path(output_file_path).
66pub fn (mut l Log) log_to_console_too() {
67 if l.output_target != .file {
68 panic('log_to_console_too should be called *after* .set_output_path')
69 }
70 l.output_target = .both
71}
72
73// flush writes the log file content to disk.
74pub fn (mut l Log) flush() {
75 l.ofile.flush()
76}
77
78// close closes the log file.
79pub fn (mut l Log) close() {
80 l.ofile.close()
81}
82
83// log_file writes log line `s` with `level` to the log file.
84fn (mut l Log) log_file(s string, level Level) {
85 timestamp := time.now().format_ss_micro()
86 e := tag_to_file(level)
87 l.ofile.writeln('${timestamp} [${e}] ${s}') or { panic(err) }
88}
89
90// log_cli writes log line `s` with `level` to stdout.
91fn (l &Log) log_cli(s string, level Level) {
92 timestamp := time.now().format_ss_micro()
93 e := tag_to_cli(level)
94 println('${timestamp} [${e}] ${s}')
95}
96
97// send_output writes log line `s` with `level` to either the log file or the console
98// according to the value of the `.output_target` field.
99pub fn (mut l Log) send_output(s &string, level Level) {
100 if l.output_target == .file || l.output_target == .both {
101 l.log_file(s, level)
102 }
103 if l.output_target == .console || l.output_target == .both {
104 l.log_cli(s, level)
105 }
106}
107
108// fatal logs line `s` via `send_output` if `Log.level` is greater than or equal to the `Level.fatal` category.
109// Note that this method performs a panic at the end, even if log level is not enabled.
110[noreturn]
111pub fn (mut l Log) fatal(s string) {
112 if int(l.level) >= int(Level.fatal) {
113 l.send_output(s, .fatal)
114 l.ofile.close()
115 }
116 panic('${l.output_label}: ${s}')
117}
118
119// error logs line `s` via `send_output` if `Log.level` is greater than or equal to the `Level.error` category.
120pub fn (mut l Log) error(s string) {
121 if int(l.level) < int(Level.error) {
122 return
123 }
124 l.send_output(s, .error)
125}
126
127// warn logs line `s` via `send_output` if `Log.level` is greater than or equal to the `Level.warn` category.
128pub fn (mut l Log) warn(s string) {
129 if int(l.level) < int(Level.warn) {
130 return
131 }
132 l.send_output(s, .warn)
133}
134
135// info logs line `s` via `send_output` if `Log.level` is greater than or equal to the `Level.info` category.
136pub fn (mut l Log) info(s string) {
137 if int(l.level) < int(Level.info) {
138 return
139 }
140 l.send_output(s, .info)
141}
142
143// debug logs line `s` via `send_output` if `Log.level` is greater than or equal to the `Level.debug` category.
144pub fn (mut l Log) debug(s string) {
145 if int(l.level) < int(Level.debug) {
146 return
147 }
148 l.send_output(s, .debug)
149}
150
151// free frees the given Log instance
152[unsafe]
153pub fn (mut f Log) free() {
154 unsafe {
155 f.output_label.free()
156 f.ofile.close()
157 f.output_file_name.free()
158 }
159}