mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-01 21:28:44 +00:00
Add log level API (#444)
* Add log level API Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update cli/loglevel/loglevel.go Co-authored-by: Anbraten <anton@ju60.de> * Move API to api routes Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: Anbraten <anton@ju60.de>
This commit is contained in:
parent
03bb0e69d8
commit
8e658c135d
8 changed files with 174 additions and 4 deletions
cli/loglevel
cmd/cli
server
woodpecker-go/woodpecker
45
cli/loglevel/loglevel.go
Normal file
45
cli/loglevel/loglevel.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package loglevel
|
||||
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/cli/internal"
|
||||
"github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker"
|
||||
)
|
||||
|
||||
// Command exports the log-level command used to change the servers log-level.
|
||||
var Command = cli.Command{
|
||||
Name: "log-level",
|
||||
ArgsUsage: "[level]",
|
||||
Usage: "get the logging level of the server, or set it with [level]",
|
||||
Action: logLevel,
|
||||
}
|
||||
|
||||
func logLevel(c *cli.Context) error {
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var ll *woodpecker.LogLevel
|
||||
arg := c.Args().First()
|
||||
if arg != "" {
|
||||
lvl, err := zerolog.ParseLevel(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ll, err = client.SetLogLevel(&woodpecker.LogLevel{
|
||||
Level: lvl.String(),
|
||||
})
|
||||
} else {
|
||||
ll, err = client.LogLevel()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Msgf("Logging level: %s", ll.Level)
|
||||
return nil
|
||||
}
|
|
@ -15,10 +15,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/rs/zerolog"
|
||||
zlog "github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/cli/build"
|
||||
|
@ -27,6 +28,7 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/cli/info"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/lint"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/log"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/loglevel"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/registry"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/repo"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/secret"
|
||||
|
@ -84,10 +86,16 @@ func main() {
|
|||
repo.Command,
|
||||
user.Command,
|
||||
lint.Command,
|
||||
loglevel.Command,
|
||||
}
|
||||
|
||||
zlog.Logger = zlog.Output(
|
||||
zerolog.ConsoleWriter{
|
||||
Out: os.Stderr,
|
||||
},
|
||||
)
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
zlog.Fatal().Err(err).Msg("error running cli")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/server/store"
|
||||
"github.com/woodpecker-ci/woodpecker/version"
|
||||
|
@ -37,3 +41,31 @@ func Version(c *gin.Context) {
|
|||
"version": version.String(),
|
||||
})
|
||||
}
|
||||
|
||||
// LogLevel endpoint returns the current logging level
|
||||
func LogLevel(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"log-level": zerolog.GlobalLevel().String(),
|
||||
})
|
||||
}
|
||||
|
||||
// SetLogLevel endpoint allows setting the logging level via API
|
||||
func SetLogLevel(c *gin.Context) {
|
||||
logLevel := struct {
|
||||
LogLevel string `json:"log-level"`
|
||||
}{}
|
||||
if err := c.Bind(&logLevel); err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
lvl, err := zerolog.ParseLevel(logLevel.LogLevel)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Log().Msgf("log level set to %s", lvl.String())
|
||||
zerolog.SetGlobalLevel(lvl)
|
||||
c.JSON(200, logLevel)
|
||||
}
|
||||
|
|
|
@ -135,6 +135,13 @@ func apiRoutes(e *gin.Engine) {
|
|||
debugger.GET("/pprof/trace", debug.TraceHandler())
|
||||
}
|
||||
|
||||
logLevel := e.Group("/api/log-level")
|
||||
{
|
||||
logLevel.Use(session.MustAdmin())
|
||||
logLevel.GET("", api.LogLevel)
|
||||
logLevel.POST("", api.SetLogLevel)
|
||||
}
|
||||
|
||||
// TODO: remove /hook in favor of /api/hook
|
||||
e.POST("/hook", api.PostHook)
|
||||
e.POST("/api/hook", api.PostHook)
|
||||
|
|
|
@ -37,6 +37,7 @@ const (
|
|||
pathBuildQueue = "%s/api/builds"
|
||||
pathQueue = "%s/api/queue"
|
||||
pathVersion = "%s/version"
|
||||
pathLogLevel = "%s/api/log-level"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
|
@ -355,6 +356,7 @@ func (c *client) SecretDelete(owner, name, secret string) error {
|
|||
return c.delete(uri)
|
||||
}
|
||||
|
||||
// QueueInfo returns queue info
|
||||
func (c *client) QueueInfo() (*Info, error) {
|
||||
out := new(Info)
|
||||
uri := fmt.Sprintf(pathQueue+"/info", c.addr)
|
||||
|
@ -362,6 +364,22 @@ func (c *client) QueueInfo() (*Info, error) {
|
|||
return out, err
|
||||
}
|
||||
|
||||
// LogLevel returns the current logging level
|
||||
func (c *client) LogLevel() (*LogLevel, error) {
|
||||
out := new(LogLevel)
|
||||
uri := fmt.Sprintf(pathLogLevel, c.addr)
|
||||
err := c.get(uri, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// SetLogLevel sets the logging level of the server
|
||||
func (c *client) SetLogLevel(in *LogLevel) (*LogLevel, error) {
|
||||
out := new(LogLevel)
|
||||
uri := fmt.Sprintf(pathLogLevel, c.addr)
|
||||
err := c.post(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
//
|
||||
// http request helper functions
|
||||
//
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package woodpecker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -45,3 +47,48 @@ func Test_QueueInfo(t *testing.T) {
|
|||
t.Errorf("Unexpected worker count: %v, %v", info, err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_LogLevel(t *testing.T) {
|
||||
logLevel := "warn"
|
||||
fixtureHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
var ll LogLevel
|
||||
if err := json.NewDecoder(r.Body).Decode(&ll); err != nil {
|
||||
t.Logf("could not decode json: %v\n", err)
|
||||
t.FailNow()
|
||||
}
|
||||
logLevel = ll.Level
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `{
|
||||
"log-level": "%s"
|
||||
}`, logLevel)
|
||||
}
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(fixtureHandler))
|
||||
defer ts.Close()
|
||||
|
||||
client := NewClient(ts.URL, http.DefaultClient)
|
||||
|
||||
curLvl, err := client.LogLevel()
|
||||
if err != nil {
|
||||
t.Logf("could not get current log level: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !strings.EqualFold(curLvl.Level, logLevel) {
|
||||
t.Logf("log level is not correct\n\tExpected: %s\n\t Got: %s\n", logLevel, curLvl.Level)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
newLvl, err := client.SetLogLevel(&LogLevel{Level: "trace"})
|
||||
if err != nil {
|
||||
t.Logf("could not set log level: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !strings.EqualFold(newLvl.Level, logLevel) {
|
||||
t.Logf("log level is not correct\n\tExpected: %s\n\t Got: %s\n", logLevel, newLvl.Level)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package woodpecker
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Client is used to communicate with a Drone server.
|
||||
type Client interface {
|
||||
|
@ -125,4 +127,10 @@ type Client interface {
|
|||
|
||||
// QueueInfo returns the queue state.
|
||||
QueueInfo() (*Info, error)
|
||||
|
||||
// LogLevel returns the current logging level
|
||||
LogLevel() (*LogLevel, error)
|
||||
|
||||
// SetLogLevel sets the server's logging level
|
||||
SetLogLevel(logLevel *LogLevel) (*LogLevel, error)
|
||||
}
|
||||
|
|
|
@ -152,4 +152,9 @@ type (
|
|||
} `json:"stats"`
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
}
|
||||
|
||||
// LogLevel is for checking/setting logging level
|
||||
LogLevel struct {
|
||||
Level string `json:"log-level"`
|
||||
}
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue