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

Logging #713

Merged
merged 4 commits into from
Apr 11, 2019
Merged
Changes from 3 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
1 change: 1 addition & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion cmd/manager/main.go
Original file line number Diff line number Diff line change
@@ -70,7 +70,8 @@ func main() {

// Initialize cluster actuator.
clusterActuator := cluster.NewActuator(cluster.ActuatorParams{
Client: cs.ClusterV1alpha1(),
Client: cs.ClusterV1alpha1(),
LoggingContext: "[cluster actuator]",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll have to keep the klog stuff like flag.Parse alive in the manager until we have a better solution

})

// Initialize machine actuator.
2 changes: 2 additions & 0 deletions pkg/cloud/aws/actuators/cluster/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@ go_library(
"//pkg/cloud/aws/services/ec2:go_default_library",
"//pkg/cloud/aws/services/elb:go_default_library",
"//pkg/deployer:go_default_library",
"//pkg/logging:go_default_library",
"//vendor/github.com/go-logr/logr:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1:go_default_library",
8 changes: 7 additions & 1 deletion pkg/cloud/aws/actuators/cluster/actuator.go
Original file line number Diff line number Diff line change
@@ -17,13 +17,15 @@ limitations under the License.
package cluster

import (
"github.com/go-logr/logr"
"github.com/pkg/errors"
"k8s.io/klog"
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/actuators"
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/certificates"
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/ec2"
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/aws/services/elb"
"sigs.k8s.io/cluster-api-provider-aws/pkg/deployer"
"sigs.k8s.io/cluster-api-provider-aws/pkg/logging"
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
client "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha1"
controllerError "sigs.k8s.io/cluster-api/pkg/controller/error"
@@ -37,18 +39,22 @@ type Actuator struct {
*deployer.Deployer

client client.ClusterV1alpha1Interface
log logr.Logger
}

// ActuatorParams holds parameter information for Actuator
type ActuatorParams struct {
Client client.ClusterV1alpha1Interface
Client client.ClusterV1alpha1Interface
LoggingContext string
}

// NewActuator creates a new Actuator
func NewActuator(params ActuatorParams) *Actuator {
log := &logging.Log{}
return &Actuator{
Deployer: deployer.New(deployer.Params{ScopeGetter: actuators.DefaultScopeGetter}),
client: params.Client,
log: log.WithName(params.LoggingContext),
}
}

12 changes: 12 additions & 0 deletions pkg/logging/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["log.go"],
importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/logging",
visibility = ["//visibility:public"],
deps = [
"//pkg/logging/klog:go_default_library",
"//vendor/github.com/go-logr/logr:go_default_library",
],
)
12 changes: 12 additions & 0 deletions pkg/logging/klog/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["logger.go"],
importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/logging/klog",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/go-logr/logr:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
160 changes: 160 additions & 0 deletions pkg/logging/klog/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
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 klog implements logr using klog.
// This particular implementation is mostly copy pasta'd from https://github.com/go-logr/glogr/blob/master/glogr.go
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

making sure this line is seen

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for the custom implementation here vs using klogr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, no, failed to notice that dir in klog. However, I do prefer dealing with structs instead of things like New that return interfaces, but I can live with it.

Updating PR, thanks for pointing that out!

package klog

import (
"bytes"
"encoding/json"
"fmt"
"runtime"
"sort"

"github.com/go-logr/logr"
"k8s.io/klog"
)

// Logger wraps klog behind a well-known interface.
type Logger struct {
level int
prefix string
values []interface{}
}

func (l Logger) clone() Logger {
return Logger{
level: l.level,
prefix: l.prefix,
values: copySlice(l.values),
}
}

func copySlice(in []interface{}) []interface{} {
out := make([]interface{}, len(in))
copy(out, in)
return out
}

// Magic string for intermediate frames that we should ignore.
const autogeneratedFrameName = "<autogenerated>"

// Discover how many frames we need to climb to find the caller. This approach
// was suggested by Ian Lance Taylor of the Go team, so it *should* be safe
// enough (famous last words).
func framesToCaller() int {
// 1 is the immediate caller. 3 should be too many.
for i := 1; i < 3; i++ {
_, file, _, _ := runtime.Caller(i + 1) // +1 for this function's frame
if file != autogeneratedFrameName {
return i
}
}
return 1 // something went wrong, this is safe
}

func flatten(kvList ...interface{}) string {
keys := make([]string, 0, len(kvList))
vals := make(map[string]interface{}, len(kvList))
for i := 0; i < len(kvList); i += 2 {
k, ok := kvList[i].(string)
if !ok {
panic(fmt.Sprintf("key is not a string: %s", pretty(kvList[i])))
}
var v interface{}
if i+1 < len(kvList) {
v = kvList[i+1]
}
keys = append(keys, k)
vals[k] = v
}
sort.Strings(keys)
buf := bytes.Buffer{}
for i, k := range keys {
v := vals[k]
if i > 0 {
buf.WriteRune(' ')
}
buf.WriteString(pretty(k))
buf.WriteString("=")
buf.WriteString(pretty(v))
}
return buf.String()
}

func pretty(value interface{}) string {
jb, _ := json.Marshal(value)
return string(jb)
}

// Info logs an informational message.
func (l Logger) Info(msg string, kvList ...interface{}) {
if l.Enabled() {
lvlStr := flatten("level", l.level)
msgStr := flatten("msg", msg)
fixedStr := flatten(l.values...)
userStr := flatten(kvList...)
klog.InfoDepth(framesToCaller(), l.prefix, " ", lvlStr, " ", msgStr, " ", fixedStr, " ", userStr)
}
}

// Enabled returns true if the logger is enabled.
func (l Logger) Enabled() bool {
return bool(klog.V(klog.Level(l.level)))
}

// Error logs an error.
func (l Logger) Error(err error, msg string, kvList ...interface{}) {
msgStr := flatten("msg", msg)
var loggableErr interface{}
if err != nil {
loggableErr = err.Error()
}
errStr := flatten("error", loggableErr)
fixedStr := flatten(l.values...)
userStr := flatten(kvList...)
klog.ErrorDepth(framesToCaller(), l.prefix, " ", msgStr, " ", errStr, " ", fixedStr, " ", userStr)
}

// V defines the verbosity level of the logging.
func (l Logger) V(level int) logr.InfoLogger {
new := l.clone()
new.level = level
return new
}

// WithName returns a new logr.Logger with the specified name appended. klogr
// uses '/' characters to separate name elements. Callers should not pass '/'
// in the provided name string, but this library does not actually enforce that.
func (l Logger) WithName(name string) logr.Logger {
new := l.clone()
if len(l.prefix) > 0 {
new.prefix = l.prefix + "/"
}
new.prefix += name
return new
}

// WithValues adds key-value pairs to the logging context.
func (l Logger) WithValues(kvList ...interface{}) logr.Logger {
new := l.clone()
new.values = append(new.values, kvList...)
return new
}

var _ logr.Logger = &Logger{}
var _ logr.InfoLogger = &Logger{}
32 changes: 32 additions & 0 deletions pkg/logging/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
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 logging defines the logger to use within the cluster-api-provider-aws
// package. Swap the implementation here.
package logging

import (
"github.com/go-logr/logr"
"sigs.k8s.io/cluster-api-provider-aws/pkg/logging/klog"
)

// Log is the log used in this project.
type Log struct {
klog.Logger
}

var _ logr.Logger = &Log{}
var _ logr.InfoLogger = &Log{}