mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Merge pull request #83237 from jfbai/feat-add-agent-and-remote
feat(apiserver): add user-agent and remote info into trace log for endpoints handlers.
This commit is contained in:
commit
103a5f92d6
@ -10,6 +10,7 @@ go_test(
|
|||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = [
|
srcs = [
|
||||||
"create_test.go",
|
"create_test.go",
|
||||||
|
"helpers_test.go",
|
||||||
"namer_test.go",
|
"namer_test.go",
|
||||||
"response_test.go",
|
"response_test.go",
|
||||||
"rest_test.go",
|
"rest_test.go",
|
||||||
@ -41,6 +42,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||||
"//vendor/github.com/evanphx/json-patch:go_default_library",
|
"//vendor/github.com/evanphx/json-patch:go_default_library",
|
||||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||||
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
"//vendor/k8s.io/utils/trace:go_default_library",
|
"//vendor/k8s.io/utils/trace:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -52,6 +54,7 @@ go_library(
|
|||||||
"delete.go",
|
"delete.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"get.go",
|
"get.go",
|
||||||
|
"helpers.go",
|
||||||
"namer.go",
|
"namer.go",
|
||||||
"patch.go",
|
"patch.go",
|
||||||
"response.go",
|
"response.go",
|
||||||
@ -77,6 +80,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
||||||
|
@ -46,7 +46,7 @@ import (
|
|||||||
func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Interface, includeName bool) http.HandlerFunc {
|
func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Interface, includeName bool) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
// For performance tracking purposes.
|
// For performance tracking purposes.
|
||||||
trace := utiltrace.New("Create", utiltrace.Field{"url", req.URL.Path})
|
trace := utiltrace.New("Create", utiltrace.Field{Key: "url", Value: req.URL.Path}, utiltrace.Field{Key: "user-agent", Value: &lazyTruncatedUserAgent{req}}, utiltrace.Field{Key: "client", Value: &lazyClientIP{req}})
|
||||||
defer trace.LogIfLong(500 * time.Millisecond)
|
defer trace.LogIfLong(500 * time.Millisecond)
|
||||||
|
|
||||||
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
||||||
|
@ -45,7 +45,7 @@ import (
|
|||||||
func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestScope, admit admission.Interface) http.HandlerFunc {
|
func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestScope, admit admission.Interface) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
// For performance tracking purposes.
|
// For performance tracking purposes.
|
||||||
trace := utiltrace.New("Delete", utiltrace.Field{"url", req.URL.Path})
|
trace := utiltrace.New("Delete", utiltrace.Field{Key: "url", Value: req.URL.Path}, utiltrace.Field{Key: "user-agent", Value: &lazyTruncatedUserAgent{req}}, utiltrace.Field{Key: "client", Value: &lazyClientIP{req}})
|
||||||
defer trace.LogIfLong(500 * time.Millisecond)
|
defer trace.LogIfLong(500 * time.Millisecond)
|
||||||
|
|
||||||
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
||||||
|
@ -49,7 +49,7 @@ type getterFunc func(ctx context.Context, name string, req *http.Request, trace
|
|||||||
// passed-in getterFunc to perform the actual get.
|
// passed-in getterFunc to perform the actual get.
|
||||||
func getResourceHandler(scope *RequestScope, getter getterFunc) http.HandlerFunc {
|
func getResourceHandler(scope *RequestScope, getter getterFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
trace := utiltrace.New("Get", utiltrace.Field{"url", req.URL.Path})
|
trace := utiltrace.New("Get", utiltrace.Field{Key: "url", Value: req.URL.Path}, utiltrace.Field{Key: "user-agent", Value: &lazyTruncatedUserAgent{req}}, utiltrace.Field{Key: "client", Value: &lazyClientIP{req}})
|
||||||
defer trace.LogIfLong(500 * time.Millisecond)
|
defer trace.LogIfLong(500 * time.Millisecond)
|
||||||
|
|
||||||
namespace, name, err := scope.Namer.Name(req)
|
namespace, name, err := scope.Namer.Name(req)
|
||||||
@ -166,7 +166,7 @@ func getRequestOptions(req *http.Request, scope *RequestScope, into runtime.Obje
|
|||||||
func ListResource(r rest.Lister, rw rest.Watcher, scope *RequestScope, forceWatch bool, minRequestTimeout time.Duration) http.HandlerFunc {
|
func ListResource(r rest.Lister, rw rest.Watcher, scope *RequestScope, forceWatch bool, minRequestTimeout time.Duration) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
// For performance tracking purposes.
|
// For performance tracking purposes.
|
||||||
trace := utiltrace.New("List", utiltrace.Field{"url", req.URL.Path})
|
trace := utiltrace.New("List", utiltrace.Field{Key: "url", Value: req.URL.Path}, utiltrace.Field{Key: "user-agent", Value: &lazyTruncatedUserAgent{req}}, utiltrace.Field{Key: "client", Value: &lazyClientIP{req}})
|
||||||
|
|
||||||
namespace, err := scope.Namer.Namespace(req)
|
namespace, err := scope.Namer.Namespace(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 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 handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxUserAgentLength = 1024
|
||||||
|
userAgentTruncateSuffix = "...TRUNCATED"
|
||||||
|
)
|
||||||
|
|
||||||
|
// lazyTruncatedUserAgent implements String() string and it will
|
||||||
|
// return user-agent which may be truncated.
|
||||||
|
type lazyTruncatedUserAgent struct {
|
||||||
|
req *http.Request
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lazy *lazyTruncatedUserAgent) String() string {
|
||||||
|
ua := "unknown"
|
||||||
|
if lazy.req != nil {
|
||||||
|
ua = utilnet.GetHTTPClient(lazy.req)
|
||||||
|
if len(ua) > maxUserAgentLength {
|
||||||
|
ua = ua[:maxUserAgentLength] + userAgentTruncateSuffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ua
|
||||||
|
}
|
||||||
|
|
||||||
|
// LazyClientIP implements String() string and it will
|
||||||
|
// calls GetClientIP() lazily only when required.
|
||||||
|
type lazyClientIP struct {
|
||||||
|
req *http.Request
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lazy *lazyClientIP) String() string {
|
||||||
|
if lazy.req != nil {
|
||||||
|
if ip := utilnet.GetClientIP(lazy.req); ip != nil {
|
||||||
|
return ip.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 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 handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLazyTruncatedUserAgent(t *testing.T) {
|
||||||
|
req := &http.Request{}
|
||||||
|
req.Header = http.Header{}
|
||||||
|
|
||||||
|
ua := "short-agent"
|
||||||
|
req.Header.Set("User-Agent", ua)
|
||||||
|
uaNotTruncated := &lazyTruncatedUserAgent{req}
|
||||||
|
assert.Equal(t, ua, fmt.Sprintf("%v", uaNotTruncated))
|
||||||
|
|
||||||
|
ua = ""
|
||||||
|
for i := 0; i < maxUserAgentLength*2; i++ {
|
||||||
|
ua = ua + "a"
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", ua)
|
||||||
|
uaTruncated := &lazyTruncatedUserAgent{req}
|
||||||
|
assert.NotEqual(t, ua, fmt.Sprintf("%v", uaTruncated))
|
||||||
|
|
||||||
|
usUnknown := &lazyTruncatedUserAgent{}
|
||||||
|
assert.Equal(t, "unknown", fmt.Sprintf("%v", usUnknown))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLazyClientIP(t *testing.T) {
|
||||||
|
req := &http.Request{}
|
||||||
|
req.Header = http.Header{}
|
||||||
|
|
||||||
|
ip := "127.0.0.1"
|
||||||
|
req.Header.Set("X-Forwarded-For", ip)
|
||||||
|
|
||||||
|
clientIPWithReq := &lazyClientIP{req}
|
||||||
|
assert.Equal(t, ip, fmt.Sprintf("%v", clientIPWithReq))
|
||||||
|
|
||||||
|
clientIPWithoutReq := &lazyClientIP{}
|
||||||
|
assert.Equal(t, "unknown", fmt.Sprintf("%v", clientIPWithoutReq))
|
||||||
|
}
|
@ -59,7 +59,7 @@ const (
|
|||||||
func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interface, patchTypes []string) http.HandlerFunc {
|
func PatchResource(r rest.Patcher, scope *RequestScope, admit admission.Interface, patchTypes []string) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
// For performance tracking purposes.
|
// For performance tracking purposes.
|
||||||
trace := utiltrace.New("Patch", utiltrace.Field{"url", req.URL.Path})
|
trace := utiltrace.New("Patch", utiltrace.Field{Key: "url", Value: req.URL.Path}, utiltrace.Field{Key: "user-agent", Value: &lazyTruncatedUserAgent{req}}, utiltrace.Field{Key: "client", Value: &lazyClientIP{req}})
|
||||||
defer trace.LogIfLong(500 * time.Millisecond)
|
defer trace.LogIfLong(500 * time.Millisecond)
|
||||||
|
|
||||||
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
||||||
|
@ -45,7 +45,7 @@ import (
|
|||||||
func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interface) http.HandlerFunc {
|
func UpdateResource(r rest.Updater, scope *RequestScope, admit admission.Interface) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
// For performance tracking purposes.
|
// For performance tracking purposes.
|
||||||
trace := utiltrace.New("Update", utiltrace.Field{"url", req.URL.Path})
|
trace := utiltrace.New("Update", utiltrace.Field{Key: "url", Value: req.URL.Path}, utiltrace.Field{Key: "user-agent", Value: &lazyTruncatedUserAgent{req}}, utiltrace.Field{Key: "client", Value: &lazyClientIP{req}})
|
||||||
defer trace.LogIfLong(500 * time.Millisecond)
|
defer trace.LogIfLong(500 * time.Millisecond)
|
||||||
|
|
||||||
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
if isDryRun(req.URL) && !utilfeature.DefaultFeatureGate.Enabled(features.DryRun) {
|
||||||
|
Loading…
Reference in New Issue
Block a user