Skip to content

Commit 5f158d9

Browse files
committed
Logging structure refactor
This splits up pkg/runtime/log into pkg/log, pkg/internal/log, and pkg/log/zap. - pkg/log contains generic logging helpers, and the generic root logger It *only* depends on logr, and thus won't pull in Zap if you don't need it. - pkg/internal/log contains the internal log handle (with the appropriate name). Nothing outside CR should be logging with this handle anyway, so this enforces it. - pkg/log/zap contains Zap-related setup code, and thus CR only has a dependency on Zap if you pull in this package. - pkg/runtime/log remains as a deprecated package to ease refactoring and compatibility. While practically a few types have been removed from this package, in reality most consumers shouldn't notice.
1 parent b15adb2 commit 5f158d9

File tree

11 files changed

+433
-205
lines changed

11 files changed

+433
-205
lines changed

pkg/internal/log/log.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package log contains utilities for fetching a new logger
18+
// when one is not already available.
19+
// Deprecated: use pkg/log
20+
package log
21+
22+
import (
23+
"github.com/go-logr/logr"
24+
25+
"sigs.k8s.io/controller-runtime/pkg/log"
26+
)
27+
28+
var (
29+
// RuntimeLog is a base parent logger for use inside controller-runtime.
30+
RuntimeLog logr.Logger
31+
)
32+
33+
func init() {
34+
RuntimeLog = log.Log.WithName("controller-runtime")
35+
}
File renamed without changes.

pkg/log/log.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package log contains utilities for fetching a new logger
18+
// when one is not already available.
19+
// Deprecated: use pkg/log
20+
package log
21+
22+
import (
23+
"github.com/go-logr/logr"
24+
)
25+
26+
// SetLogger sets a concrete logging implementation for all deferred Loggers.
27+
func SetLogger(l logr.Logger) {
28+
Log.Fulfill(l)
29+
}
30+
31+
// Log is the base logger used by kubebuilder. It delegates
32+
// to another logr.Logger. You *must* call SetLogger to
33+
// get any actual logging.
34+
var Log = NewDelegatingLogger(NullLogger{})

