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.

manager_logging.go 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package cmd
  5. import (
  6. "fmt"
  7. "net/http"
  8. "os"
  9. "code.gitea.io/gitea/modules/log"
  10. "code.gitea.io/gitea/modules/private"
  11. "github.com/urfave/cli"
  12. )
  13. var (
  14. defaultLoggingFlags = []cli.Flag{
  15. cli.StringFlag{
  16. Name: "group, g",
  17. Usage: "Group to add logger to - will default to \"default\"",
  18. }, cli.StringFlag{
  19. Name: "name, n",
  20. Usage: "Name of the new logger - will default to mode",
  21. }, cli.StringFlag{
  22. Name: "level, l",
  23. Usage: "Logging level for the new logger",
  24. }, cli.StringFlag{
  25. Name: "stacktrace-level, L",
  26. Usage: "Stacktrace logging level",
  27. }, cli.StringFlag{
  28. Name: "flags, F",
  29. Usage: "Flags for the logger",
  30. }, cli.StringFlag{
  31. Name: "expression, e",
  32. Usage: "Matching expression for the logger",
  33. }, cli.StringFlag{
  34. Name: "prefix, p",
  35. Usage: "Prefix for the logger",
  36. }, cli.BoolFlag{
  37. Name: "color",
  38. Usage: "Use color in the logs",
  39. }, cli.BoolFlag{
  40. Name: "debug",
  41. },
  42. }
  43. subcmdLogging = cli.Command{
  44. Name: "logging",
  45. Usage: "Adjust logging commands",
  46. Subcommands: []cli.Command{
  47. {
  48. Name: "pause",
  49. Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
  50. Flags: []cli.Flag{
  51. cli.BoolFlag{
  52. Name: "debug",
  53. },
  54. },
  55. Action: runPauseLogging,
  56. }, {
  57. Name: "resume",
  58. Usage: "Resume logging",
  59. Flags: []cli.Flag{
  60. cli.BoolFlag{
  61. Name: "debug",
  62. },
  63. },
  64. Action: runResumeLogging,
  65. }, {
  66. Name: "release-and-reopen",
  67. Usage: "Cause Gitea to release and re-open files used for logging",
  68. Flags: []cli.Flag{
  69. cli.BoolFlag{
  70. Name: "debug",
  71. },
  72. },
  73. Action: runReleaseReopenLogging,
  74. }, {
  75. Name: "remove",
  76. Usage: "Remove a logger",
  77. ArgsUsage: "[name] Name of logger to remove",
  78. Flags: []cli.Flag{
  79. cli.BoolFlag{
  80. Name: "debug",
  81. }, cli.StringFlag{
  82. Name: "group, g",
  83. Usage: "Group to add logger to - will default to \"default\"",
  84. },
  85. },
  86. Action: runRemoveLogger,
  87. }, {
  88. Name: "add",
  89. Usage: "Add a logger",
  90. Subcommands: []cli.Command{
  91. {
  92. Name: "console",
  93. Usage: "Add a console logger",
  94. Flags: append(defaultLoggingFlags,
  95. cli.BoolFlag{
  96. Name: "stderr",
  97. Usage: "Output console logs to stderr - only relevant for console",
  98. }),
  99. Action: runAddConsoleLogger,
  100. }, {
  101. Name: "file",
  102. Usage: "Add a file logger",
  103. Flags: append(defaultLoggingFlags, []cli.Flag{
  104. cli.StringFlag{
  105. Name: "filename, f",
  106. Usage: "Filename for the logger - this must be set.",
  107. }, cli.BoolTFlag{
  108. Name: "rotate, r",
  109. Usage: "Rotate logs",
  110. }, cli.Int64Flag{
  111. Name: "max-size, s",
  112. Usage: "Maximum size in bytes before rotation",
  113. }, cli.BoolTFlag{
  114. Name: "daily, d",
  115. Usage: "Rotate logs daily",
  116. }, cli.IntFlag{
  117. Name: "max-days, D",
  118. Usage: "Maximum number of daily logs to keep",
  119. }, cli.BoolTFlag{
  120. Name: "compress, z",
  121. Usage: "Compress rotated logs",
  122. }, cli.IntFlag{
  123. Name: "compression-level, Z",
  124. Usage: "Compression level to use",
  125. },
  126. }...),
  127. Action: runAddFileLogger,
  128. }, {
  129. Name: "conn",
  130. Usage: "Add a net conn logger",
  131. Flags: append(defaultLoggingFlags, []cli.Flag{
  132. cli.BoolFlag{
  133. Name: "reconnect-on-message, R",
  134. Usage: "Reconnect to host for every message",
  135. }, cli.BoolFlag{
  136. Name: "reconnect, r",
  137. Usage: "Reconnect to host when connection is dropped",
  138. }, cli.StringFlag{
  139. Name: "protocol, P",
  140. Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)",
  141. }, cli.StringFlag{
  142. Name: "address, a",
  143. Usage: "Host address and port to connect to (defaults to :7020)",
  144. },
  145. }...),
  146. Action: runAddConnLogger,
  147. }, {
  148. Name: "smtp",
  149. Usage: "Add an SMTP logger",
  150. Flags: append(defaultLoggingFlags, []cli.Flag{
  151. cli.StringFlag{
  152. Name: "username, u",
  153. Usage: "Mail server username",
  154. }, cli.StringFlag{
  155. Name: "password, P",
  156. Usage: "Mail server password",
  157. }, cli.StringFlag{
  158. Name: "host, H",
  159. Usage: "Mail server host (defaults to: 127.0.0.1:25)",
  160. }, cli.StringSliceFlag{
  161. Name: "send-to, s",
  162. Usage: "Email address(es) to send to",
  163. }, cli.StringFlag{
  164. Name: "subject, S",
  165. Usage: "Subject header of sent emails",
  166. },
  167. }...),
  168. Action: runAddSMTPLogger,
  169. },
  170. },
  171. },
  172. },
  173. }
  174. )
  175. func runRemoveLogger(c *cli.Context) error {
  176. setup("manager", c.Bool("debug"))
  177. group := c.String("group")
  178. if len(group) == 0 {
  179. group = log.DEFAULT
  180. }
  181. name := c.Args().First()
  182. ctx, cancel := installSignals()
  183. defer cancel()
  184. statusCode, msg := private.RemoveLogger(ctx, group, name)
  185. switch statusCode {
  186. case http.StatusInternalServerError:
  187. return fail("InternalServerError", msg)
  188. }
  189. fmt.Fprintln(os.Stdout, msg)
  190. return nil
  191. }
  192. func runAddSMTPLogger(c *cli.Context) error {
  193. setup("manager", c.Bool("debug"))
  194. vals := map[string]interface{}{}
  195. mode := "smtp"
  196. if c.IsSet("host") {
  197. vals["host"] = c.String("host")
  198. } else {
  199. vals["host"] = "127.0.0.1:25"
  200. }
  201. if c.IsSet("username") {
  202. vals["username"] = c.String("username")
  203. }
  204. if c.IsSet("password") {
  205. vals["password"] = c.String("password")
  206. }
  207. if !c.IsSet("send-to") {
  208. return fmt.Errorf("Some recipients must be provided")
  209. }
  210. vals["sendTos"] = c.StringSlice("send-to")
  211. if c.IsSet("subject") {
  212. vals["subject"] = c.String("subject")
  213. } else {
  214. vals["subject"] = "Diagnostic message from Gitea"
  215. }
  216. return commonAddLogger(c, mode, vals)
  217. }
  218. func runAddConnLogger(c *cli.Context) error {
  219. setup("manager", c.Bool("debug"))
  220. vals := map[string]interface{}{}
  221. mode := "conn"
  222. vals["net"] = "tcp"
  223. if c.IsSet("protocol") {
  224. switch c.String("protocol") {
  225. case "udp":
  226. vals["net"] = "udp"
  227. case "unix":
  228. vals["net"] = "unix"
  229. }
  230. }
  231. if c.IsSet("address") {
  232. vals["address"] = c.String("address")
  233. } else {
  234. vals["address"] = ":7020"
  235. }
  236. if c.IsSet("reconnect") {
  237. vals["reconnect"] = c.Bool("reconnect")
  238. }
  239. if c.IsSet("reconnect-on-message") {
  240. vals["reconnectOnMsg"] = c.Bool("reconnect-on-message")
  241. }
  242. return commonAddLogger(c, mode, vals)
  243. }
  244. func runAddFileLogger(c *cli.Context) error {
  245. setup("manager", c.Bool("debug"))
  246. vals := map[string]interface{}{}
  247. mode := "file"
  248. if c.IsSet("filename") {
  249. vals["filename"] = c.String("filename")
  250. } else {
  251. return fmt.Errorf("filename must be set when creating a file logger")
  252. }
  253. if c.IsSet("rotate") {
  254. vals["rotate"] = c.Bool("rotate")
  255. }
  256. if c.IsSet("max-size") {
  257. vals["maxsize"] = c.Int64("max-size")
  258. }
  259. if c.IsSet("daily") {
  260. vals["daily"] = c.Bool("daily")
  261. }
  262. if c.IsSet("max-days") {
  263. vals["maxdays"] = c.Int("max-days")
  264. }
  265. if c.IsSet("compress") {
  266. vals["compress"] = c.Bool("compress")
  267. }
  268. if c.IsSet("compression-level") {
  269. vals["compressionLevel"] = c.Int("compression-level")
  270. }
  271. return commonAddLogger(c, mode, vals)
  272. }
  273. func runAddConsoleLogger(c *cli.Context) error {
  274. setup("manager", c.Bool("debug"))
  275. vals := map[string]interface{}{}
  276. mode := "console"
  277. if c.IsSet("stderr") && c.Bool("stderr") {
  278. vals["stderr"] = c.Bool("stderr")
  279. }
  280. return commonAddLogger(c, mode, vals)
  281. }
  282. func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
  283. if len(c.String("level")) > 0 {
  284. vals["level"] = log.FromString(c.String("level")).String()
  285. }
  286. if len(c.String("stacktrace-level")) > 0 {
  287. vals["stacktraceLevel"] = log.FromString(c.String("stacktrace-level")).String()
  288. }
  289. if len(c.String("expression")) > 0 {
  290. vals["expression"] = c.String("expression")
  291. }
  292. if len(c.String("prefix")) > 0 {
  293. vals["prefix"] = c.String("prefix")
  294. }
  295. if len(c.String("flags")) > 0 {
  296. vals["flags"] = log.FlagsFromString(c.String("flags"))
  297. }
  298. if c.IsSet("color") {
  299. vals["colorize"] = c.Bool("color")
  300. }
  301. group := "default"
  302. if c.IsSet("group") {
  303. group = c.String("group")
  304. }
  305. name := mode
  306. if c.IsSet("name") {
  307. name = c.String("name")
  308. }
  309. ctx, cancel := installSignals()
  310. defer cancel()
  311. statusCode, msg := private.AddLogger(ctx, group, name, mode, vals)
  312. switch statusCode {
  313. case http.StatusInternalServerError:
  314. return fail("InternalServerError", msg)
  315. }
  316. fmt.Fprintln(os.Stdout, msg)
  317. return nil
  318. }
  319. func runPauseLogging(c *cli.Context) error {
  320. ctx, cancel := installSignals()
  321. defer cancel()
  322. setup("manager", c.Bool("debug"))
  323. statusCode, msg := private.PauseLogging(ctx)
  324. switch statusCode {
  325. case http.StatusInternalServerError:
  326. return fail("InternalServerError", msg)
  327. }
  328. fmt.Fprintln(os.Stdout, msg)
  329. return nil
  330. }
  331. func runResumeLogging(c *cli.Context) error {
  332. ctx, cancel := installSignals()
  333. defer cancel()
  334. setup("manager", c.Bool("debug"))
  335. statusCode, msg := private.ResumeLogging(ctx)
  336. switch statusCode {
  337. case http.StatusInternalServerError:
  338. return fail("InternalServerError", msg)
  339. }
  340. fmt.Fprintln(os.Stdout, msg)
  341. return nil
  342. }
  343. func runReleaseReopenLogging(c *cli.Context) error {
  344. ctx, cancel := installSignals()
  345. defer cancel()
  346. setup("manager", c.Bool("debug"))
  347. statusCode, msg := private.ReleaseReopenLogging(ctx)
  348. switch statusCode {
  349. case http.StatusInternalServerError:
  350. return fail("InternalServerError", msg)
  351. }
  352. fmt.Fprintln(os.Stdout, msg)
  353. return nil
  354. }