logging.odin 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //+private
  2. package testing
  3. import "base:runtime"
  4. import "core:fmt"
  5. import pkg_log "core:log"
  6. import "core:strings"
  7. import "core:sync/chan"
  8. import "core:time"
  9. Default_Test_Logger_Opts :: runtime.Logger_Options {
  10. .Level,
  11. .Terminal_Color,
  12. .Short_File_Path,
  13. .Line,
  14. .Procedure,
  15. .Date, .Time,
  16. }
  17. Log_Message :: struct {
  18. level: runtime.Logger_Level,
  19. text: string,
  20. time: time.Time,
  21. // `text` may be allocated differently, depending on where a log message
  22. // originates from.
  23. allocator: runtime.Allocator,
  24. }
  25. test_logger_proc :: proc(logger_data: rawptr, level: runtime.Logger_Level, text: string, options: runtime.Logger_Options, location := #caller_location) {
  26. t := cast(^T)logger_data
  27. if level >= .Error {
  28. t.error_count += 1
  29. }
  30. cloned_text, clone_error := strings.clone(text, t._log_allocator)
  31. assert(clone_error == nil, "Error while cloning string in test thread logger proc.")
  32. now := time.now()
  33. chan.send(t.channel, Event_Log_Message {
  34. level = level,
  35. text = cloned_text,
  36. time = now,
  37. formatted_text = format_log_text(level, text, options, location, now, t._log_allocator),
  38. })
  39. }
  40. runner_logger_proc :: proc(logger_data: rawptr, level: runtime.Logger_Level, text: string, options: runtime.Logger_Options, location := #caller_location) {
  41. log_messages := cast(^[dynamic]Log_Message)logger_data
  42. now := time.now()
  43. append(log_messages, Log_Message {
  44. level = level,
  45. text = format_log_text(level, text, options, location, now),
  46. time = now,
  47. allocator = context.allocator,
  48. })
  49. }
  50. format_log_text :: proc(level: runtime.Logger_Level, text: string, options: runtime.Logger_Options, location: runtime.Source_Code_Location, at_time: time.Time, allocator := context.allocator) -> string{
  51. backing: [1024]byte
  52. buf := strings.builder_from_bytes(backing[:])
  53. pkg_log.do_level_header(options, &buf, level)
  54. pkg_log.do_time_header(options, &buf, at_time)
  55. pkg_log.do_location_header(options, &buf, location)
  56. return fmt.aprintf("%s%s", strings.to_string(buf), text, allocator = allocator)
  57. }