mirror of https://github.com/k3s-io/k3s
Support dynamicly set logging verbosity
parent
e59ae29fbc
commit
73a22b2e61
|
@ -65,6 +65,7 @@ import (
|
|||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||
|
||||
// install apis
|
||||
"github.com/golang/glog"
|
||||
_ "k8s.io/apiserver/pkg/apis/apiserver/install"
|
||||
)
|
||||
|
||||
|
@ -575,6 +576,16 @@ func installAPI(s *GenericAPIServer, c *Config) {
|
|||
if c.EnableContentionProfiling {
|
||||
goruntime.SetBlockProfileRate(1)
|
||||
}
|
||||
// so far, only logging related endpoints are considered valid to add for these debug flags.
|
||||
routes.DebugFlags{}.Install(s.Handler.NonGoRestfulMux, "v", routes.StringFlagPutHandler(
|
||||
routes.StringFlagSetterFunc(func(val string) (string, error) {
|
||||
var level glog.Level
|
||||
if err := level.Set(val); err != nil {
|
||||
return "", fmt.Errorf("failed set glog.logging.verbosity %s: %v", val, err)
|
||||
}
|
||||
return "successfully set glog.logging.verbosity to " + val, nil
|
||||
}),
|
||||
))
|
||||
}
|
||||
if c.EnableMetrics {
|
||||
if c.EnableProfiling {
|
||||
|
@ -583,6 +594,7 @@ func installAPI(s *GenericAPIServer, c *Config) {
|
|||
routes.DefaultMetrics{}.Install(s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
}
|
||||
|
||||
routes.Version{Version: c.Version}.Install(s.Handler.GoRestfulContainer)
|
||||
|
||||
if c.EnableDiscovery {
|
||||
|
|
|
@ -385,6 +385,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) {
|
|||
{"/"},
|
||||
{"/swagger-ui/"},
|
||||
{"/debug/pprof/"},
|
||||
{"/debug/flags/"},
|
||||
{"/version"},
|
||||
} {
|
||||
resp := httptest.NewRecorder()
|
||||
|
|
|
@ -9,6 +9,7 @@ go_library(
|
|||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"flags.go",
|
||||
"index.go",
|
||||
"metrics.go",
|
||||
"openapi.go",
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apiserver/pkg/server/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
lock = &sync.RWMutex{}
|
||||
registeredFlags = map[string]debugFlag{}
|
||||
)
|
||||
|
||||
// DebugFlags adds handlers for flags under /debug/flags.
|
||||
type DebugFlags struct {
|
||||
}
|
||||
|
||||
// Install registers the APIServer's flags handler.
|
||||
func (f DebugFlags) Install(c *mux.PathRecorderMux, flag string, handler func(http.ResponseWriter, *http.Request)) {
|
||||
c.UnlistedHandle("/debug/flags", http.HandlerFunc(f.Index))
|
||||
c.UnlistedHandlePrefix("/debug/flags/", http.HandlerFunc(f.Index))
|
||||
|
||||
url := path.Join("/debug/flags", flag)
|
||||
c.UnlistedHandleFunc(url, handler)
|
||||
|
||||
f.addFlag(flag)
|
||||
}
|
||||
|
||||
// Index responds with the `/debug/flags` request.
|
||||
// For example, "/debug/flags/v" serves the "--v" flag.
|
||||
// Index responds to a request for "/debug/flags/" with an HTML page
|
||||
// listing the available flags.
|
||||
func (f DebugFlags) Index(w http.ResponseWriter, r *http.Request) {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
if err := indexTmpl.Execute(w, registeredFlags); err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
var indexTmpl = template.Must(template.New("index").Parse(`<html>
|
||||
<head>
|
||||
<title>/debug/flags/</title>
|
||||
</head>
|
||||
<body>
|
||||
/debug/flags/<br>
|
||||
<br>
|
||||
flags:<br>
|
||||
<table>
|
||||
{{range .}}
|
||||
<tr>{{.Flag}}<br>
|
||||
{{end}}
|
||||
</table>
|
||||
<br>
|
||||
full flags configurable<br>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
|
||||
type debugFlag struct {
|
||||
Flag string
|
||||
}
|
||||
|
||||
func (f DebugFlags) addFlag(flag string) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
registeredFlags[flag] = debugFlag{flag}
|
||||
}
|
||||
|
||||
// StringFlagSetterFunc is a func used for setting string type flag.
|
||||
type StringFlagSetterFunc func(string) (string, error)
|
||||
|
||||
// StringFlagPutHandler wraps an http Handler to set string type flag.
|
||||
func StringFlagPutHandler(setter StringFlagSetterFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
switch {
|
||||
case req.Method == "PUT":
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
writePlainText(http.StatusBadRequest, "error reading request body: "+err.Error(), w)
|
||||
return
|
||||
}
|
||||
defer req.Body.Close()
|
||||
response, err := setter(string(body))
|
||||
if err != nil {
|
||||
writePlainText(http.StatusBadRequest, err.Error(), w)
|
||||
return
|
||||
}
|
||||
writePlainText(http.StatusOK, response, w)
|
||||
return
|
||||
default:
|
||||
writePlainText(http.StatusNotAcceptable, "unsupported http method", w)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// writePlainText renders a simple string response.
|
||||
func writePlainText(statusCode int, text string, w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.WriteHeader(statusCode)
|
||||
fmt.Fprintln(w, text)
|
||||
}
|
Loading…
Reference in New Issue