log.odin 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package log
  2. import "core:runtime"
  3. import "core:fmt"
  4. // NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle.
  5. Level :: runtime.Logger_Level;
  6. /*
  7. Logger_Level :: enum {
  8. Debug = 0,
  9. Info = 10,
  10. Warning = 20,
  11. Error = 30,
  12. Fatal = 40,
  13. }
  14. */
  15. Option :: runtime.Logger_Option;
  16. /*
  17. Option :: enum {
  18. Level,
  19. Date,
  20. Time,
  21. Short_File_Path,
  22. Long_File_Path,
  23. Line,
  24. Procedure,
  25. Terminal_Color
  26. }
  27. */
  28. Options :: runtime.Logger_Options;
  29. /*
  30. Options :: bit_set[Option];
  31. */
  32. Full_Timestamp_Opts :: Options{
  33. .Date,
  34. .Time,
  35. };
  36. Location_Header_Opts :: Options{
  37. .Short_File_Path,
  38. .Long_File_Path,
  39. .Line,
  40. .Procedure,
  41. };
  42. Location_File_Opts :: Options{
  43. .Short_File_Path,
  44. .Long_File_Path,
  45. };
  46. Logger_Proc :: runtime.Logger_Proc;
  47. /*
  48. Logger_Proc :: #type proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location);
  49. */
  50. Logger :: runtime.Logger;
  51. /*
  52. Logger :: struct {
  53. procedure: Logger_Proc,
  54. data: rawptr,
  55. lowest_level: Level,
  56. options: Logger_Options,
  57. }
  58. */
  59. nil_logger_proc :: proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location) {
  60. // Do nothing
  61. }
  62. nil_logger :: proc() -> Logger {
  63. return Logger{nil_logger_proc, nil, Level.Debug, nil};
  64. }
  65. // TODO(bill): Should these be redesigned so that they are do not rely upon `package fmt`?
  66. debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
  67. logf(level=.Debug, fmt_str=fmt_str, args=args, location=location);
  68. }
  69. infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {
  70. logf(level=.Info, fmt_str=fmt_str, args=args, location=location);
  71. }
  72. warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
  73. logf(level=.Warning, fmt_str=fmt_str, args=args, location=location);
  74. }
  75. errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
  76. logf(level=.Error, fmt_str=fmt_str, args=args, location=location);
  77. }
  78. fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
  79. logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location);
  80. }
  81. debug :: proc(args: ..any, sep := " ", location := #caller_location) {
  82. log(level=.Debug, args=args, sep=sep, location=location);
  83. }
  84. info :: proc(args: ..any, sep := " ", location := #caller_location) {
  85. log(level=.Info, args=args, sep=sep, location=location);
  86. }
  87. warn :: proc(args: ..any, sep := " ", location := #caller_location) {
  88. log(level=.Warning, args=args, sep=sep, location=location);
  89. }
  90. error :: proc(args: ..any, sep := " ", location := #caller_location) {
  91. log(level=.Error, args=args, sep=sep, location=location);
  92. }
  93. fatal :: proc(args: ..any, sep := " ", location := #caller_location) {
  94. log(level=.Fatal, args=args, sep=sep, location=location);
  95. }
  96. panic :: proc(args: ..any, location := #caller_location) -> ! {
  97. log(level=.Fatal, args=args, location=location);
  98. runtime.panic("log.panic", location);
  99. }
  100. panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {
  101. logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location);
  102. runtime.panic("log.panicf", location);
  103. }
  104. log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location) {
  105. logger := context.logger;
  106. if logger.procedure == nil {
  107. return;
  108. }
  109. if level < logger.lowest_level {
  110. return;
  111. }
  112. str := fmt.tprint(args=args, sep=sep); //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
  113. logger.procedure(logger.data, level, str, logger.options, location);
  114. }
  115. logf :: proc(level: Level, fmt_str: string, args: ..any, location := #caller_location) {
  116. logger := context.logger;
  117. if logger.procedure == nil {
  118. return;
  119. }
  120. if level < logger.lowest_level {
  121. return;
  122. }
  123. str := fmt.tprintf(fmt_str, ..args);
  124. logger.procedure(logger.data, level, str, logger.options, location);
  125. }