logger.ha 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. use os;
  2. use io;
  3. use fmt;
  4. use ascii;
  5. use bufio;
  6. export type Level = enum u8 {
  7. NONE,
  8. CRITICAL,
  9. ERROR,
  10. WARNING,
  11. INFO,
  12. DEBUG,
  13. };
  14. export fn level2str(l: Level) str =
  15. switch (l) {
  16. case Level::NONE => yield "NONE";
  17. case Level::CRITICAL => yield "CRITICAL";
  18. case Level::ERROR => yield "ERROR";
  19. case Level::WARNING => yield "WARNING";
  20. case Level::INFO => yield "INFO";
  21. case Level::DEBUG => yield "DEBUG";
  22. };
  23. export type InvalidLevel = !str;
  24. export type LevelStringTooLong = !size;
  25. export type LevelError = !(InvalidLevel | LevelStringTooLong);
  26. export fn str2level(l: str) (Level | !LevelError) = {
  27. static let buf: [64]u8 = [0...];
  28. static const max_level_len: size = 16;
  29. const actual_len = len(l);
  30. if (actual_len > max_level_len) return actual_len: !LevelStringTooLong;
  31. return switch (ascii::strupper_buf(l, buf[..0])) {
  32. case "NONE" => yield Level::NONE;
  33. case "CRITICAL" => yield Level::CRITICAL;
  34. case "ERROR" => yield Level::ERROR;
  35. case "WARNING" => yield Level::WARNING;
  36. case "INFO" => yield Level::INFO;
  37. case "DEBUG" => yield Level::DEBUG;
  38. case => return l: !InvalidLevel;
  39. };
  40. };
  41. export type Logger = struct {
  42. name: str,
  43. level: Level,
  44. handle: io::handle,
  45. };
  46. export fn new(name: str, level: Level, handle: io::handle) Logger =
  47. Logger {
  48. name = name,
  49. level = level,
  50. handle = handle,
  51. };
  52. export fn log(level: Level, l: Logger, fmt: str, args: fmt::field...) void =
  53. if (level <= l.level && level > Level::NONE) {
  54. static let buf: [os::BUFSZ]u8 = [0...];
  55. const handle: io::handle = &bufio::init(l.handle, [], buf);
  56. defer io::close(handle)!;
  57. fmt::fprintf(handle, "{}: {}: ", l.name, level2str(level))!;
  58. fmt::fprintf(handle, fmt, args...)!;
  59. fmt::fprintln(handle)!;
  60. };
  61. export fn critical(l: Logger, fmt: str, args: fmt::field...) void =
  62. log(Level::CRITICAL, l, fmt, args...);
  63. export fn error(l: Logger, fmt: str, args: fmt::field...) void =
  64. log(Level::ERROR, l, fmt, args...);
  65. export fn warning(l: Logger, fmt: str, args: fmt::field...) void =
  66. log(Level::WARNING, l, fmt, args...);
  67. export fn warn(l: Logger, fmt: str, args: fmt::field...) void =
  68. warning(l, fmt, args...);
  69. export fn info(l: Logger, fmt: str, args: fmt::field...) void =
  70. log(Level::INFO, l, fmt, args...);
  71. export fn debug(l: Logger, fmt: str, args: fmt::field...) void =
  72. log(Level::DEBUG, l, fmt, args...);