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.9KB

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