You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package log
  4. import (
  5. "sort"
  6. "strings"
  7. "code.gitea.io/gitea/modules/json"
  8. )
  9. // These flags define which text to prefix to each log entry generated
  10. // by the Logger. Bits are or'ed together to control what's printed.
  11. // There is no control over the order they appear (the order listed
  12. // here) or the format they present (as described in the comments).
  13. // The prefix is followed by a colon only if more than time is stated
  14. // is specified. For example, flags Ldate | Ltime
  15. // produce, 2009/01/23 01:23:23 message.
  16. // The standard is:
  17. // 2009/01/23 01:23:23 ...a/logger/c/d.go:23:runtime.Caller() [I]: message
  18. const (
  19. Ldate uint32 = 1 << iota // the date in the local time zone: 2009/01/23
  20. Ltime // the time in the local time zone: 01:23:23
  21. Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
  22. Llongfile // full file name and line number: /a/logger/c/d.go:23
  23. Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
  24. Lfuncname // function name of the caller: runtime.Caller()
  25. Lshortfuncname // last part of the function name
  26. LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
  27. Llevelinitial // Initial character of the provided level in brackets, eg. [I] for info
  28. Llevel // Provided level in brackets [INFO]
  29. Lgopid // the Goroutine-PID of the context
  30. Lmedfile = Lshortfile | Llongfile // last 20 characters of the filename
  31. LstdFlags = Ldate | Ltime | Lmedfile | Lshortfuncname | Llevelinitial // default
  32. )
  33. const Ldefault = LstdFlags
  34. type Flags struct {
  35. defined bool
  36. flags uint32
  37. }
  38. var flagFromString = map[string]uint32{
  39. "date": Ldate,
  40. "time": Ltime,
  41. "microseconds": Lmicroseconds,
  42. "longfile": Llongfile,
  43. "shortfile": Lshortfile,
  44. "funcname": Lfuncname,
  45. "shortfuncname": Lshortfuncname,
  46. "utc": LUTC,
  47. "levelinitial": Llevelinitial,
  48. "level": Llevel,
  49. "gopid": Lgopid,
  50. "medfile": Lmedfile,
  51. "stdflags": LstdFlags,
  52. }
  53. var flagComboToString = []struct {
  54. flag uint32
  55. name string
  56. }{
  57. // name with more bits comes first
  58. {LstdFlags, "stdflags"},
  59. {Lmedfile, "medfile"},
  60. {Ldate, "date"},
  61. {Ltime, "time"},
  62. {Lmicroseconds, "microseconds"},
  63. {Llongfile, "longfile"},
  64. {Lshortfile, "shortfile"},
  65. {Lfuncname, "funcname"},
  66. {Lshortfuncname, "shortfuncname"},
  67. {LUTC, "utc"},
  68. {Llevelinitial, "levelinitial"},
  69. {Llevel, "level"},
  70. {Lgopid, "gopid"},
  71. }
  72. func (f Flags) Bits() uint32 {
  73. if !f.defined {
  74. return Ldefault
  75. }
  76. return f.flags
  77. }
  78. func (f Flags) String() string {
  79. flags := f.Bits()
  80. var flagNames []string
  81. for _, it := range flagComboToString {
  82. if flags&it.flag == it.flag {
  83. flags &^= it.flag
  84. flagNames = append(flagNames, it.name)
  85. }
  86. }
  87. if len(flagNames) == 0 {
  88. return "none"
  89. }
  90. sort.Strings(flagNames)
  91. return strings.Join(flagNames, ",")
  92. }
  93. func (f *Flags) UnmarshalJSON(bytes []byte) error {
  94. var s string
  95. if err := json.Unmarshal(bytes, &s); err != nil {
  96. return err
  97. }
  98. *f = FlagsFromString(s)
  99. return nil
  100. }
  101. func (f Flags) MarshalJSON() ([]byte, error) {
  102. return []byte(`"` + f.String() + `"`), nil
  103. }
  104. func FlagsFromString(from string, def ...uint32) Flags {
  105. from = strings.TrimSpace(from)
  106. if from == "" && len(def) > 0 {
  107. return Flags{defined: true, flags: def[0]}
  108. }
  109. flags := uint32(0)
  110. for _, flag := range strings.Split(strings.ToLower(from), ",") {
  111. flags |= flagFromString[strings.TrimSpace(flag)]
  112. }
  113. return Flags{defined: true, flags: flags}
  114. }
  115. func FlagsFromBits(flags uint32) Flags {
  116. return Flags{defined: true, flags: flags}
  117. }