pkg/runtime/log/log_suite_test.go renamed to pkg/log/log_suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ import (
2626

2727
func TestSource(t *testing.T) {
2828
RegisterFailHandler(Fail)
29-
RunSpecsWithDefaultAndCustomReporters(t, "Runtime Log Suite", []Reporter{printer.NewlineReporter{}})
29+
RunSpecsWithDefaultAndCustomReporters(t, "Log Suite", []Reporter{printer.NewlineReporter{}})
3030
}

pkg/runtime/log/log_test.go renamed to pkg/log/log_test.go

Lines changed: 1 addition & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,12 @@ limitations under the License.
1717
package log
1818

1919
import (
20-
"bytes"
21-
"encoding/json"
22-
"io/ioutil"
2320

2421
"github.com/go-logr/logr"
2522
. "github.com/onsi/ginkgo"
2623
. "github.com/onsi/gomega"
27-
kapi "k8s.io/api/core/v1"
28-
"k8s.io/apimachinery/pkg/types"
2924
)
3025

31-
// testStringer is a fmt.Stringer
32-
type testStringer struct{}
33-
34-
func (testStringer) String() string {
35-
return "value"
36-
}
37-
38-
// fakeSyncWriter is a fake zap.SyncerWriter that lets us test if sync was called
39-
type fakeSyncWriter bool
40-
41-
func (w *fakeSyncWriter) Write(p []byte) (int, error) {
42-
return len(p), nil
43-
}
44-
func (w *fakeSyncWriter) Sync() error {
45-
*w = true
46-
return nil
47-
}
48-
4926
// logInfo is the information for a particular fakeLogger message
5027
type logInfo struct {
5128
name []string
@@ -112,7 +89,7 @@ func (f *fakeLogger) Info(msg string, vals ...interface{}) {
11289
func (f *fakeLogger) Enabled() bool { return true }
11390
func (f *fakeLogger) V(lvl int) logr.InfoLogger { return f }
11491

115-
var _ = Describe("runtime log", func() {
92+
var _ = Describe("logging", func() {
11693

11794
Describe("top-level logger", func() {
11895
It("hold newly created loggers until a logger is set", func() {
@@ -238,122 +215,4 @@ var _ = Describe("runtime log", func() {
238215
))
239216
})
240217
})
241-
242-
Describe("Zap logger setup", func() {
243-
Context("with the default output", func() {
244-
It("shouldn't fail when setting up production", func() {
245-
Expect(ZapLogger(false)).NotTo(BeNil())
246-
})
247-
248-
It("shouldn't fail when setting up development", func() {
249-
Expect(ZapLogger(true)).NotTo(BeNil())
250-
})
251-
})
252-
253-
Context("with custom non-sync output", func() {
254-
It("shouldn't fail when setting up production", func() {
255-
Expect(ZapLoggerTo(ioutil.Discard, false)).NotTo(BeNil())
256-
})
257-
258-
It("shouldn't fail when setting up development", func() {
259-
Expect(ZapLoggerTo(ioutil.Discard, true)).NotTo(BeNil())
260-
})
261-
})
262-
263-
Context("when logging kubernetes objects", func() {
264-
var logOut *bytes.Buffer
265-
var logger logr.Logger
266-
267-
BeforeEach(func() {
268-
logOut = new(bytes.Buffer)
269-
By("setting up the logger")
270-
// use production settings (false) to get just json output
271-
logger = ZapLoggerTo(logOut, false)
272-
})
273-
274-
It("should log a standard namespaced Kubernetes object name and namespace", func() {
275-
pod := &kapi.Pod{}
276-
pod.Name = "some-pod"
277-
pod.Namespace = "some-ns"
278-
logger.Info("here's a kubernetes object", "thing", pod)
279-
280-
outRaw := logOut.Bytes()
281-
res := map[string]interface{}{}
282-
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
283-
284-
Expect(res).To(HaveKeyWithValue("thing", map[string]interface{}{
285-
"name": pod.Name,
286-
"namespace": pod.Namespace,
287-
}))
288-
})
289-
290-
It("should work fine with normal stringers", func() {
291-
logger.Info("here's a non-kubernetes stringer", "thing", testStringer{})
292-
outRaw := logOut.Bytes()
293-
res := map[string]interface{}{}
294-
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
295-
296-
Expect(res).To(HaveKeyWithValue("thing", "value"))
297-
})
298-
299-
It("should log a standard non-namespaced Kubernetes object name", func() {
300-
node := &kapi.Node{}
301-
node.Name = "some-node"
302-
logger.Info("here's a kubernetes object", "thing", node)
303-
304-
outRaw := logOut.Bytes()
305-
res := map[string]interface{}{}
306-
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
307-
308-
Expect(res).To(HaveKeyWithValue("thing", map[string]interface{}{
309-
"name": node.Name,
310-
}))
311-
})
312-
313-
It("should log a standard Kubernetes object's kind, if set", func() {
314-
node := &kapi.Node{}
315-
node.Name = "some-node"
316-
node.APIVersion = "v1"
317-
node.Kind = "Node"
318-
logger.Info("here's a kubernetes object", "thing", node)
319-
320-
outRaw := logOut.Bytes()
321-
res := map[string]interface{}{}
322-
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
323-
324-
Expect(res).To(HaveKeyWithValue("thing", map[string]interface{}{
325-
"name": node.Name,
326-
"apiVersion": "v1",
327-
"kind": "Node",
328-
}))
329-
})
330-
331-
It("should log a standard non-namespaced NamespacedName name", func() {
332-
name := types.NamespacedName{Name: "some-node"}
333-
logger.Info("here's a kubernetes object", "thing", name)
334-
335-
outRaw := logOut.Bytes()
336-
res := map[string]interface{}{}
337-
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
338-
339-
Expect(res).To(HaveKeyWithValue("thing", map[string]interface{}{
340-
"name": name.Name,
341-
}))
342-
})
343-
344-
It("should log a standard namespaced NamespacedName name and namespace", func() {
345-
name := types.NamespacedName{Name: "some-pod", Namespace: "some-ns"}
346-
logger.Info("here's a kubernetes object", "thing", name)
347-
348-
outRaw := logOut.Bytes()
349-
res := map[string]interface{}{}
350-
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
351-
352-
Expect(res).To(HaveKeyWithValue("thing", map[string]interface{}{
353-
"name": name.Name,
354-
"namespace": name.Namespace,
355-
}))
356-
})
357-
})
358-
})
359218
})
File renamed without changes.

pkg/runtime/log/kube_helpers.go renamed to pkg/log/zap/kube_helpers.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2018 The Kubernetes Authors.
2+
Copyright 2019 The Kubernetes Authors.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -14,9 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
// Package log contains utilities for fetching a new logger
18-
// when one is not already available.
19-
package log
17+
package zap
2018

2119
import (
2220
"fmt"
@@ -127,3 +125,4 @@ func (k *KubeAwareEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Fie
127125

128126
return k.Encoder.EncodeEntry(entry, fields)
129127
}
128+

pkg/log/zap/zap.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package zap contains helpers for setting up a new logr.Logger instance
18+
// using the Zap logging framework.
19+
package zap
20+
21+
import (
22+
"io"
23+
"os"
24+
"time"
25+
26+
"github.com/go-logr/logr"
27+
"github.com/go-logr/zapr"
28+
"go.uber.org/zap"
29+
"go.uber.org/zap/zapcore"
30+
)
31+
32+
// Logger is a Logger implementation.
33+
// If development is true, a Zap development config will be used
34+
// (stacktraces on warnings, no sampling), otherwise a Zap production
35+
// config will be used (stacktraces on errors, sampling).
36+
func Logger(development bool) logr.Logger {
37+
return LoggerTo(os.Stderr, development)
38+
}
39+
40+
// LoggerTo returns a new Logger implementation using Zap which logs
41+
// to the given destination, instead of stderr. It otherwise behaves like
42+
// ZapLogger.
43+
func LoggerTo(destWriter io.Writer, development bool) logr.Logger {
44+
// this basically mimics New<type>Config, but with a custom sink
45+
sink := zapcore.AddSync(destWriter)
46+
47+
var enc zapcore.Encoder
48+
var lvl zap.AtomicLevel
49+
var opts []zap.Option
50+
if development {
51+
encCfg := zap.NewDevelopmentEncoderConfig()
52+
enc = zapcore.NewConsoleEncoder(encCfg)
53+
lvl = zap.NewAtomicLevelAt(zap.DebugLevel)
54+
opts = append(opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel))
55+
} else {
56+
encCfg := zap.NewProductionEncoderConfig()
57+
enc = zapcore.NewJSONEncoder(encCfg)
58+
lvl = zap.NewAtomicLevelAt(zap.InfoLevel)
59+
opts = append(opts, zap.AddStacktrace(zap.WarnLevel),
60+
zap.WrapCore(func(core zapcore.Core) zapcore.Core {
61+
return zapcore.NewSampler(core, time.Second, 100, 100)
62+
}))
63+
}
64+
opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
65+
log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: enc, Verbose: development}, sink, lvl))
66+
log = log.WithOptions(opts...)
67+
return zapr.NewLogger(log)
68+
}

pkg/log/zap/zap_suite_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package zap
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo"
23+
. "github.com/onsi/gomega"
24+
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
25+
)
26+
27+
func TestSource(t *testing.T) {
28+
RegisterFailHandler(Fail)
29+
RunSpecsWithDefaultAndCustomReporters(t, "Zap Log Suite", []Reporter{printer.NewlineReporter{}})
30+
}

0 commit comments

Comments
 (0)