forked from clearcontainers/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogger.go
147 lines (120 loc) · 3.59 KB
/
logger.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
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (c) 2017 Intel Corporation
//
// 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 main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Sirupsen/logrus"
)
const (
// globalLogEnv is the name of the environment variable that
// specifies the full path to a global log.
//
// This variable takes priority over global_log_path in the
// config file.
globalLogEnv = "CC_RUNTIME_GLOBAL_LOG"
// globalLogMode is the mode used to create the global log file.
globalLogMode = os.FileMode(0640)
// globalLogDirMode is the mode used to create the directory
// to hold the global log.
globalLogDirMode = os.FileMode(0750)
// globalLogFlags are the flags used to open the global log
// file.
globalLogFlags = (os.O_CREATE | os.O_WRONLY | os.O_APPEND | os.O_SYNC)
)
var (
errNeedGlobalLogPath = errors.New("Global log path cannot be empty")
)
// GlobalLogHook represents a "global logfile" that is appended to by all
// runtimes.
//
// A global log is useful since although container managers
// such as docker pass a path for the runtime to use for logging, if the
// runtime fails, the directory used for logging may be deleted. A
// global log can be specified in a location distinct from such
// container-specific paths to provide a persistent log of all runtime
// activity, including debugging failures.
type GlobalLogHook struct {
path string
file *os.File
}
// handleGlobalLog sets up the global logger.
//
// Note that the logfile path may be blank since this function also
// checks the environment to see whether global logging is required.
func handleGlobalLog(logfilePath string) error {
// the environment variable takes priority
path := os.Getenv(globalLogEnv)
if path == "" {
path = logfilePath
}
if path == "" {
// global logging not required
return nil
}
if strings.HasPrefix(path, "/") == false {
return fmt.Errorf("Global log path must be absolute: %v", path)
}
dir := filepath.Dir(logfilePath)
err := os.MkdirAll(dir, globalLogDirMode)
if err != nil {
return err
}
hook, err := newGlobalLogHook(path)
if err != nil {
return err
}
ccLog.Hooks.Add(hook)
return nil
}
// newGlobalLogHook creates a new hook that can be used by a logrus
// logger.
func newGlobalLogHook(logfilePath string) (*GlobalLogHook, error) {
if logfilePath == "" {
return nil, errNeedGlobalLogPath
}
f, err := os.OpenFile(logfilePath, globalLogFlags, globalLogMode)
if err != nil {
return nil, err
}
hook := &GlobalLogHook{
path: logfilePath,
file: f,
}
return hook, nil
}
// Levels informs the logrus Logger which log levels this hook supports.
func (hook *GlobalLogHook) Levels() []logrus.Level {
// Log at all levels
return logrus.AllLevels
}
// Fire is called by the logrus logger when data is available for the
// hook.
func (hook *GlobalLogHook) Fire(entry *logrus.Entry) error {
// Ignore any formatter that has been used and log in a custom format
// to the global log.
_, err := hook.file.WriteString(fmt.Sprintf("%v:%d:%s:%s:%s\n",
entry.Time,
os.Getpid(),
name,
entry.Level,
entry.Message))
if err != nil {
return err
}
return nil
}