-
Notifications
You must be signed in to change notification settings - Fork 18
/
logging.go
134 lines (113 loc) · 3.43 KB
/
logging.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0
package logging
import (
"encoding/json"
"sync"
"github.com/mandelsoft/logging"
logcfg "github.com/mandelsoft/logging/config"
"github.com/opencontainers/go-digest"
"github.com/open-component-model/ocm/pkg/errors"
)
// REALM is used to tag all logging done by this library with the ocm tag.
// This is also used as message context to configure settings for all
// log output provided by this library.
var REALM = logging.DefineRealm("ocm", "general realm used for the ocm go library.")
type StaticContext struct {
logging.Context
applied map[string]struct{}
lock sync.Mutex
}
func NewContext(ctx logging.Context) *StaticContext {
if ctx == nil {
ctx = logging.DefaultContext()
}
return &StaticContext{
Context: ctx.WithContext(REALM),
applied: map[string]struct{}{},
}
}
// Configure applies a configuration once.
// Every config identified by its hash is applied
// only once.
func (s *StaticContext) Configure(config *logcfg.Config, extra ...string) error {
add := ""
for _, e := range extra {
if e != "" {
add += "/" + e
}
}
data, err := json.Marshal(config)
if err != nil {
return errors.Wrapf(err, "cannot marshal log config")
}
d := digest.FromBytes(data).String() + add
s.lock.Lock()
defer s.lock.Unlock()
if _, ok := s.applied[d]; ok {
return nil
}
s.applied[d] = struct{}{}
return logcfg.Configure(logContext, config)
}
// global is a wrapper for the default global log content.
var global = NewContext(nil)
// logContext is the global ocm log context.
// It can be replaced by SetContext.
var logContext = global
// SetContext sets a new preconfigured context.
// This function should be called prior to any configuration
// to avoid loosing them.
func SetContext(ctx logging.Context) {
logContext = NewContext(ctx)
}
// Context returns the default logging configuration used for this library.
func Context() *StaticContext {
return logContext
}
// Logger determines a default logger for this given message context
// based on the rule settings for this library.
func Logger(messageContext ...logging.MessageContext) logging.Logger {
return logContext.Logger(messageContext...)
}
func LogContext(ctx logging.Context, provider logging.ContextProvider) logging.Context {
switch {
case ctx != nil:
return ctx
case provider != nil:
return provider.LoggingContext()
default:
return Context()
}
}
// Configure applies configuration for the default log context
// provided by this package.
func Configure(config *logcfg.Config, extra ...string) error {
return logContext.Configure(config, extra...)
}
// ConfigureGlobal applies configuration for the default global log context
// provided by this package.
func ConfigureGlobal(config *logcfg.Config, extra ...string) error {
return global.Configure(config, extra...)
}
// DynamicLogger gets an unbound logger based on the default library logging context.
func DynamicLogger(messageContext ...logging.MessageContext) logging.UnboundLogger {
return logging.DynamicLogger(Context(), messageContext...)
}
var (
contexts []*StaticContext
lock sync.Mutex
)
func PushContext(ctx logging.Context) {
lock.Lock()
defer lock.Unlock()
contexts = append(contexts, logContext)
SetContext(ctx)
}
func PopContext() {
lock.Lock()
defer lock.Unlock()
logContext = contexts[len(contexts)-1]
contexts = contexts[:len(contexts)-1]
}