Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add log level API #444

Merged
merged 4 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions cli/loglevel/loglevel.go
Original file line number Diff line number Diff line change
@@ -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
}
14 changes: 11 additions & 3 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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")
}
}
32 changes: 32 additions & 0 deletions server/api/z.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
}
7 changes: 7 additions & 0 deletions server/router/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions woodpecker-go/woodpecker/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
pathBuildQueue = "%s/api/builds"
pathQueue = "%s/api/queue"
pathVersion = "%s/version"
pathLogLevel = "%s/api/log-level"
)

type client struct {
Expand Down Expand Up @@ -355,13 +356,30 @@ 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)
err := c.get(uri, out)
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
//
Expand Down
47 changes: 47 additions & 0 deletions woodpecker-go/woodpecker/client_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package woodpecker

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
)

Expand Down Expand Up @@ -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()
}
}
10 changes: 9 additions & 1 deletion woodpecker-go/woodpecker/interface.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package woodpecker

import "net/http"
import (
"net/http"
)

// Client is used to communicate with a Drone server.
type Client interface {
Expand Down Expand Up @@ -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)
}
5 changes: 5 additions & 0 deletions woodpecker-go/woodpecker/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
)