|
@@ -1,228 +0,0 @@
|
|
|
-// Package le_go provides a Golang client library for logging to
|
|
|
-// logentries.com over a TCP connection.
|
|
|
-//
|
|
|
-// it uses an access token for sending log events.
|
|
|
-package le_go
|
|
|
-
|
|
|
-import (
|
|
|
- "crypto/tls"
|
|
|
- "fmt"
|
|
|
- "net"
|
|
|
- "os"
|
|
|
- "strings"
|
|
|
- "sync"
|
|
|
- "time"
|
|
|
-)
|
|
|
-
|
|
|
-// Logger represents a Logentries logger,
|
|
|
-// it holds the open TCP connection, access token, prefix and flags.
|
|
|
-//
|
|
|
-// all Logger operations are thread safe and blocking,
|
|
|
-// log operations can be invoked in a non-blocking way by calling them from
|
|
|
-// a goroutine.
|
|
|
-type Logger struct {
|
|
|
- conn net.Conn
|
|
|
- flag int
|
|
|
- mu sync.Mutex
|
|
|
- prefix string
|
|
|
- token string
|
|
|
- buf []byte
|
|
|
-}
|
|
|
-
|
|
|
-const lineSep = "\n"
|
|
|
-
|
|
|
-// Connect creates a new Logger instance and opens a TCP connection to
|
|
|
-// logentries.com,
|
|
|
-// The token can be generated at logentries.com by adding a new log,
|
|
|
-// choosing manual configuration and token based TCP connection.
|
|
|
-func Connect(token string) (*Logger, error) {
|
|
|
- logger := Logger{
|
|
|
- token: token,
|
|
|
- }
|
|
|
-
|
|
|
- if err := logger.openConnection(); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return &logger, nil
|
|
|
-}
|
|
|
-
|
|
|
-// Close closes the TCP connection to logentries.com
|
|
|
-func (logger *Logger) Close() error {
|
|
|
- if logger.conn != nil {
|
|
|
- return logger.conn.Close()
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-// Opens a TCP connection to logentries.com
|
|
|
-func (logger *Logger) openConnection() error {
|
|
|
- conn, err := tls.Dial("tcp", "data.logentries.com:443", &tls.Config{})
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- logger.conn = conn
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-// It returns if the TCP connection to logentries.com is open
|
|
|
-func (logger *Logger) isOpenConnection() bool {
|
|
|
- if logger.conn == nil {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- buf := make([]byte, 1)
|
|
|
-
|
|
|
- logger.conn.SetReadDeadline(time.Now())
|
|
|
-
|
|
|
- _, err := logger.conn.Read(buf)
|
|
|
-
|
|
|
- switch err.(type) {
|
|
|
- case net.Error:
|
|
|
- if err.(net.Error).Timeout() == true {
|
|
|
- logger.conn.SetReadDeadline(time.Time{})
|
|
|
-
|
|
|
- return true
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false
|
|
|
-}
|
|
|
-
|
|
|
-// It ensures that the TCP connection to logentries.com is open.
|
|
|
-// If the connection is closed, a new one is opened.
|
|
|
-func (logger *Logger) ensureOpenConnection() error {
|
|
|
- if !logger.isOpenConnection() {
|
|
|
- if err := logger.openConnection(); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-// Fatal is same as Print() but calls to os.Exit(1)
|
|
|
-func (logger *Logger) Fatal(v ...interface{}) {
|
|
|
- logger.Output(2, fmt.Sprint(v...))
|
|
|
- os.Exit(1)
|
|
|
-}
|
|
|
-
|
|
|
-// Fatalf is same as Printf() but calls to os.Exit(1)
|
|
|
-func (logger *Logger) Fatalf(format string, v ...interface{}) {
|
|
|
- logger.Output(2, fmt.Sprintf(format, v...))
|
|
|
- os.Exit(1)
|
|
|
-}
|
|
|
-
|
|
|
-// Fatalln is same as Println() but calls to os.Exit(1)
|
|
|
-func (logger *Logger) Fatalln(v ...interface{}) {
|
|
|
- logger.Output(2, fmt.Sprintln(v...))
|
|
|
- os.Exit(1)
|
|
|
-}
|
|
|
-
|
|
|
-// Flags returns the logger flags
|
|
|
-func (logger *Logger) Flags() int {
|
|
|
- return logger.flag
|
|
|
-}
|
|
|
-
|
|
|
-// Output does the actual writing to the TCP connection
|
|
|
-func (logger *Logger) Output(calldepth int, s string) error {
|
|
|
- var (
|
|
|
- err error
|
|
|
- waitPeriod = time.Millisecond
|
|
|
- )
|
|
|
- for {
|
|
|
- _, err = logger.Write([]byte(s))
|
|
|
- if err != nil {
|
|
|
- if connectionErr := logger.openConnection(); connectionErr != nil {
|
|
|
- return connectionErr
|
|
|
- }
|
|
|
- waitPeriod *= 2
|
|
|
- time.Sleep(waitPeriod)
|
|
|
- continue
|
|
|
- }
|
|
|
- return err
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Panic is same as Print() but calls to panic
|
|
|
-func (logger *Logger) Panic(v ...interface{}) {
|
|
|
- s := fmt.Sprint(v...)
|
|
|
- logger.Output(2, s)
|
|
|
- panic(s)
|
|
|
-}
|
|
|
-
|
|
|
-// Panicf is same as Printf() but calls to panic
|
|
|
-func (logger *Logger) Panicf(format string, v ...interface{}) {
|
|
|
- s := fmt.Sprintf(format, v...)
|
|
|
- logger.Output(2, s)
|
|
|
- panic(s)
|
|
|
-}
|
|
|
-
|
|
|
-// Panicln is same as Println() but calls to panic
|
|
|
-func (logger *Logger) Panicln(v ...interface{}) {
|
|
|
- s := fmt.Sprintln(v...)
|
|
|
- logger.Output(2, s)
|
|
|
- panic(s)
|
|
|
-}
|
|
|
-
|
|
|
-// Prefix returns the logger prefix
|
|
|
-func (logger *Logger) Prefix() string {
|
|
|
- return logger.prefix
|
|
|
-}
|
|
|
-
|
|
|
-// Print logs a message
|
|
|
-func (logger *Logger) Print(v ...interface{}) error {
|
|
|
- return logger.Output(2, fmt.Sprint(v...))
|
|
|
-}
|
|
|
-
|
|
|
-// Printf logs a formatted message
|
|
|
-func (logger *Logger) Printf(format string, v ...interface{}) error {
|
|
|
- return logger.Output(2, fmt.Sprintf(format, v...))
|
|
|
-}
|
|
|
-
|
|
|
-// Println logs a message with a linebreak
|
|
|
-func (logger *Logger) Println(v ...interface{}) error {
|
|
|
- return logger.Output(2, fmt.Sprintln(v...))
|
|
|
-}
|
|
|
-
|
|
|
-// SetFlags sets the logger flags
|
|
|
-func (logger *Logger) SetFlags(flag int) {
|
|
|
- logger.flag = flag
|
|
|
-}
|
|
|
-
|
|
|
-// SetPrefix sets the logger prefix
|
|
|
-func (logger *Logger) SetPrefix(prefix string) {
|
|
|
- logger.prefix = prefix
|
|
|
-}
|
|
|
-
|
|
|
-// Write writes a bytes array to the Logentries TCP connection,
|
|
|
-// it adds the access token and prefix and also replaces
|
|
|
-// line breaks with the unicode \u2028 character
|
|
|
-func (logger *Logger) Write(p []byte) (n int, err error) {
|
|
|
- logger.mu.Lock()
|
|
|
- if err := logger.ensureOpenConnection(); err != nil {
|
|
|
- return 0, err
|
|
|
- }
|
|
|
- defer logger.mu.Unlock()
|
|
|
-
|
|
|
- logger.makeBuf(p)
|
|
|
-
|
|
|
- return logger.conn.Write(logger.buf)
|
|
|
-}
|
|
|
-
|
|
|
-// makeBuf constructs the logger buffer
|
|
|
-// it is not safe to be used from within multiple concurrent goroutines
|
|
|
-func (logger *Logger) makeBuf(p []byte) {
|
|
|
- count := strings.Count(string(p), lineSep)
|
|
|
- p = []byte(strings.Replace(string(p), lineSep, "\u2028", count-1))
|
|
|
-
|
|
|
- logger.buf = logger.buf[:0]
|
|
|
- logger.buf = append(logger.buf, (logger.token + " ")...)
|
|
|
- logger.buf = append(logger.buf, (logger.prefix + " ")...)
|
|
|
- logger.buf = append(logger.buf, p...)
|
|
|
-
|
|
|
- if !strings.HasSuffix(string(logger.buf), lineSep) {
|
|
|
- logger.buf = append(logger.buf, (lineSep)...)
|
|
|
- }
|
|
|
-}
|