Browse Source

Godep: update capnslog dependency

Xiang Li 10 years ago
parent
commit
48e36bbb84

+ 6 - 1
Godeps/Godeps.json

@@ -41,6 +41,11 @@
 			"Comment": "v3-6-gcea488b",
 			"Rev": "cea488b4e6855fee89b6c22a811e3c5baca861b6"
 		},
+		{
+			"ImportPath": "github.com/coreos/go-systemd/journal",
+			"Comment": "v3-6-gcea488b",
+			"Rev": "cea488b4e6855fee89b6c22a811e3c5baca861b6"
+		},
 		{
 			"ImportPath": "github.com/coreos/go-systemd/util",
 			"Comment": "v3-6-gcea488b",
@@ -48,7 +53,7 @@
 		},
 		{
 			"ImportPath": "github.com/coreos/pkg/capnslog",
-			"Rev": "99f6e6b8f8ea30b0f82769c1411691c44a66d015"
+			"Rev": "6b7d4a60e79f6aa57a27591288f28e1dcd47a3bc"
 		},
 		{
 			"ImportPath": "github.com/gogo/protobuf/proto",

+ 166 - 0
Godeps/_workspace/src/github.com/coreos/go-systemd/journal/send.go

@@ -0,0 +1,166 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package journal provides write bindings to the systemd journal
+package journal
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"os"
+	"strconv"
+	"strings"
+	"syscall"
+)
+
+// Priority of a journal message
+type Priority int
+
+const (
+	PriEmerg Priority = iota
+	PriAlert
+	PriCrit
+	PriErr
+	PriWarning
+	PriNotice
+	PriInfo
+	PriDebug
+)
+
+var conn net.Conn
+
+func init() {
+	var err error
+	conn, err = net.Dial("unixgram", "/run/systemd/journal/socket")
+	if err != nil {
+		conn = nil
+	}
+}
+
+// Enabled returns true iff the systemd journal is available for logging
+func Enabled() bool {
+	return conn != nil
+}
+
+// Send a message to the systemd journal. vars is a map of journald fields to
+// values.  Fields must be composed of uppercase letters, numbers, and
+// underscores, but must not start with an underscore. Within these
+// restrictions, any arbitrary field name may be used.  Some names have special
+// significance: see the journalctl documentation
+// (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
+// for more details.  vars may be nil.
+func Send(message string, priority Priority, vars map[string]string) error {
+	if conn == nil {
+		return journalError("could not connect to journald socket")
+	}
+
+	data := new(bytes.Buffer)
+	appendVariable(data, "PRIORITY", strconv.Itoa(int(priority)))
+	appendVariable(data, "MESSAGE", message)
+	for k, v := range vars {
+		appendVariable(data, k, v)
+	}
+
+	_, err := io.Copy(conn, data)
+	if err != nil && isSocketSpaceError(err) {
+		file, err := tempFd()
+		if err != nil {
+			return journalError(err.Error())
+		}
+		_, err = io.Copy(file, data)
+		if err != nil {
+			return journalError(err.Error())
+		}
+
+		rights := syscall.UnixRights(int(file.Fd()))
+
+		/* this connection should always be a UnixConn, but better safe than sorry */
+		unixConn, ok := conn.(*net.UnixConn)
+		if !ok {
+			return journalError("can't send file through non-Unix connection")
+		}
+		unixConn.WriteMsgUnix([]byte{}, rights, nil)
+	} else if err != nil {
+		return journalError(err.Error())
+	}
+	return nil
+}
+
+func appendVariable(w io.Writer, name, value string) {
+	if !validVarName(name) {
+		journalError("variable name contains invalid character, ignoring")
+	}
+	if strings.ContainsRune(value, '\n') {
+		/* When the value contains a newline, we write:
+		 * - the variable name, followed by a newline
+		 * - the size (in 64bit little endian format)
+		 * - the data, followed by a newline
+		 */
+		fmt.Fprintln(w, name)
+		binary.Write(w, binary.LittleEndian, uint64(len(value)))
+		fmt.Fprintln(w, value)
+	} else {
+		/* just write the variable and value all on one line */
+		fmt.Fprintf(w, "%s=%s\n", name, value)
+	}
+}
+
+func validVarName(name string) bool {
+	/* The variable name must be in uppercase and consist only of characters,
+	 * numbers and underscores, and may not begin with an underscore. (from the docs)
+	 */
+
+	valid := name[0] != '_'
+	for _, c := range name {
+		valid = valid && ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_'
+	}
+	return valid
+}
+
+func isSocketSpaceError(err error) bool {
+	opErr, ok := err.(*net.OpError)
+	if !ok {
+		return false
+	}
+
+	sysErr, ok := opErr.Err.(syscall.Errno)
+	if !ok {
+		return false
+	}
+
+	return sysErr == syscall.EMSGSIZE || sysErr == syscall.ENOBUFS
+}
+
+func tempFd() (*os.File, error) {
+	file, err := ioutil.TempFile("/dev/shm/", "journal.XXXXX")
+	if err != nil {
+		return nil, err
+	}
+	syscall.Unlink(file.Name())
+	if err != nil {
+		return nil, err
+	}
+	return file, nil
+}
+
+func journalError(s string) error {
+	s = "journal error: " + s
+	fmt.Fprintln(os.Stderr, s)
+	return errors.New(s)
+}

