1
0
mirror of https://github.com/rancher/os.git synced 2025-06-29 16:26:50 +00:00

Merge pull request #1415 from SvenDowideit/log-to-dmesg

Log all `ros` logLevels to dmesg.
This commit is contained in:
Josh Curl 2016-11-29 20:21:51 -05:00 committed by GitHub
commit a425c4cc1b
69 changed files with 691 additions and 169 deletions

View File

@ -7,7 +7,7 @@ import (
"strconv"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -9,10 +9,10 @@ import (
"path"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/coreos/coreos-cloudinit/system"
rancherConfig "github.com/rancher/os/config"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
"golang.org/x/net/context"
)
@ -37,6 +37,7 @@ func init() {
func Main() {
flags.Parse(os.Args[1:])
log.InitLogger()
log.Infof("Running cloud-init-execute: pre-console=%v, console=%v", preConsole, console)
cfg := rancherConfig.LoadConfig()

View File

@ -25,7 +25,6 @@ import (
yaml "github.com/cloudfoundry-incubator/candiedyaml"
log "github.com/Sirupsen/logrus"
"github.com/coreos/coreos-cloudinit/config"
"github.com/coreos/coreos-cloudinit/datasource"
"github.com/coreos/coreos-cloudinit/datasource/configdrive"
@ -40,6 +39,7 @@ import (
"github.com/rancher/os/cmd/cloudinitsave/gce"
"github.com/rancher/os/cmd/network"
rancherConfig "github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/netconf"
"github.com/rancher/os/util"
)
@ -54,6 +54,7 @@ const (
)
func Main() {
log.InitLogger()
log.Info("Running cloud-init-save")
cfg := rancherConfig.LoadConfig()

View File

@ -8,9 +8,10 @@ import (
"path"
"strings"
"github.com/rancher/os/log"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/Sirupsen/logrus"
"github.com/packethost/packngo/metadata"
"github.com/rancher/os/config"
"github.com/rancher/os/netconf"
@ -21,7 +22,7 @@ func enablePacketNetwork(cfg *config.RancherConfig) {
for _, v := range cfg.Network.Interfaces {
if v.Address != "" {
if err := netconf.ApplyNetworkConfigs(&cfg.Network); err != nil {
logrus.Errorf("Failed to bootstrap network: %v", err)
log.Errorf("Failed to bootstrap network: %v", err)
return
}
bootStrapped = true
@ -36,7 +37,7 @@ func enablePacketNetwork(cfg *config.RancherConfig) {
c := metadata.NewClient(http.DefaultClient)
m, err := c.Metadata.Get()
if err != nil {
logrus.Errorf("Failed to get Packet metadata: %v", err)
log.Errorf("Failed to get Packet metadata: %v", err)
return
}
@ -78,7 +79,7 @@ func enablePacketNetwork(cfg *config.RancherConfig) {
netCfg.Interfaces["bond0"] = bondCfg
b, _ := yaml.Marshal(netCfg)
logrus.Debugf("Generated network config: %s", string(b))
log.Debugf("Generated network config: %s", string(b))
cc := config.CloudConfig{
Rancher: config.RancherConfig{
@ -89,15 +90,15 @@ func enablePacketNetwork(cfg *config.RancherConfig) {
// Post to phone home URL on first boot
if _, err = os.Stat(config.CloudConfigNetworkFile); err != nil {
if _, err = http.Post(m.PhoneHomeURL, "application/json", bytes.NewReader([]byte{})); err != nil {
logrus.Errorf("Failed to post to Packet phone home URL: %v", err)
log.Errorf("Failed to post to Packet phone home URL: %v", err)
}
}
if err := os.MkdirAll(path.Dir(config.CloudConfigNetworkFile), 0700); err != nil {
logrus.Errorf("Failed to create directory for file %s: %v", config.CloudConfigNetworkFile, err)
log.Errorf("Failed to create directory for file %s: %v", config.CloudConfigNetworkFile, err)
}
if err := config.WriteToFile(cc, config.CloudConfigNetworkFile); err != nil {
logrus.Errorf("Failed to save config file %s: %v", config.CloudConfigNetworkFile, err)
log.Errorf("Failed to save config file %s: %v", config.CloudConfigNetworkFile, err)
}
}

View File

@ -9,8 +9,8 @@ import (
"github.com/codegangsta/cli"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -3,13 +3,14 @@ package control
import (
"os"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/rancher/os/cmd/control/service"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
)
func Main() {
log.InitLogger()
app := cli.NewApp()
app.Name = os.Args[0]

View File

@ -9,8 +9,8 @@ import (
"strings"
"text/template"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/rancher/os/log"
"github.com/codegangsta/cli"
"github.com/rancher/os/config"

View File

@ -8,12 +8,12 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util/network"
)

View File

@ -11,10 +11,10 @@ import (
"strings"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/rancher/os/cmd/cloudinitexecute"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -9,9 +9,9 @@ import (
"syscall"
"time"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -8,11 +8,11 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util/network"
)

View File

@ -5,8 +5,8 @@ import (
"os/exec"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/rancher/os/log"
"golang.org/x/net/context"
"github.com/rancher/os/cmd/cloudinitexecute"

View File

@ -6,7 +6,7 @@ import (
"os/exec"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
"github.com/codegangsta/cli"
"github.com/rancher/os/cmd/power"

View File

@ -10,8 +10,8 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/rancher/os/log"
"github.com/codegangsta/cli"
dockerClient "github.com/docker/engine-api/client"

View File

@ -13,9 +13,9 @@ import (
"github.com/codegangsta/cli"
log "github.com/Sirupsen/logrus"
dockerClient "github.com/docker/engine-api/client"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
)
const (

View File

@ -7,9 +7,9 @@ import (
"strings"
"syscall"
"github.com/rancher/os/log"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/libcompose/project"
"github.com/docker/libcompose/project/options"
@ -102,7 +102,7 @@ func ProjectUp(p project.APIProject, c *cli.Context) error {
cleanupDone <- true
case err := <-errChan:
if err != nil {
logrus.Fatal(err)
log.Fatal(err)
}
cleanupDone <- true
}
@ -155,7 +155,7 @@ func ProjectDelete(p project.APIProject, c *cli.Context) error {
var answer string
_, err := fmt.Scanln(&answer)
if err != nil {
logrus.Error(err)
log.Error(err)
return false
}
if answer != "y" && answer != "Y" {

View File

@ -4,13 +4,13 @@ import (
"fmt"
"strings"
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
dockerApp "github.com/docker/libcompose/cli/docker/app"
"github.com/docker/libcompose/project"
"github.com/rancher/os/cmd/control/service/command"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util/network"
)
@ -24,7 +24,7 @@ func (p *projectFactory) Create(c *cli.Context) (project.APIProject, error) {
func beforeApp(c *cli.Context) error {
if c.GlobalBool("verbose") {
logrus.SetLevel(logrus.DebugLevel)
log.SetLevel(log.DebugLevel)
}
return nil
}
@ -101,7 +101,7 @@ func disable(c *cli.Context) error {
if changed {
if err := updateIncludedServices(cfg); err != nil {
logrus.Fatal(err)
log.Fatal(err)
}
}
@ -122,7 +122,7 @@ func del(c *cli.Context) error {
if changed {
if err := updateIncludedServices(cfg); err != nil {
logrus.Fatal(err)
log.Fatal(err)
}
}
@ -137,7 +137,7 @@ func enable(c *cli.Context) error {
for _, service := range c.Args() {
if val, ok := cfg.Rancher.ServicesInclude[service]; !ok || !val {
if strings.HasPrefix(service, "/") && !strings.HasPrefix(service, "/var/lib/rancher/conf") {
logrus.Fatalf("ERROR: Service should be in path /var/lib/rancher/conf")
log.Fatalf("ERROR: Service should be in path /var/lib/rancher/conf")
}
cfg.Rancher.ServicesInclude[service] = true
@ -147,11 +147,11 @@ func enable(c *cli.Context) error {
if len(enabledServices) > 0 {
if err := compose.StageServices(cfg, enabledServices...); err != nil {
logrus.Fatal(err)
log.Fatal(err)
}
if err := updateIncludedServices(cfg); err != nil {
logrus.Fatal(err)
log.Fatal(err)
}
}
@ -168,7 +168,7 @@ func list(c *cli.Context) error {
services, err := network.GetServices(cfg.Rancher.Repositories.ToArray())
if err != nil {
logrus.Fatalf("Failed to get services: %v", err)
log.Fatalf("Failed to get services: %v", err)
}
for _, service := range services {

View File

@ -3,11 +3,11 @@ package control
import (
"errors"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"golang.org/x/net/context"
)

View File

@ -5,7 +5,7 @@ import (
"os"
"path/filepath"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
"github.com/codegangsta/cli"
machineUtil "github.com/docker/machine/utils"

View File

@ -4,8 +4,8 @@ import (
"os"
"os/exec"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/rancher/os/log"
)
func udevSettleAction(c *cli.Context) {

View File

@ -12,13 +12,13 @@ import (
"path/filepath"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
composeClient "github.com/docker/libcompose/docker/client"
"github.com/docker/libcompose/project"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
rosDocker "github.com/rancher/os/docker"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -4,7 +4,7 @@ import (
"fmt"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
)
func yes(question string) bool {

View File

@ -1,7 +1,7 @@
package network
import (
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
"github.com/docker/libnetwork/resolvconf"
"github.com/rancher/os/config"
@ -10,6 +10,7 @@ import (
)
func Main() {
log.InitLogger()
log.Infof("Running network")
cfg := config.LoadConfig()

View File

@ -10,10 +10,10 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/filters"
"github.com/rancher/os/log"
"github.com/rancher/os/docker"
"github.com/rancher/os/util"

View File

@ -5,9 +5,11 @@ import (
"github.com/codegangsta/cli"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
)
func Main() {
log.InitLogger()
app := cli.NewApp()
app.Name = os.Args[0]

View File

@ -12,8 +12,8 @@ import (
"syscall"
"time"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/rancher/os/log"
)
var (
@ -23,6 +23,7 @@ var (
)
func Main() {
log.InitLogger()
runtime.GOMAXPROCS(1)
runtime.LockOSThread()
app := cli.NewApp()

View File

@ -1,11 +1,12 @@
package sysinit
import (
log "github.com/Sirupsen/logrus"
initPkg "github.com/rancher/os/init"
"github.com/rancher/os/log"
)
func Main() {
log.InitLogger()
if err := initPkg.SysInit(); err != nil {
log.Fatal(err)
}

View File

@ -1,14 +1,15 @@
package systemdocker
import (
"log"
"os"
"github.com/docker/docker/docker"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
)
func Main() {
log.InitLogger()
if os.Geteuid() != 0 {
log.Fatalf("%s: Need to be root", os.Args[0])
}

View File

@ -3,17 +3,18 @@ package wait
import (
"os"
"github.com/Sirupsen/logrus"
"github.com/rancher/os/config"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
)
func Main() {
log.InitLogger()
_, err := docker.NewClient(config.DockerHost)
if err != nil {
logrus.Errorf("Failed to connect to Docker")
log.Errorf("Failed to connect to Docker")
os.Exit(1)
}
logrus.Infof("Docker is ready")
log.Infof("Docker is ready")
}

View File

@ -5,7 +5,6 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/docker/libcompose/cli/logger"
composeConfig "github.com/docker/libcompose/config"
@ -16,6 +15,7 @@ import (
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/config"
rosDocker "github.com/rancher/os/docker"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
"github.com/rancher/os/util/network"
)

View File

@ -3,12 +3,12 @@ package compose
import (
"fmt"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/project"
"github.com/rancher/os/config"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
"github.com/rancher/os/util/network"
)

View File

@ -1,8 +1,8 @@
package config
import (
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/rancher/os/log"
"strings"

View File

@ -7,12 +7,12 @@ import (
"sort"
"strings"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/coreos/coreos-cloudinit/datasource"
"github.com/coreos/coreos-cloudinit/initialize"
"github.com/docker/engine-api/types"
composeConfig "github.com/docker/libcompose/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -11,9 +11,9 @@ import (
"strings"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/resolvconf"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/netconf"
"github.com/rancher/os/selinux"
"github.com/rancher/os/util"
@ -694,6 +694,7 @@ func LaunchDocker(config *Config, docker string, args ...string) (*exec.Cmd, err
}
func Main() {
log.InitLogger()
if os.Getenv("DOCKER_LAUNCH_DEBUG") == "true" {
log.SetLevel(log.DebugLevel)
}

View File

@ -5,11 +5,11 @@ import (
"fmt"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/registry"
"github.com/docker/engine-api/types"
"github.com/docker/libcompose/docker"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
)
// ConfigAuthLookup will lookup registry auth info from cloud config

View File

@ -6,11 +6,11 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
dockerclient "github.com/docker/engine-api/client"
composeClient "github.com/docker/libcompose/docker/client"
"github.com/docker/libcompose/project"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -3,7 +3,6 @@ package docker
import (
"fmt"
"github.com/Sirupsen/logrus"
dockerclient "github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
composeConfig "github.com/docker/libcompose/config"
@ -11,6 +10,7 @@ import (
"github.com/docker/libcompose/project"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"golang.org/x/net/context"
)
@ -96,7 +96,7 @@ func (s *Service) shouldRebuild(ctx context.Context) (bool, error) {
origRebuildLabel := containerInfo.Config.Labels[config.RebuildLabel]
newRebuildLabel := s.Config().Labels[config.RebuildLabel]
rebuildLabelChanged := newRebuildLabel != origRebuildLabel
logrus.WithFields(logrus.Fields{
log.WithFields(log.Fields{
"origRebuildLabel": origRebuildLabel,
"newRebuildLabel": newRebuildLabel,
"rebuildLabelChanged": rebuildLabelChanged,
@ -121,7 +121,7 @@ func (s *Service) shouldRebuild(ctx context.Context) (bool, error) {
} else if rebuildLabelChanged || origRebuildLabel != "false" {
return true, nil
} else {
logrus.Warnf("%s needs rebuilding", name)
log.Warnf("%s needs rebuilding", name)
}
}
}
@ -140,7 +140,7 @@ func (s *Service) Up(ctx context.Context, options options.Up) error {
return err
}
if shouldRebuild {
logrus.Infof("Rebuilding %s", s.Name())
log.Infof("Rebuilding %s", s.Name())
cs, err := s.Service.Containers(ctx)
if err != nil {
return err
@ -221,7 +221,7 @@ func (s *Service) rename(ctx context.Context) error {
}
if len(info.Name) > 0 && info.Name[1:] != s.Name() {
logrus.Debugf("Renaming container %s => %s", info.Name[1:], s.Name())
log.Debugf("Renaming container %s => %s", info.Name[1:], s.Name())
return client.ContainerRename(context.Background(), info.ID, s.Name())
}
return nil

View File

@ -50,11 +50,13 @@ If you're on OS X, you can run RancherOS using [_xhyve_](https://github.com/mist
### Debugging and logging.
You can enable extra log information by setting them using `sudo ros config set`,
You can enable extra log information in the console by setting them using `sudo ros config set`,
or as kernel boot parameters.
Enable all logging by setting `rancher.debug` true
or you can set `rancher.docker.debug`, `racher.system_docker.debug`, `rancher.bootstrap_docker.debug`, or `rancher.log` individually.
You will also be able to view the debug logging information by running `dmesg` as root.
## Repositories
All of repositories are located within our main GitHub [page](https://github.com/rancher).

View File

@ -35,6 +35,9 @@ COPY inputrc /etc/inputrc
COPY growpart /usr/bin/growpart
RUN sed -i s/"partx --update \"\$part\" \"\$dev\""/"partx --update --nr \"\$part\" \"\$dev\""/g /usr/bin/growpart && \
sed -i -e 's/duid/clientid/g' /etc/dhcpcd.conf && \
sed -i 1,10d /etc/rsyslog.conf
sed -i 1,10d /etc/rsyslog.conf && \
echo "*.* /var/log/syslog" >> /etc/rsyslog.conf
# dump kernel log to console (but after we've finished booting)
# echo "kern.* /dev/console" >> /etc/rsyslog.conf
ENTRYPOINT ["/usr/bin/ros", "entrypoint"]

View File

@ -3,10 +3,10 @@ package init
import (
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/dfs"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
)

View File

@ -11,11 +11,11 @@ import (
"strings"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/mount"
"github.com/rancher/os/cmd/cloudinitsave"
"github.com/rancher/os/config"
"github.com/rancher/os/dfs"
"github.com/rancher/os/log"
"github.com/rancher/os/util"
"github.com/rancher/os/util/network"
)
@ -87,6 +87,7 @@ func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) {
}
func MainInit() {
// TODO: log.InitLogger()
if err := RunInit(); err != nil {
log.Fatal(err)
}

View File

@ -8,10 +8,10 @@ import (
"strings"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/archive"
"github.com/rancher/os/config"
"github.com/rancher/os/dfs"
"github.com/rancher/os/log"
)
func cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir string) (bool, error) {

View File

@ -3,8 +3,8 @@
package init
import (
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
"github.com/rancher/os/selinux"
"io/ioutil"
)

View File

@ -7,12 +7,12 @@ import (
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/cmd/control"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/docker"
"github.com/rancher/os/log"
)
const (

143
log/log.go Normal file
View File

@ -0,0 +1,143 @@
package log
import (
"io"
"os"
"github.com/Sirupsen/logrus"
)
// Default to using the logrus standard logger until log.InitLogger(logLevel) is called
var appLog = logrus.StandardLogger()
var userHook *ShowuserlogHook
type Fields logrus.Fields
type Level logrus.Level
type Logger logrus.Logger
const (
// PanicLevel level, highest level of severity. Logs and then calls panic with the
// message passed to Debug, Info, ...
PanicLevel Level = iota
// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
// logging level is set to Panic.
FatalLevel
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service.
ErrorLevel
// WarnLevel level. Non-critical entries that deserve eyes.
WarnLevel
// InfoLevel level. General operational entries about what's going on inside the
// application.
InfoLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel
)
func SetOutput(out io.Writer) {
appLog.Out = out
}
func SetLevel(level Level) {
if userHook != nil {
userHook.Level = logrus.Level(level)
} else {
appLog.Level = logrus.Level(level)
logrus.SetLevel(logrus.Level(level))
}
}
func Debugf(format string, args ...interface{}) {
appLog.Debugf(format, args...)
}
func Infof(format string, args ...interface{}) {
appLog.Infof(format, args...)
}
func Printf(format string, args ...interface{}) {
appLog.Printf(format, args...)
}
func Warnf(format string, args ...interface{}) {
appLog.Warnf(format, args...)
}
func Warningf(format string, args ...interface{}) {
appLog.Warningf(format, args...)
}
func Errorf(format string, args ...interface{}) {
appLog.Errorf(format, args...)
}
func Fatalf(format string, args ...interface{}) {
appLog.Fatalf(format, args...)
}
func Panicf(format string, args ...interface{}) {
appLog.Panicf(format, args...)
}
func Debug(args ...interface{}) {
appLog.Debug(args...)
}
func Info(args ...interface{}) {
appLog.Info(args...)
}
func Print(args ...interface{}) {
appLog.Print(args...)
}
func Warn(args ...interface{}) {
appLog.Warn(args...)
}
func Warning(args ...interface{}) {
appLog.Warning(args...)
}
func Error(args ...interface{}) {
appLog.Error(args...)
}
func Fatal(args ...interface{}) {
appLog.Fatal(args...)
}
func Panic(args ...interface{}) {
appLog.Panic(args...)
}
func WithField(key string, value interface{}) *logrus.Entry {
return appLog.WithField(key, value)
}
func WithFields(fields Fields) *logrus.Entry {
return appLog.WithFields(logrus.Fields(fields))
}
func InitLogger() {
if userHook != nil {
return // we've already initialised it
}
thisLog := logrus.New()
filename := "/dev/kmsg"
f, err := os.OpenFile(filename, os.O_WRONLY, 0644)
if err != nil {
logrus.Debugf("error opening /dev/kmsg %s", err)
}
// Filter what the user sees (info level, unless they set --debug)
stdLogger := logrus.StandardLogger()
showuserHook, err := NewShowuserlogHook(stdLogger.Level)
if err != nil {
f.Close()
logrus.Errorf("hook failure %s", err)
}
// We're all set up, now we can make it global
appLog = thisLog
userHook = showuserHook
thisLog.Hooks.Add(showuserHook)
logrus.StandardLogger().Hooks.Add(showuserHook)
thisLog.Out = f
logrus.SetOutput(f)
thisLog.Level = logrus.DebugLevel
pwd, err := os.Getwd()
if err != nil {
thisLog.Error(err)
}
thisLog.Debugf("START: %v in %s", os.Args, pwd)
}

40
log/showuserlog.go Normal file
View File

@ -0,0 +1,40 @@
package log
import (
"fmt"
"github.com/Sirupsen/logrus"
"os"
)
// ShowuserlogHook writes all levels of logrus entries to a file for later analysis
type ShowuserlogHook struct {
Level logrus.Level
}
func NewShowuserlogHook(l logrus.Level) (*ShowuserlogHook, error) {
return &ShowuserlogHook{l}, nil
}
func (hook *ShowuserlogHook) Fire(entry *logrus.Entry) error {
line, err := entry.String()
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
return err
}
if entry.Level <= hook.Level {
fmt.Printf("> %s", line)
}
return nil
}
func (hook *ShowuserlogHook) Levels() []logrus.Level {
return []logrus.Level{
logrus.DebugLevel,
logrus.InfoLevel,
logrus.WarnLevel,
logrus.ErrorLevel,
logrus.FatalLevel,
logrus.PanicLevel,
}
}

View File

@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
"github.com/vishvananda/netlink"
)
@ -23,7 +23,7 @@ type Bonding struct {
func (b *Bonding) init() error {
_, err := os.Stat(bondingMasters)
if os.IsNotExist(err) {
logrus.Info("Loading bonding kernel module")
log.Info("Loading bonding kernel module")
cmd := exec.Command("modprobe", "bonding")
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdin
@ -89,7 +89,7 @@ func (b *Bonding) RemoveSlave(slave string) error {
}
p := base + b.name + "/bonding/slaves"
logrus.Infof("Removing slave %s from master %s", slave, b.name)
log.Infof("Removing slave %s from master %s", slave, b.name)
return ioutil.WriteFile(p, []byte("-"+slave), 0644)
}
@ -101,7 +101,7 @@ func (b *Bonding) AddSlave(slave string) error {
}
p := base + b.name + "/bonding/slaves"
logrus.Infof("Adding slave %s to master %s", slave, b.name)
log.Infof("Adding slave %s to master %s", slave, b.name)
return ioutil.WriteFile(p, []byte("+"+slave), 0644)
}
@ -117,11 +117,11 @@ func (b *Bonding) Opt(key, value string) error {
p := base + b.name + "/bonding/" + key
if err := ioutil.WriteFile(p, []byte(value), 0644); err != nil {
logrus.Errorf("Failed to set %s=%s on %s: %v", key, value, b.name, err)
log.Errorf("Failed to set %s=%s on %s: %v", key, value, b.name, err)
return err
}
logrus.Infof("Set %s=%s on %s", key, value, b.name)
log.Infof("Set %s=%s on %s", key, value, b.name)
return nil
}
@ -138,6 +138,6 @@ func Bond(name string) (*Bonding, error) {
return b, nil
}
logrus.Infof("Creating bond %s", name)
log.Infof("Creating bond %s", name)
return b, ioutil.WriteFile(bondingMasters, []byte("+"+name), 0644)
}

View File

@ -6,7 +6,7 @@ import (
"math/rand"
"net"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
"github.com/j-keck/arping"
"github.com/vishvananda/netlink"

View File

@ -10,8 +10,8 @@ import (
"sync"
"syscall"
log "github.com/Sirupsen/logrus"
"github.com/flynn/go-shlex"
"github.com/rancher/os/log"
"github.com/rancher/os/config"
"github.com/ryanuber/go-glob"

View File

@ -1,6 +1,6 @@
github.com/Microsoft/go-winio v0.1.0
github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
github.com/Sirupsen/logrus v0.9.0
github.com/Sirupsen/logrus v0.11.0
github.com/boltdb/bolt v1.2.0
github.com/cloudfoundry-incubator/candiedyaml 01cbc92901719f599b11f3a7e3b1768d7002b0bb https://github.com/rancher/candiedyaml
github.com/cloudfoundry/gosigar 3ed7c74352dae6dc00bdc8c74045375352e3ec05

View File

@ -6,7 +6,7 @@ import (
"io/ioutil"
"os"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/log"
)
const (

View File

@ -11,8 +11,8 @@ import (
yaml "github.com/cloudfoundry-incubator/candiedyaml"
log "github.com/Sirupsen/logrus"
"github.com/rancher/os/config"
"github.com/rancher/os/log"
)
var (

View File

@ -11,10 +11,10 @@ import (
"path"
"strings"
"github.com/rancher/os/log"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
osYaml "github.com/rancher/os/config/yaml"
log "github.com/Sirupsen/logrus"
)
const (

View File

@ -3,6 +3,7 @@ go:
- 1.3
- 1.4
- 1.5
- 1.6
- tip
install:
- go get -t ./...

View File

@ -1,3 +1,10 @@
# 0.10.0
* feature: Add a test hook (#180)
* feature: `ParseLevel` is now case-insensitive (#326)
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
* performance: avoid re-allocations on `WithFields` (#335)
# 0.9.0
* logrus/text_formatter: don't emit empty msg

View File

@ -1,4 +1,4 @@
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus)&nbsp;[![godoc reference](https://godoc.org/github.com/Sirupsen/logrus?status.png)][godoc]
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus)&nbsp;[![GoDoc](https://godoc.org/github.com/Sirupsen/logrus?status.svg)](https://godoc.org/github.com/Sirupsen/logrus)
Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
@ -12,7 +12,7 @@ plain text):
![Colored](http://i.imgur.com/PY7qMwd.png)
With `log.Formatter = new(logrus.JSONFormatter)`, for easy parsing by logstash
With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
or Splunk:
```json
@ -32,7 +32,7 @@ ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
```
With the default `log.Formatter = new(&log.TextFormatter{})` when a TTY is not
With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not
attached, the output is compatible with the
[logfmt](http://godoc.org/github.com/kr/logfmt) format:
@ -218,10 +218,22 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) |
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
#### Level logging
@ -299,14 +311,10 @@ The built-in logging formatters are:
field to `true`. To force no colored output even if there is a TTY set the
`DisableColors` field to `true`
* `logrus.JSONFormatter`. Logs fields as JSON.
* `logrus/formatters/logstash.LogstashFormatter`. Logs fields as [Logstash](http://logstash.net) Events.
```go
logrus.SetFormatter(&logstash.LogstashFormatter{Type: "application_name"})
```
Third party logging formatters:
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
@ -362,5 +370,56 @@ entries. It should not be a feature of the application-level logger.
| Tool | Description |
| ---- | ----------- |
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper arround Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
[godoc]: https://godoc.org/github.com/Sirupsen/logrus
#### Testing
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
```go
logger, hook := NewNullLogger()
logger.Error("Hello error")
assert.Equal(1, len(hook.Entries))
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
assert.Equal("Hello error", hook.LastEntry().Message)
hook.Reset()
assert.Nil(hook.LastEntry())
```
#### Fatal handlers
Logrus can register one or more functions that will be called when any `fatal`
level message is logged. The registered handlers will be executed before
logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
```
...
handler := func() {
// gracefully shutdown something...
}
logrus.RegisterExitHandler(handler)
...
```
#### Thread safty
By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
Situation when locking is not needed includes:
* You have no hooks registered, or hooks calling is already thread-safe.
* Writing to logger.Out is already thread-safe, for example:
1) logger.Out is protected by locks.
2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)

64
vendor/github.com/Sirupsen/logrus/alt_exit.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package logrus
// The following code was sourced and modified from the
// https://bitbucket.org/tebeka/atexit package governed by the following license:
//
// Copyright (c) 2012 Miki Tebeka <miki.tebeka@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import (
"fmt"
"os"
)
var handlers = []func(){}
func runHandler(handler func()) {
defer func() {
if err := recover(); err != nil {
fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err)
}
}()
handler()
}
func runHandlers() {
for _, handler := range handlers {
runHandler(handler)
}
}
// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code)
func Exit(code int) {
runHandlers()
os.Exit(code)
}
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
// all handlers. The handlers will also be invoked when any Fatal log entry is
// made.
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
// closing database connections, or sending a alert that the application is
// closing.
func RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
}

View File

@ -3,11 +3,21 @@ package logrus
import (
"bytes"
"fmt"
"io"
"os"
"sync"
"time"
)
var bufferPool *sync.Pool
func init() {
bufferPool = &sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
}
// Defines the key when adding errors using WithError.
var ErrorKey = "error"
@ -29,6 +39,9 @@ type Entry struct {
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
Message string
// When formatter is called in entry.log(), an Buffer may be set to entry
Buffer *bytes.Buffer
}
func NewEntry(logger *Logger) *Entry {
@ -39,21 +52,15 @@ func NewEntry(logger *Logger) *Entry {
}
}
// Returns a reader for the entry, which is a proxy to the formatter.
func (entry *Entry) Reader() (*bytes.Buffer, error) {
serialized, err := entry.Logger.Formatter.Format(entry)
return bytes.NewBuffer(serialized), err
}
// Returns the string representation from the reader and ultimately the
// formatter.
func (entry *Entry) String() (string, error) {
reader, err := entry.Reader()
serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil {
return "", err
}
return reader.String(), err
str := string(serialized)
return str, nil
}
// Add an error as single field (using the key defined in ErrorKey) to the Entry.
@ -68,7 +75,7 @@ func (entry *Entry) WithField(key string, value interface{}) *Entry {
// Add a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
data := Fields{}
data := make(Fields, len(entry.Data)+len(fields))
for k, v := range entry.Data {
data[k] = v
}
@ -81,6 +88,7 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) {
var buffer *bytes.Buffer
entry.Time = time.Now()
entry.Level = level
entry.Message = msg
@ -90,20 +98,23 @@ func (entry Entry) log(level Level, msg string) {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
entry.Logger.mu.Unlock()
}
reader, err := entry.Reader()
buffer = bufferPool.Get().(*bytes.Buffer)
buffer.Reset()
defer bufferPool.Put(buffer)
entry.Buffer = buffer
serialized, err := entry.Logger.Formatter.Format(&entry)
entry.Buffer = nil
if err != nil {
entry.Logger.mu.Lock()
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
entry.Logger.mu.Unlock()
}
entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
_, err = io.Copy(entry.Logger.Out, reader)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
} else {
entry.Logger.mu.Lock()
_, err = entry.Logger.Out.Write(serialized)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
}
entry.Logger.mu.Unlock()
}
// To avoid Entry#log() returning a value that only would make sense for
@ -150,7 +161,7 @@ func (entry *Entry) Fatal(args ...interface{}) {
if entry.Logger.Level >= FatalLevel {
entry.log(FatalLevel, fmt.Sprint(args...))
}
os.Exit(1)
Exit(1)
}
func (entry *Entry) Panic(args ...interface{}) {
@ -198,7 +209,7 @@ func (entry *Entry) Fatalf(format string, args ...interface{}) {
if entry.Logger.Level >= FatalLevel {
entry.Fatal(fmt.Sprintf(format, args...))
}
os.Exit(1)
Exit(1)
}
func (entry *Entry) Panicf(format string, args ...interface{}) {
@ -245,7 +256,7 @@ func (entry *Entry) Fatalln(args ...interface{}) {
if entry.Logger.Level >= FatalLevel {
entry.Fatal(entry.sprintlnn(args...))
}
os.Exit(1)
Exit(1)
}
func (entry *Entry) Panicln(args ...interface{}) {

View File

@ -31,18 +31,15 @@ type Formatter interface {
// It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters.
func prefixFieldClashes(data Fields) {
_, ok := data["time"]
if ok {
data["fields.time"] = data["time"]
if t, ok := data["time"]; ok {
data["fields.time"] = t
}
_, ok = data["msg"]
if ok {
data["fields.msg"] = data["msg"]
if m, ok := data["msg"]; ok {
data["fields.msg"] = m
}
_, ok = data["level"]
if ok {
data["fields.level"] = data["level"]
if l, ok := data["level"]; ok {
data["fields.level"] = l
}
}

View File

@ -26,8 +26,31 @@ type Logger struct {
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
// logged. `logrus.Debug` is useful in
Level Level
// Used to sync writing to the log.
mu sync.Mutex
// Used to sync writing to the log. Locking is enabled by Default
mu MutexWrap
// Reusable empty entry
entryPool sync.Pool
}
type MutexWrap struct {
lock sync.Mutex
disabled bool
}
func (mw *MutexWrap) Lock() {
if !mw.disabled {
mw.lock.Lock()
}
}
func (mw *MutexWrap) Unlock() {
if !mw.disabled {
mw.lock.Unlock()
}
}
func (mw *MutexWrap) Disable() {
mw.disabled = true
}
// Creates a new logger. Configuration should be set by changing `Formatter`,
@ -51,162 +74,235 @@ func New() *Logger {
}
}
// Adds a field to the log entry, note that you it doesn't log until you call
func (logger *Logger) newEntry() *Entry {
entry, ok := logger.entryPool.Get().(*Entry)
if ok {
return entry
}
return NewEntry(logger)
}
func (logger *Logger) releaseEntry(entry *Entry) {
logger.entryPool.Put(entry)
}
// Adds a field to the log entry, note that it doesn't log until you call
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
// If you want multiple fields, use `WithFields`.
func (logger *Logger) WithField(key string, value interface{}) *Entry {
return NewEntry(logger).WithField(key, value)
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithField(key, value)
}
// Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`.
func (logger *Logger) WithFields(fields Fields) *Entry {
return NewEntry(logger).WithFields(fields)
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithFields(fields)
}
// Add an error as single field to the log entry. All it does is call
// `WithError` for the given `error`.
func (logger *Logger) WithError(err error) *Entry {
return NewEntry(logger).WithError(err)
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithError(err)
}
func (logger *Logger) Debugf(format string, args ...interface{}) {
if logger.Level >= DebugLevel {
NewEntry(logger).Debugf(format, args...)
entry := logger.newEntry()
entry.Debugf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Infof(format string, args ...interface{}) {
if logger.Level >= InfoLevel {
NewEntry(logger).Infof(format, args...)
entry := logger.newEntry()
entry.Infof(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Printf(format string, args ...interface{}) {
NewEntry(logger).Printf(format, args...)
entry := logger.newEntry()
entry.Printf(format, args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warnf(format string, args ...interface{}) {
if logger.Level >= WarnLevel {
NewEntry(logger).Warnf(format, args...)
entry := logger.newEntry()
entry.Warnf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Warningf(format string, args ...interface{}) {
if logger.Level >= WarnLevel {
NewEntry(logger).Warnf(format, args...)
entry := logger.newEntry()
entry.Warnf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Errorf(format string, args ...interface{}) {
if logger.Level >= ErrorLevel {
NewEntry(logger).Errorf(format, args...)
entry := logger.newEntry()
entry.Errorf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Fatalf(format string, args ...interface{}) {
if logger.Level >= FatalLevel {
NewEntry(logger).Fatalf(format, args...)
entry := logger.newEntry()
entry.Fatalf(format, args...)
logger.releaseEntry(entry)
}
os.Exit(1)
Exit(1)
}
func (logger *Logger) Panicf(format string, args ...interface{}) {
if logger.Level >= PanicLevel {
NewEntry(logger).Panicf(format, args...)
entry := logger.newEntry()
entry.Panicf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Debug(args ...interface{}) {
if logger.Level >= DebugLevel {
NewEntry(logger).Debug(args...)
entry := logger.newEntry()
entry.Debug(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Info(args ...interface{}) {
if logger.Level >= InfoLevel {
NewEntry(logger).Info(args...)
entry := logger.newEntry()
entry.Info(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Print(args ...interface{}) {
NewEntry(logger).Info(args...)
entry := logger.newEntry()
entry.Info(args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warn(args ...interface{}) {
if logger.Level >= WarnLevel {
NewEntry(logger).Warn(args...)
entry := logger.newEntry()
entry.Warn(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Warning(args ...interface{}) {
if logger.Level >= WarnLevel {
NewEntry(logger).Warn(args...)
entry := logger.newEntry()
entry.Warn(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Error(args ...interface{}) {
if logger.Level >= ErrorLevel {
NewEntry(logger).Error(args...)
entry := logger.newEntry()
entry.Error(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Fatal(args ...interface{}) {
if logger.Level >= FatalLevel {
NewEntry(logger).Fatal(args...)
entry := logger.newEntry()
entry.Fatal(args...)
logger.releaseEntry(entry)
}
os.Exit(1)
Exit(1)
}
func (logger *Logger) Panic(args ...interface{}) {
if logger.Level >= PanicLevel {
NewEntry(logger).Panic(args...)
entry := logger.newEntry()
entry.Panic(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Debugln(args ...interface{}) {
if logger.Level >= DebugLevel {
NewEntry(logger).Debugln(args...)
entry := logger.newEntry()
entry.Debugln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Infoln(args ...interface{}) {
if logger.Level >= InfoLevel {
NewEntry(logger).Infoln(args...)
entry := logger.newEntry()
entry.Infoln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Println(args ...interface{}) {
NewEntry(logger).Println(args...)
entry := logger.newEntry()
entry.Println(args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warnln(args ...interface{}) {
if logger.Level >= WarnLevel {
NewEntry(logger).Warnln(args...)
entry := logger.newEntry()
entry.Warnln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Warningln(args ...interface{}) {
if logger.Level >= WarnLevel {
NewEntry(logger).Warnln(args...)
entry := logger.newEntry()
entry.Warnln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Errorln(args ...interface{}) {
if logger.Level >= ErrorLevel {
NewEntry(logger).Errorln(args...)
entry := logger.newEntry()
entry.Errorln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Fatalln(args ...interface{}) {
if logger.Level >= FatalLevel {
NewEntry(logger).Fatalln(args...)
entry := logger.newEntry()
entry.Fatalln(args...)
logger.releaseEntry(entry)
}
os.Exit(1)
Exit(1)
}
func (logger *Logger) Panicln(args ...interface{}) {
if logger.Level >= PanicLevel {
NewEntry(logger).Panicln(args...)
entry := logger.newEntry()
entry.Panicln(args...)
logger.releaseEntry(entry)
}
}
//When file is opened with appending mode, it's safe to
//write concurrently to a file (within 4k message on Linux).
//In these cases user can choose to disable the lock.
func (logger *Logger) SetNoLock() {
logger.mu.Disable()
}

View File

@ -3,6 +3,7 @@ package logrus
import (
"fmt"
"log"
"strings"
)
// Fields type, used to pass to `WithFields`.
@ -33,7 +34,7 @@ func (level Level) String() string {
// ParseLevel takes a string level and returns the Logrus log level constant.
func ParseLevel(lvl string) (Level, error) {
switch lvl {
switch strings.ToLower(lvl) {
case "panic":
return PanicLevel, nil
case "fatal":
@ -52,6 +53,16 @@ func ParseLevel(lvl string) (Level, error) {
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
}
// A constant exposing all logging levels
var AllLevels = []Level{
PanicLevel,
FatalLevel,
ErrorLevel,
WarnLevel,
InfoLevel,
DebugLevel,
}
// These are the different logging levels. You can set the logging level to log
// on your instance of logger, obtained with `logrus.New()`.
const (
@ -96,3 +107,37 @@ type StdLogger interface {
Panicf(string, ...interface{})
Panicln(...interface{})
}
// The FieldLogger interface generalizes the Entry and Logger types
type FieldLogger interface {
WithField(key string, value interface{}) *Entry
WithFields(fields Fields) *Entry
WithError(err error) *Entry
Debugf(format string, args ...interface{})
Infof(format string, args ...interface{})
Printf(format string, args ...interface{})
Warnf(format string, args ...interface{})
Warningf(format string, args ...interface{})
Errorf(format string, args ...interface{})
Fatalf(format string, args ...interface{})
Panicf(format string, args ...interface{})
Debug(args ...interface{})
Info(args ...interface{})
Print(args ...interface{})
Warn(args ...interface{})
Warning(args ...interface{})
Error(args ...interface{})
Fatal(args ...interface{})
Panic(args ...interface{})
Debugln(args ...interface{})
Infoln(args ...interface{})
Println(args ...interface{})
Warnln(args ...interface{})
Warningln(args ...interface{})
Errorln(args ...interface{})
Fatalln(args ...interface{})
Panicln(args ...interface{})
}

View File

@ -0,0 +1,8 @@
// +build appengine
package logrus
// IsTerminal returns true if stderr's file descriptor is a terminal.
func IsTerminal() bool {
return true
}

View File

@ -1,4 +1,5 @@
// +build darwin freebsd openbsd netbsd dragonfly
// +build !appengine
package logrus

View File

@ -3,6 +3,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !appengine
package logrus
import "syscall"

View File

@ -4,6 +4,7 @@
// license that can be found in the LICENSE file.
// +build linux darwin freebsd openbsd netbsd dragonfly
// +build !appengine
package logrus

View File

@ -1,4 +1,4 @@
// +build solaris
// +build solaris,!appengine
package logrus

View File

@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
// +build windows,!appengine
package logrus

View File

@ -57,6 +57,7 @@ type TextFormatter struct {
}
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
var b *bytes.Buffer
var keys []string = make([]string, 0, len(entry.Data))
for k := range entry.Data {
keys = append(keys, k)
@ -65,8 +66,11 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
if !f.DisableSorting {
sort.Strings(keys)
}
b := &bytes.Buffer{}
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
prefixFieldClashes(entry.Data)
@ -118,7 +122,8 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
}
for _, k := range keys {
v := entry.Data[k]
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
f.appendValue(b, v)
}
}
@ -128,34 +133,36 @@ func needsQuoting(text string) bool {
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.') {
return false
return true
}
}
return true
return false
}
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
b.WriteString(key)
b.WriteByte('=')
f.appendValue(b, value)
b.WriteByte(' ')
}
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
switch value := value.(type) {
case string:
if needsQuoting(value) {
if !needsQuoting(value) {
b.WriteString(value)
} else {
fmt.Fprintf(b, "%q", value)
}
case error:
errmsg := value.Error()
if needsQuoting(errmsg) {
if !needsQuoting(errmsg) {
b.WriteString(errmsg)
} else {
fmt.Fprintf(b, "%q", value)
fmt.Fprintf(b, "%q", errmsg)
}
default:
fmt.Fprint(b, value)
}
b.WriteByte(' ')
}

View File

@ -7,18 +7,40 @@ import (
)
func (logger *Logger) Writer() *io.PipeWriter {
return logger.WriterLevel(InfoLevel)
}
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
reader, writer := io.Pipe()
go logger.writerScanner(reader)
var printFunc func(args ...interface{})
switch level {
case DebugLevel:
printFunc = logger.Debug
case InfoLevel:
printFunc = logger.Info
case WarnLevel:
printFunc = logger.Warn
case ErrorLevel:
printFunc = logger.Error
case FatalLevel:
printFunc = logger.Fatal
case PanicLevel:
printFunc = logger.Panic
default:
printFunc = logger.Print
}
go logger.writerScanner(reader, printFunc)
runtime.SetFinalizer(writer, writerFinalizer)
return writer
}
func (logger *Logger) writerScanner(reader *io.PipeReader) {
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
logger.Print(scanner.Text())
printFunc(scanner.Text())
}
if err := scanner.Err(); err != nil {
logger.Errorf("Error while reading from Writer: %s", err)