1// Copyright 2020 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
5package private
6
7import (
8	"fmt"
9	"net/http"
10
11	"code.gitea.io/gitea/modules/context"
12	"code.gitea.io/gitea/modules/graceful"
13	"code.gitea.io/gitea/modules/json"
14	"code.gitea.io/gitea/modules/log"
15	"code.gitea.io/gitea/modules/private"
16	"code.gitea.io/gitea/modules/queue"
17	"code.gitea.io/gitea/modules/setting"
18	"code.gitea.io/gitea/modules/web"
19)
20
21// FlushQueues flushes all the Queues
22func FlushQueues(ctx *context.PrivateContext) {
23	opts := web.GetForm(ctx).(*private.FlushOptions)
24	if opts.NonBlocking {
25		// Save the hammer ctx here - as a new one is created each time you call this.
26		baseCtx := graceful.GetManager().HammerContext()
27		go func() {
28			err := queue.GetManager().FlushAll(baseCtx, opts.Timeout)
29			if err != nil {
30				log.Error("Flushing request timed-out with error: %v", err)
31			}
32		}()
33		ctx.JSON(http.StatusAccepted, private.Response{
34			Err: "Flushing",
35		})
36		return
37	}
38	err := queue.GetManager().FlushAll(ctx, opts.Timeout)
39	if err != nil {
40		ctx.JSON(http.StatusRequestTimeout, private.Response{
41			Err: fmt.Sprintf("%v", err),
42		})
43	}
44	ctx.PlainText(http.StatusOK, "success")
45}
46
47// PauseLogging pauses logging
48func PauseLogging(ctx *context.PrivateContext) {
49	log.Pause()
50	ctx.PlainText(http.StatusOK, "success")
51}
52
53// ResumeLogging resumes logging
54func ResumeLogging(ctx *context.PrivateContext) {
55	log.Resume()
56	ctx.PlainText(http.StatusOK, "success")
57}
58
59// ReleaseReopenLogging releases and reopens logging files
60func ReleaseReopenLogging(ctx *context.PrivateContext) {
61	if err := log.ReleaseReopen(); err != nil {
62		ctx.JSON(http.StatusInternalServerError, private.Response{
63			Err: fmt.Sprintf("Error during release and reopen: %v", err),
64		})
65		return
66	}
67	ctx.PlainText(http.StatusOK, "success")
68}
69
70// RemoveLogger removes a logger
71func RemoveLogger(ctx *context.PrivateContext) {
72	group := ctx.Params("group")
73	name := ctx.Params("name")
74	ok, err := log.GetLogger(group).DelLogger(name)
75	if err != nil {
76		ctx.JSON(http.StatusInternalServerError, private.Response{
77			Err: fmt.Sprintf("Failed to remove logger: %s %s %v", group, name, err),
78		})
79		return
80	}
81	if ok {
82		setting.RemoveSubLogDescription(group, name)
83	}
84	ctx.PlainText(http.StatusOK, fmt.Sprintf("Removed %s %s", group, name))
85}
86
87// AddLogger adds a logger
88func AddLogger(ctx *context.PrivateContext) {
89	opts := web.GetForm(ctx).(*private.LoggerOptions)
90	if len(opts.Group) == 0 {
91		opts.Group = log.DEFAULT
92	}
93	if _, ok := opts.Config["flags"]; !ok {
94		switch opts.Group {
95		case "access":
96			opts.Config["flags"] = log.FlagsFromString("")
97		case "router":
98			opts.Config["flags"] = log.FlagsFromString("date,time")
99		default:
100			opts.Config["flags"] = log.FlagsFromString("stdflags")
101		}
102	}
103
104	if _, ok := opts.Config["colorize"]; !ok && opts.Mode == "console" {
105		if _, ok := opts.Config["stderr"]; ok {
106			opts.Config["colorize"] = log.CanColorStderr
107		} else {
108			opts.Config["colorize"] = log.CanColorStdout
109		}
110	}
111
112	if _, ok := opts.Config["level"]; !ok {
113		opts.Config["level"] = setting.LogLevel
114	}
115
116	if _, ok := opts.Config["stacktraceLevel"]; !ok {
117		opts.Config["stacktraceLevel"] = setting.StacktraceLogLevel
118	}
119
120	if opts.Mode == "file" {
121		if _, ok := opts.Config["maxsize"]; !ok {
122			opts.Config["maxsize"] = 1 << 28
123		}
124		if _, ok := opts.Config["maxdays"]; !ok {
125			opts.Config["maxdays"] = 7
126		}
127		if _, ok := opts.Config["compressionLevel"]; !ok {
128			opts.Config["compressionLevel"] = -1
129		}
130	}
131
132	bufferLen := setting.Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000)
133	byteConfig, err := json.Marshal(opts.Config)
134	if err != nil {
135		log.Error("Failed to marshal log configuration: %v %v", opts.Config, err)
136		ctx.JSON(http.StatusInternalServerError, private.Response{
137			Err: fmt.Sprintf("Failed to marshal log configuration: %v %v", opts.Config, err),
138		})
139		return
140	}
141	config := string(byteConfig)
142
143	if err := log.NewNamedLogger(opts.Group, bufferLen, opts.Name, opts.Mode, config); err != nil {
144		log.Error("Failed to create new named logger: %s %v", config, err)
145		ctx.JSON(http.StatusInternalServerError, private.Response{
146			Err: fmt.Sprintf("Failed to create new named logger: %s %v", config, err),
147		})
148		return
149	}
150
151	setting.AddSubLogDescription(opts.Group, setting.SubLogDescription{
152		Name:     opts.Name,
153		Provider: opts.Mode,
154		Config:   config,
155	})
156
157	ctx.PlainText(http.StatusOK, "success")
158}
159