Elektron Logging library (#16)
switch to logrus for logging. replaced old logging library with a wrapper around logrus. We now just need to use the exported Log(...) and Logf(...) from the logging/ package that wraps around a set of loggers constituting a chain (following COR). Loggers are configured using a YAML file that specifies the following. 1. enabled/disabled 2. whether the message should be logged on console. 3. filename extension. 4. minimum log level. Retrofitted source code to now use the updated logging library. Updated the documentation with information regarding the specification of the log config file. Currently, the log format in the config file is not adhered to. This is going to be addressed in a future commit.
This commit is contained in:
parent
9977251c14
commit
3543960689
61 changed files with 1510 additions and 1067 deletions
117
logging/clsfnTaskDistrOverheadLogger.go
Normal file
117
logging/clsfnTaskDistrOverheadLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type clsfnTaskDistrOverheadLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newClsfnTaskDistrOverheadLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *clsfnTaskDistrOverheadLogger {
|
||||
|
||||
cLog := &clsfnTaskDistrOverheadLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.TaskDistrConfig.Enabled,
|
||||
FilenameExtension: config.TaskDistrConfig.FilenameExtension,
|
||||
AllowOnConsole: config.TaskDistrConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
cLog.createLogFile(prefix)
|
||||
return cLog
|
||||
}
|
||||
func (cLog clsfnTaskDistrOverheadLogger) Log(logType int, level log.Level, message string) {
|
||||
if cLog.logType == logType {
|
||||
if cLog.isEnabled() {
|
||||
if cLog.isAllowedOnConsole() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if cLog.next != nil {
|
||||
cLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog clsfnTaskDistrOverheadLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if cLog.logType == logType {
|
||||
if cLog.isEnabled() {
|
||||
if cLog.isAllowedOnConsole() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
if cLog.next != nil {
|
||||
cLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog *clsfnTaskDistrOverheadLogger) createLogFile(prefix string) {
|
||||
|
||||
if cLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, cLog.getFilenameExtension()}, "")
|
||||
dirName := cLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
cLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/consoleLogger.go
Normal file
117
logging/consoleLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type consoleLogger struct {
|
||||
baseElektronLogger
|
||||
MinLogLevel string
|
||||
}
|
||||
|
||||
func newConsoleLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *consoleLogger {
|
||||
|
||||
cLog := &consoleLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.ConsoleConfig.Enabled,
|
||||
FilenameExtension: config.ConsoleConfig.FilenameExtension,
|
||||
AllowOnConsole: config.ConsoleConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
|
||||
MinLogLevel: config.ConsoleConfig.MinLogLevel,
|
||||
}
|
||||
|
||||
cLog.createLogFile(prefix)
|
||||
return cLog
|
||||
}
|
||||
|
||||
func (cLog consoleLogger) Log(logType int, level log.Level, message string) {
|
||||
if logType <= cLog.logType {
|
||||
if cLog.isEnabled() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger.
|
||||
if cLog.next != nil {
|
||||
cLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog consoleLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if logType <= cLog.logType {
|
||||
if cLog.isEnabled() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
if cLog.next != nil {
|
||||
cLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog *consoleLogger) createLogFile(prefix string) {
|
||||
// Create log file for the type if it is enabled.
|
||||
if cLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, cLog.getFilenameExtension()}, "")
|
||||
dirName := cLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
cLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
logging/createLogDir.go
Normal file
57
logging/createLogDir.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type logDirectory struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (logD *logDirectory) getDirName() string {
|
||||
return logD.name
|
||||
}
|
||||
|
||||
func (logD *logDirectory) createLogDir(prefix string, startTime time.Time) {
|
||||
|
||||
if logD.name == "" {
|
||||
// Creating directory to store all logs for this run. Directory name format : _2019-November-21_14-33-0.
|
||||
prefix = prefix + "_"
|
||||
logDirName := strings.Join([]string{"./", prefix, strconv.Itoa(startTime.Year())}, "")
|
||||
logDirName = strings.Join([]string{logDirName, startTime.Month().String(), strconv.Itoa(startTime.Day())}, "-")
|
||||
logDirName = strings.Join([]string{logDirName, strconv.Itoa(startTime.Hour())}, "_")
|
||||
logDirName = strings.Join([]string{logDirName, strconv.Itoa(startTime.Minute()), strconv.Itoa(startTime.Second())}, "-")
|
||||
|
||||
if _, err := os.Stat(logDirName); os.IsNotExist(err) {
|
||||
os.Mkdir(logDirName, 0755)
|
||||
} else {
|
||||
log.Println("Unable to create log directory: ", err)
|
||||
logDirName = ""
|
||||
}
|
||||
|
||||
logD.name = logDirName
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type ClsfnTaskDistOverheadLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (col ClsfnTaskDistOverheadLogger) Log(message string) {
|
||||
// Logging the overhead of classifying tasks in the scheduling window and determining the distribution
|
||||
// of light power consuming and heavy power consuming tasks.
|
||||
col.logObserverSpecifics[clsfnTaskDistOverheadLogger].logFile.Println(message)
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
type ConsoleLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (cl ConsoleLogger) Log(message string) {
|
||||
// We need to log to console only if the message is not empty
|
||||
if message != "" {
|
||||
log.Println(message)
|
||||
// Also logging the message to the console log file
|
||||
cl.logObserverSpecifics[conLogger].logFile.Println(message)
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import "github.com/fatih/color"
|
||||
|
||||
// Defining enums of log message types
|
||||
var logMessageNames []string
|
||||
|
||||
// Possible log message types
|
||||
var (
|
||||
ERROR = messageNametoMessageType("ERROR")
|
||||
WARNING = messageNametoMessageType("WARNING")
|
||||
GENERAL = messageNametoMessageType("GENERAL")
|
||||
SUCCESS = messageNametoMessageType("SUCCESS")
|
||||
SCHED_TRACE = messageNametoMessageType("SCHED_TRACE")
|
||||
PCP = messageNametoMessageType("PCP")
|
||||
SPS = messageNametoMessageType("SPS")
|
||||
CLSFN_TASKDIST_OVERHEAD = messageNametoMessageType("CLSFN_TASKDIST_OVERHEAD")
|
||||
SCHED_WINDOW = messageNametoMessageType("SCHED_WINDOW")
|
||||
)
|
||||
|
||||
// Text colors for the different types of log messages.
|
||||
var LogMessageColors map[LogMessageType]*color.Color = map[LogMessageType]*color.Color{
|
||||
ERROR: color.New(color.FgRed, color.Bold),
|
||||
WARNING: color.New(color.FgYellow, color.Bold),
|
||||
GENERAL: color.New(color.FgWhite, color.Bold),
|
||||
SUCCESS: color.New(color.FgGreen, color.Bold),
|
||||
}
|
||||
|
||||
type LogMessageType int
|
||||
|
||||
func (lmt LogMessageType) String() string {
|
||||
return logMessageNames[lmt]
|
||||
}
|
||||
|
||||
func GetLogMessageTypes() []string {
|
||||
return logMessageNames
|
||||
}
|
||||
|
||||
func messageNametoMessageType(messageName string) LogMessageType {
|
||||
// Appending messageName to LogMessageNames
|
||||
logMessageNames = append(logMessageNames, messageName)
|
||||
// Mapping messageName to int
|
||||
return LogMessageType(len(logMessageNames) - 1)
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type LoggerDriver struct {
|
||||
loggerSubject
|
||||
allowedMessageTypes map[LogMessageType]bool
|
||||
}
|
||||
|
||||
func newLogger() *LoggerDriver {
|
||||
logger := &LoggerDriver{
|
||||
allowedMessageTypes: map[LogMessageType]bool{
|
||||
ERROR: true,
|
||||
GENERAL: true,
|
||||
WARNING: true,
|
||||
SCHED_TRACE: true,
|
||||
SUCCESS: true,
|
||||
PCP: true,
|
||||
SPS: true,
|
||||
CLSFN_TASKDIST_OVERHEAD: true,
|
||||
SCHED_WINDOW: true,
|
||||
},
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
func BuildLogger(startTime time.Time, prefix string) *LoggerDriver {
|
||||
// building logger
|
||||
l := newLogger()
|
||||
attachAllLoggers(l, startTime, prefix)
|
||||
return l
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) EnabledLogging(messageType LogMessageType) {
|
||||
log.allowedMessageTypes[messageType] = true
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) DisableLogging(messageType LogMessageType) {
|
||||
log.allowedMessageTypes[messageType] = false
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) WriteLog(messageType LogMessageType, message string) {
|
||||
// checking to see if logging for given messageType is disabled
|
||||
if log.allowedMessageTypes[messageType] {
|
||||
log.setMessage(message)
|
||||
// notify registered loggers to log
|
||||
log.notify(messageType)
|
||||
}
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) Listen(logMType <-chan LogMessageType, logMsg <-chan string) {
|
||||
for {
|
||||
mType := <-logMType
|
||||
msg := <-logMsg
|
||||
log.WriteLog(mType, msg)
|
||||
}
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
logUtils "github.com/spdfg/elektron/logging/utils"
|
||||
)
|
||||
|
||||
// Names of different loggers
|
||||
const (
|
||||
conLogger = "console-logger"
|
||||
schedTraceLogger = "schedTrace-logger"
|
||||
pcpLogger = "pcp-logger"
|
||||
spsLogger = "schedPolicySwitch-logger"
|
||||
clsfnTaskDistOverheadLogger = "classificationOverhead-logger"
|
||||
schedWindowLogger = "schedWindow-logger"
|
||||
)
|
||||
|
||||
// Logger class factory
|
||||
var Loggers map[string]loggerObserver = map[string]loggerObserver{
|
||||
conLogger: nil,
|
||||
schedTraceLogger: nil,
|
||||
pcpLogger: nil,
|
||||
spsLogger: nil,
|
||||
clsfnTaskDistOverheadLogger: nil,
|
||||
schedWindowLogger: nil,
|
||||
}
|
||||
|
||||
// Logger options to help initialize loggers
|
||||
type loggerOption func(l loggerObserver) error
|
||||
|
||||
func withLogDirectory(startTime time.Time, prefix string) loggerOption {
|
||||
return func(l loggerObserver) error {
|
||||
l.(*loggerObserverImpl).setLogDirectory(logUtils.GetLogDir(startTime, prefix))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// This loggerOption initializes the specifics for each loggerObserver
|
||||
func withLoggerSpecifics(prefix string) loggerOption {
|
||||
return func(l loggerObserver) error {
|
||||
l.(*loggerObserverImpl).logObserverSpecifics = map[string]*specifics{
|
||||
conLogger: &specifics{},
|
||||
schedTraceLogger: &specifics{},
|
||||
pcpLogger: &specifics{},
|
||||
spsLogger: &specifics{},
|
||||
clsfnTaskDistOverheadLogger: &specifics{},
|
||||
schedWindowLogger: &specifics{},
|
||||
}
|
||||
l.(*loggerObserverImpl).setLogFilePrefix(prefix)
|
||||
l.(*loggerObserverImpl).setLogFile()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Build and assign all loggers
|
||||
func attachAllLoggers(lg *LoggerDriver, startTime time.Time, prefix string) {
|
||||
loi := &loggerObserverImpl{}
|
||||
loi.init(withLogDirectory(startTime, strings.Split(prefix, startTime.Format("20060102150405"))[0]),
|
||||
withLoggerSpecifics(prefix))
|
||||
Loggers[conLogger] = &ConsoleLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[schedTraceLogger] = &SchedTraceLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[pcpLogger] = &PCPLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[spsLogger] = &SchedPolicySwitchLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[clsfnTaskDistOverheadLogger] = &ClsfnTaskDistOverheadLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[schedWindowLogger] = &SchedWindowLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
|
||||
for _, lmt := range GetLogMessageTypes() {
|
||||
switch lmt {
|
||||
case SCHED_TRACE.String():
|
||||
lg.attach(SCHED_TRACE, Loggers[schedTraceLogger])
|
||||
case GENERAL.String():
|
||||
lg.attach(GENERAL, Loggers[conLogger])
|
||||
case WARNING.String():
|
||||
lg.attach(WARNING, Loggers[conLogger])
|
||||
case ERROR.String():
|
||||
lg.attach(ERROR, Loggers[conLogger])
|
||||
case SUCCESS.String():
|
||||
lg.attach(SUCCESS, Loggers[conLogger])
|
||||
case PCP.String():
|
||||
lg.attach(PCP, Loggers[pcpLogger])
|
||||
case SPS.String():
|
||||
lg.attach(SPS, Loggers[spsLogger])
|
||||
case CLSFN_TASKDIST_OVERHEAD.String():
|
||||
lg.attach(CLSFN_TASKDIST_OVERHEAD, Loggers[clsfnTaskDistOverheadLogger])
|
||||
case SCHED_WINDOW.String():
|
||||
lg.attach(SCHED_WINDOW, Loggers[schedWindowLogger])
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logging platform
|
||||
type loggerObserver interface {
|
||||
Log(message string)
|
||||
setLogFile()
|
||||
setLogFilePrefix(prefix string)
|
||||
setLogDirectory(dirName string)
|
||||
init(opts ...loggerOption)
|
||||
}
|
||||
|
||||
type specifics struct {
|
||||
logFilePrefix string
|
||||
logFile *log.Logger
|
||||
}
|
||||
|
||||
type loggerObserverImpl struct {
|
||||
logFile *log.Logger
|
||||
logObserverSpecifics map[string]*specifics
|
||||
logDirectory string
|
||||
}
|
||||
|
||||
func (loi *loggerObserverImpl) init(opts ...loggerOption) {
|
||||
for _, opt := range opts {
|
||||
// applying logger options
|
||||
if err := opt(loi); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (loi loggerObserverImpl) Log(message string) {}
|
||||
|
||||
// Requires logFilePrefix to have already been set
|
||||
func (loi *loggerObserverImpl) setLogFile() {
|
||||
for prefix, ls := range loi.logObserverSpecifics {
|
||||
if logFile, err := os.Create(ls.logFilePrefix); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
fmt.Printf("Creating logFile with pathname: %s, and prefix: %s\n", ls.logFilePrefix, prefix)
|
||||
ls.logFile = log.New(logFile, "", log.LstdFlags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (loi *loggerObserverImpl) setLogFilePrefix(prefix string) {
|
||||
// Setting logFilePrefix for pcp logger
|
||||
pcpLogFilePrefix := prefix + ".pcplog"
|
||||
if loi.logDirectory != "" {
|
||||
pcpLogFilePrefix = loi.logDirectory + "/" + pcpLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[pcpLogger].logFilePrefix = pcpLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for console logger
|
||||
consoleLogFilePrefix := prefix + "_console.log"
|
||||
if loi.logDirectory != "" {
|
||||
consoleLogFilePrefix = loi.logDirectory + "/" + consoleLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[conLogger].logFilePrefix = consoleLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for schedTrace logger
|
||||
schedTraceLogFilePrefix := prefix + "_schedTrace.log"
|
||||
if loi.logDirectory != "" {
|
||||
schedTraceLogFilePrefix = loi.logDirectory + "/" + schedTraceLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[schedTraceLogger].logFilePrefix = schedTraceLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for schedulingPolicySwitch logger
|
||||
schedPolicySwitchLogFilePrefix := prefix + "_schedPolicySwitch.log"
|
||||
if loi.logDirectory != "" {
|
||||
schedPolicySwitchLogFilePrefix = loi.logDirectory + "/" + schedPolicySwitchLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[spsLogger].logFilePrefix = schedPolicySwitchLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for clsfnTaskDist logger.
|
||||
// Execution time of every call to def.GetTaskDistribution(...) would be recorded and logged in this file.
|
||||
// The overhead would be logged in microseconds.
|
||||
clsfnTaskDistOverheadLogFilePrefix := prefix + "_classificationOverhead.log"
|
||||
if loi.logDirectory != "" {
|
||||
clsfnTaskDistOverheadLogFilePrefix = loi.logDirectory + "/" + clsfnTaskDistOverheadLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[clsfnTaskDistOverheadLogger].logFilePrefix = clsfnTaskDistOverheadLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for schedWindow logger.
|
||||
// Going to log the time stamp when the scheduling window was determined
|
||||
// and the size of the scheduling window.
|
||||
schedWindowLogFilePrefix := prefix + "_schedWindow.log"
|
||||
if loi.logDirectory != "" {
|
||||
schedWindowLogFilePrefix = loi.logDirectory + "/" + schedWindowLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[schedWindowLogger].logFilePrefix = schedWindowLogFilePrefix
|
||||
}
|
||||
|
||||
func (loi *loggerObserverImpl) setLogDirectory(dirName string) {
|
||||
loi.logDirectory = dirName
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type loggerSubject struct {
|
||||
Registry map[LogMessageType][]loggerObserver
|
||||
message string
|
||||
}
|
||||
|
||||
func (ls *loggerSubject) setMessage(message string) {
|
||||
ls.message = message
|
||||
}
|
||||
|
||||
func (ls *loggerSubject) attach(messageType LogMessageType, lo loggerObserver) {
|
||||
if ls.Registry == nil {
|
||||
ls.Registry = make(map[LogMessageType][]loggerObserver)
|
||||
}
|
||||
ls.Registry[messageType] = append(ls.Registry[messageType], lo)
|
||||
}
|
||||
|
||||
func (ls *loggerSubject) notify(messageType LogMessageType) {
|
||||
for _, logObserver := range ls.Registry[messageType] {
|
||||
logObserver.Log(ls.message)
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type SchedPolicySwitchLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (pl *SchedPolicySwitchLogger) Log(message string) {
|
||||
pl.logObserverSpecifics[spsLogger].logFile.Println(message)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type SchedTraceLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (stl SchedTraceLogger) Log(message string) {
|
||||
// Logging schedule trace to mentioned file
|
||||
stl.logObserverSpecifics[schedTraceLogger].logFile.Println(message)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type SchedWindowLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (swl SchedWindowLogger) Log(message string) {
|
||||
// Logging schedule trace to mentioned file
|
||||
swl.logObserverSpecifics[schedWindowLogger].logFile.Println(message)
|
||||
}
|
54
logging/elektronFormatter.go
Normal file
54
logging/elektronFormatter.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type elektronFormatter struct {
|
||||
TimestampFormat string
|
||||
}
|
||||
|
||||
func (f elektronFormatter) Format(entry *log.Entry) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
|
||||
if entry.Buffer != nil {
|
||||
b = entry.Buffer
|
||||
} else {
|
||||
b = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
level := fmt.Sprintf("[%s]:", strings.ToUpper(entry.Level.String()))
|
||||
message := strings.Join([]string{level, entry.Time.Format(f.TimestampFormat), entry.Message, " "}, " ")
|
||||
|
||||
var formattedFields []string
|
||||
for key, value := range entry.Data {
|
||||
formattedFields = append(formattedFields, strings.Join([]string{key, value.(string)}, "="))
|
||||
}
|
||||
|
||||
b.WriteString(message)
|
||||
b.WriteString(strings.Join(formattedFields, ", "))
|
||||
b.WriteByte('\n')
|
||||
return b.Bytes(), nil
|
||||
}
|
165
logging/logger.go
Normal file
165
logging/logger.go
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
)
|
||||
|
||||
// var config loggerConfig
|
||||
var formatter elektronFormatter
|
||||
var elektronLoggerInstance elektronLogger
|
||||
|
||||
type elektronLogger interface {
|
||||
setNext(next elektronLogger)
|
||||
Log(logType int, level log.Level, message string)
|
||||
Logf(logType int, level log.Level, msgFmtString string, args ...interface{})
|
||||
WithFields(logData log.Fields) elektronLogger
|
||||
WithField(key string, value string) elektronLogger
|
||||
}
|
||||
|
||||
type baseLogData struct {
|
||||
data log.Fields
|
||||
}
|
||||
|
||||
type baseElektronLogger struct {
|
||||
*baseLogData
|
||||
|
||||
config struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}
|
||||
|
||||
logType int
|
||||
logFile *os.File
|
||||
next elektronLogger
|
||||
logger *log.Logger
|
||||
logDir *logDirectory
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) isEnabled() bool {
|
||||
return l.config.Enabled
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) isAllowedOnConsole() bool {
|
||||
return l.config.AllowOnConsole
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) getFilenameExtension() string {
|
||||
return l.config.FilenameExtension
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) WithFields(logData log.Fields) elektronLogger {
|
||||
l.data = logData
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) WithField(key string, value string) elektronLogger {
|
||||
l.data[key] = value
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) setNext(next elektronLogger) {
|
||||
l.next = next
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) Log(logType int, level log.Level, message string) {
|
||||
if l.next != nil {
|
||||
l.next.Log(logType, level, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if l.next != nil {
|
||||
l.next.Logf(logType, level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) resetFields() {
|
||||
l.data = nil
|
||||
l.data = log.Fields{}
|
||||
}
|
||||
|
||||
func BuildLogger(prefix string, logConfigFilename string) error {
|
||||
|
||||
// Create the log directory.
|
||||
startTime := time.Now()
|
||||
formatter.TimestampFormat = "2006-01-02 15:04:05"
|
||||
formattedStartTime := startTime.Format("20060102150405")
|
||||
logDir := &logDirectory{}
|
||||
logDir.createLogDir(prefix, startTime)
|
||||
|
||||
// Instantiate the logrus instance.
|
||||
prefix = strings.Join([]string{prefix, formattedStartTime}, "_")
|
||||
logger := &log.Logger{
|
||||
Out: os.Stderr,
|
||||
Level: log.DebugLevel,
|
||||
Formatter: &formatter,
|
||||
}
|
||||
|
||||
// Create a chain of loggers.
|
||||
b := &baseLogData{data: log.Fields{}}
|
||||
head := &baseElektronLogger{baseLogData: b}
|
||||
|
||||
// Read configuration from yaml.
|
||||
if config, err := getConfig(logConfigFilename); err != nil {
|
||||
return errors.Wrap(err, "Failed to build logger")
|
||||
} else {
|
||||
cLog := newConsoleLogger(config, b, CONSOLE, prefix, logger, logDir)
|
||||
pLog := newPCPLogger(config, b, PCP, prefix, logger, logDir)
|
||||
schedTraceLog := newSchedTraceLogger(config, b, SCHED_TRACE, prefix, logger, logDir)
|
||||
spsLog := newSchedPolicySwitchLogger(config, b, SPS, prefix, logger, logDir)
|
||||
schedWindowLog := newSchedWindowLogger(config, b, SCHED_WINDOW, prefix, logger, logDir)
|
||||
tskDistLog := newClsfnTaskDistrOverheadLogger(config, b, CLSFN_TASKDISTR_OVERHEAD, prefix, logger, logDir)
|
||||
|
||||
head.setNext(cLog)
|
||||
cLog.setNext(pLog)
|
||||
pLog.setNext(schedTraceLog)
|
||||
schedTraceLog.setNext(spsLog)
|
||||
spsLog.setNext(schedWindowLog)
|
||||
schedWindowLog.setNext(tskDistLog)
|
||||
|
||||
}
|
||||
|
||||
elektronLoggerInstance = head
|
||||
return nil
|
||||
}
|
||||
|
||||
func Log(logType int, level log.Level, message string) {
|
||||
elektronLoggerInstance.Log(logType, level, message)
|
||||
}
|
||||
|
||||
func Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
elektronLoggerInstance.Logf(logType, level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
func WithFields(logData log.Fields) elektronLogger {
|
||||
return elektronLoggerInstance.WithFields(logData)
|
||||
}
|
||||
|
||||
func WithField(key string, value string) elektronLogger {
|
||||
return elektronLoggerInstance.WithField(key, value)
|
||||
}
|
83
logging/loggerConfig.go
Normal file
83
logging/loggerConfig.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type loggerConfig struct {
|
||||
SchedTraceConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"schedTrace"`
|
||||
|
||||
PCPConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"pcp"`
|
||||
|
||||
ConsoleConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
MinLogLevel string `yaml:"minLogLevel"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"console"`
|
||||
|
||||
SPSConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"sps"`
|
||||
|
||||
TaskDistrConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"clsfnTaskDistrOverhead"`
|
||||
|
||||
SchedWindowConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"schedWindow"`
|
||||
|
||||
Format []string `yaml:"format"`
|
||||
}
|
||||
|
||||
func getConfig(logConfigFilename string) (*loggerConfig, error) {
|
||||
|
||||
yamlFile, err := ioutil.ReadFile(logConfigFilename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read log config file")
|
||||
}
|
||||
|
||||
c := &loggerConfig{}
|
||||
err = yaml.Unmarshal(yamlFile, c)
|
||||
if err != nil {
|
||||
log.Fatalf("Error in unmarshalling yaml: %v", err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
117
logging/pcpLogger.go
Normal file
117
logging/pcpLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type pcpLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newPCPLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *pcpLogger {
|
||||
|
||||
pLog := &pcpLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.PCPConfig.Enabled,
|
||||
FilenameExtension: config.PCPConfig.FilenameExtension,
|
||||
AllowOnConsole: config.PCPConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
pLog.createLogFile(prefix)
|
||||
return pLog
|
||||
}
|
||||
|
||||
func (pLog pcpLogger) Log(logType int, level log.Level, message string) {
|
||||
if pLog.logType == logType {
|
||||
if pLog.isEnabled() {
|
||||
if pLog.isAllowedOnConsole() {
|
||||
pLog.logger.SetOutput(os.Stdout)
|
||||
pLog.logger.WithFields(pLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
pLog.logger.SetOutput(pLog.logFile)
|
||||
pLog.logger.WithFields(pLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
if pLog.next != nil {
|
||||
pLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
pLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (pLog pcpLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if pLog.logType == logType {
|
||||
if pLog.isEnabled() {
|
||||
if pLog.isAllowedOnConsole() {
|
||||
pLog.logger.SetOutput(os.Stdout)
|
||||
pLog.logger.WithFields(pLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
pLog.logger.SetOutput(pLog.logFile)
|
||||
pLog.logger.WithFields(pLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if pLog.next != nil {
|
||||
pLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
pLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (pLog *pcpLogger) createLogFile(prefix string) {
|
||||
if pLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, pLog.getFilenameExtension()}, "")
|
||||
dirName := pLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
pLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/schedPolicySwitchLogger.go
Normal file
117
logging/schedPolicySwitchLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type schedPolicySwitchLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newSchedPolicySwitchLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *schedPolicySwitchLogger {
|
||||
|
||||
sLog := &schedPolicySwitchLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.SPSConfig.Enabled,
|
||||
FilenameExtension: config.SPSConfig.FilenameExtension,
|
||||
AllowOnConsole: config.SPSConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
sLog.createLogFile(prefix)
|
||||
return sLog
|
||||
}
|
||||
|
||||
func (sLog schedPolicySwitchLogger) Log(logType int, level log.Level, message string) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
if sLog.next != nil {
|
||||
sLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog schedPolicySwitchLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if sLog.next != nil {
|
||||
sLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog *schedPolicySwitchLogger) createLogFile(prefix string) {
|
||||
if sLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, sLog.getFilenameExtension()}, "")
|
||||
dirName := sLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
sLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/schedTraceLogger.go
Normal file
117
logging/schedTraceLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type schedTraceLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newSchedTraceLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *schedTraceLogger {
|
||||
|
||||
sLog := &schedTraceLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.SchedTraceConfig.Enabled,
|
||||
FilenameExtension: config.SchedTraceConfig.FilenameExtension,
|
||||
AllowOnConsole: config.SchedTraceConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
sLog.createLogFile(prefix)
|
||||
return sLog
|
||||
}
|
||||
|
||||
func (sLog schedTraceLogger) Log(logType int, level log.Level, message string) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
if sLog.next != nil {
|
||||
sLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog schedTraceLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if sLog.next != nil {
|
||||
sLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog *schedTraceLogger) createLogFile(prefix string) {
|
||||
if sLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, sLog.getFilenameExtension()}, "")
|
||||
dirName := sLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
sLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/schedWindowLogger.go
Normal file
117
logging/schedWindowLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type schedWindowLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newSchedWindowLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *schedWindowLogger {
|
||||
|
||||
sLog := &schedWindowLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.SchedWindowConfig.Enabled,
|
||||
FilenameExtension: config.SchedWindowConfig.FilenameExtension,
|
||||
AllowOnConsole: config.SchedWindowConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
sLog.createLogFile(prefix)
|
||||
return sLog
|
||||
}
|
||||
|
||||
func (sLog schedWindowLogger) Log(logType int, level log.Level, message string) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if sLog.next != nil {
|
||||
sLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog schedWindowLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
if sLog.next != nil {
|
||||
sLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog *schedWindowLogger) createLogFile(prefix string) {
|
||||
if sLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, sLog.getFilenameExtension()}, "")
|
||||
dirName := sLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
sLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +1,28 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package logging
|
||||
package types
|
||||
|
||||
type PCPLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (pl *PCPLogger) Log(message string) {
|
||||
pl.logObserverSpecifics[pcpLogger].logFile.Println(message)
|
||||
}
|
||||
const (
|
||||
CONSOLE = iota
|
||||
PCP
|
||||
SCHED_TRACE
|
||||
SPS
|
||||
SCHED_WINDOW
|
||||
CLSFN_TASKDISTR_OVERHEAD
|
||||
)
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var LogDir string
|
||||
|
||||
func GetLogDir(startTime time.Time, prefix string) string {
|
||||
if LogDir == "" {
|
||||
LogDir = createLogDir(prefix, startTime)
|
||||
}
|
||||
return LogDir
|
||||
}
|
||||
|
||||
func createLogDir(prefix string, startTime time.Time) string {
|
||||
// Creating directory to store all logs for this run
|
||||
logDirName := "./" + prefix + strconv.Itoa(startTime.Year())
|
||||
logDirName += "-"
|
||||
logDirName += startTime.Month().String()
|
||||
logDirName += "-"
|
||||
logDirName += strconv.Itoa(startTime.Day())
|
||||
logDirName += "_"
|
||||
logDirName += strconv.Itoa(startTime.Hour())
|
||||
logDirName += "-"
|
||||
logDirName += strconv.Itoa(startTime.Minute())
|
||||
logDirName += "-"
|
||||
logDirName += strconv.Itoa(startTime.Second())
|
||||
if _, err := os.Stat(logDirName); os.IsNotExist(err) {
|
||||
os.Mkdir(logDirName, 0755)
|
||||
} else {
|
||||
log.Println("Unable to create log directory: ", err)
|
||||
logDirName = ""
|
||||
}
|
||||
return logDirName
|
||||
}
|
Reference in a new issue