+ 0 - 2
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/example/hello_dolly.go

@@ -17,7 +17,6 @@ package main
 import (
 	"flag"
 	oldlog "log"
-	"os"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/pkg/capnslog"
 )
@@ -32,7 +31,6 @@ func init() {
 
 func main() {
 	rl := capnslog.MustRepoLogger("github.com/coreos/pkg/capnslog/cmd")
-	capnslog.SetFormatter(capnslog.NewStringFormatter(os.Stderr))
 
 	// We can parse the log level configs from the command line
 	flag.Parse()

+ 53 - 10
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/formatters.go

@@ -18,6 +18,7 @@ import (
 	"bufio"
 	"fmt"
 	"io"
+	"runtime"
 	"strings"
 	"time"
 )
@@ -38,26 +39,68 @@ type StringFormatter struct {
 }
 
 func (s *StringFormatter) Format(pkg string, l LogLevel, i int, entries ...interface{}) {
-	now := time.Now()
-	y, m, d := now.Date()
-	h, min, sec := now.Clock()
-	s.w.WriteString(fmt.Sprintf("%d/%02d/%d %02d:%02d:%02d ", y, m, d, h, min, sec))
-	s.writeEntries(pkg, l, i, entries...)
+	now := time.Now().UTC()
+	s.w.WriteString(now.Format(time.RFC3339))
+	s.w.WriteByte(' ')
+	writeEntries(s.w, pkg, l, i, entries...)
+	s.Flush()
 }
 
-func (s *StringFormatter) writeEntries(pkg string, _ LogLevel, _ int, entries ...interface{}) {
+func writeEntries(w *bufio.Writer, pkg string, _ LogLevel, _ int, entries ...interface{}) {
 	if pkg != "" {
-		s.w.WriteString(pkg + ": ")
+		w.WriteString(pkg + ": ")
 	}
 	str := fmt.Sprint(entries...)
 	endsInNL := strings.HasSuffix(str, "\n")
-	s.w.WriteString(str)
+	w.WriteString(str)
 	if !endsInNL {
-		s.w.WriteString("\n")
+		w.WriteString("\n")
 	}
-	s.Flush()
 }
 
 func (s *StringFormatter) Flush() {
 	s.w.Flush()
 }
+
+func NewPrettyFormatter(w io.Writer, debug bool) Formatter {
+	return &PrettyFormatter{
+		w:     bufio.NewWriter(w),
+		debug: debug,
+	}
+}
+
+type PrettyFormatter struct {
+	w     *bufio.Writer
+	debug bool
+}
+
+func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...interface{}) {
+	now := time.Now()
+	ts := now.Format("2006-01-02 15:04:05")
+	c.w.WriteString(ts)
+	ms := now.Nanosecond() / 1000
+	c.w.WriteString(fmt.Sprintf(".%06d", ms))
+	if c.debug {
+		_, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
+		if !ok {
+			file = "???"
+			line = 1
+		} else {
+			slash := strings.LastIndex(file, "/")
+			if slash >= 0 {
+				file = file[slash+1:]
+			}
+		}
+		if line < 0 {
+			line = 0 // not a real line number
+		}
+		c.w.WriteString(fmt.Sprintf(" [%s:%d]", file, line))
+	}
+	c.w.WriteString(fmt.Sprint(" ", l.Char(), " | "))
+	writeEntries(c.w, pkg, l, depth, entries...)
+	c.Flush()
+}
+
+func (c *PrettyFormatter) Flush() {
+	c.w.Flush()
+}

+ 2 - 1
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/glog_formatter.go

@@ -44,7 +44,7 @@ func (g GlogFormatter) Format(pkg string, level LogLevel, depth int, entries ...
 
 func GlogHeader(level LogLevel, depth int) []byte {
 	// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
-	now := time.Now()
+	now := time.Now().UTC()
 	_, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
 	if !ok {
 		file = "???"
@@ -73,6 +73,7 @@ func GlogHeader(level LogLevel, depth int) []byte {
 	twoDigits(buf, second)
 	buf.WriteByte('.')
 	buf.WriteString(strconv.Itoa(now.Nanosecond() / 1000))
+	buf.WriteByte('Z')
 	buf.WriteByte(' ')
 	buf.WriteString(strconv.Itoa(pid))
 	buf.WriteByte(' ')

+ 47 - 0
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/init.go

@@ -0,0 +1,47 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+// Here's where the opinionation comes in. We need some sensible defaults,
+// especially after taking over the log package. Your project (whatever it may
+// be) may see things differently. That's okay; there should be no defaults in
+// the main package that cannot be controlled or overridden programatically,
+// otherwise it's a bug. Doing so is creating your own init_log.go file much
+// like this one.
+
+func init() {
+	initHijack()
+
+	// Go `log` pacakge uses os.Stderr.
+	SetFormatter(NewDefaultFormatter(os.Stderr))
+	SetGlobalLogLevel(INFO)
+}
+
+func NewDefaultFormatter(out io.Writer) Formatter {
+	if syscall.Getppid() == 1 {
+		// We're running under init, which may be systemd.
+		f, err := NewJournaldFormatter()
+		if err == nil {
+			return f
+		}
+	}
+	return NewPrettyFormatter(out, false)
+}

+ 66 - 0
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/journald_formatter.go

@@ -0,0 +1,66 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// +build !windows
+
+package capnslog
+
+import (
+	"errors"
+	"fmt"
+	"os"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/go-systemd/journal"
+)
+
+func NewJournaldFormatter() (Formatter, error) {
+	if !journal.Enabled() {
+		return nil, errors.New("No systemd detected")
+	}
+	return &journaldFormatter{}, nil
+}
+
+type journaldFormatter struct{}
+
+func (j *journaldFormatter) Format(pkg string, l LogLevel, _ int, entries ...interface{}) {
+	var pri journal.Priority
+	switch l {
+	case CRITICAL:
+		pri = journal.PriCrit
+	case ERROR:
+		pri = journal.PriErr
+	case WARNING:
+		pri = journal.PriWarning
+	case NOTICE:
+		pri = journal.PriNotice
+	case INFO:
+		pri = journal.PriInfo
+	case DEBUG:
+		pri = journal.PriDebug
+	case TRACE:
+		pri = journal.PriDebug
+	default:
+		panic("Unhandled loglevel")
+	}
+	msg := fmt.Sprint(entries...)
+	tags := map[string]string{
+		"PACKAGE": pkg,
+	}
+	err := journal.Send(msg, pri, tags)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+	}
+}
+
+func (j *journaldFormatter) Flush() {}

+ 1 - 1
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/log_hijack.go

@@ -18,7 +18,7 @@ import (
 	"log"
 )
 
-func init() {
+func initHijack() {
 	pkg := NewPackageLogger("log", "")
 	w := packageWriter{pkg}
 	log.SetFlags(0)

+ 1 - 1
Godeps/_workspace/src/github.com/coreos/pkg/capnslog/pkg_logger.go

@@ -24,7 +24,7 @@ type PackageLogger struct {
 	level LogLevel
 }
 
-const calldepth = 3
+const calldepth = 2
 
 func (p *PackageLogger) internalLog(depth int, inLevel LogLevel, entries ...interface{}) {
 	if inLevel != CRITICAL && p.level < inLevel {