adds vendor directory

vendors dependencies in standard `vendor` directory, managed by glide
This commit is contained in:
Jon Chen
2017-05-14 19:35:03 -07:00
parent 070aa50762
commit 737231705f
2173 changed files with 2312028 additions and 0 deletions

2
vendor/github.com/couchbase/goutils/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
*~
*.swp

47
vendor/github.com/couchbase/goutils/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,47 @@
COUCHBASE INC. COMMUNITY EDITION LICENSE AGREEMENT
IMPORTANT-READ CAREFULLY: BY CLICKING THE "I ACCEPT" BOX OR INSTALLING,
DOWNLOADING OR OTHERWISE USING THIS SOFTWARE AND ANY ASSOCIATED
DOCUMENTATION, YOU, ON BEHALF OF YOURSELF OR AS AN AUTHORIZED
REPRESENTATIVE ON BEHALF OF AN ENTITY ("LICENSEE") AGREE TO ALL THE
TERMS OF THIS COMMUNITY EDITION LICENSE AGREEMENT (THE "AGREEMENT")
REGARDING YOUR USE OF THE SOFTWARE. YOU REPRESENT AND WARRANT THAT YOU
HAVE FULL LEGAL AUTHORITY TO BIND THE LICENSEE TO THIS AGREEMENT. IF YOU
DO NOT AGREE WITH ALL OF THESE TERMS, DO NOT SELECT THE "I ACCEPT" BOX
AND DO NOT INSTALL, DOWNLOAD OR OTHERWISE USE THE SOFTWARE. THE
EFFECTIVE DATE OF THIS AGREEMENT IS THE DATE ON WHICH YOU CLICK "I
ACCEPT" OR OTHERWISE INSTALL, DOWNLOAD OR USE THE SOFTWARE.
1. License Grant. Couchbase Inc. hereby grants Licensee, free of charge,
the non-exclusive right to use, copy, 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 Licensee including
the following copyright notice in all copies or substantial portions of
the Software:
Couchbase (r) http://www.Couchbase.com Copyright 2016 Couchbase, Inc.
As used in this Agreement, "Software" means the object code version of
the applicable elastic data management server software provided by
Couchbase Inc.
2. Restrictions. Licensee will not reverse engineer, disassemble, or
decompile the Software (except to the extent such restrictions are
prohibited by law).
3. Support. Couchbase, Inc. will provide Licensee with access to, and
use of, the Couchbase, Inc. support forum available at the following
URL: http://www.couchbase.org/forums/. Couchbase, Inc. may, at its
discretion, modify, suspend or terminate support at any time upon notice
to Licensee.
4. Warranty Disclaimer and Limitation of Liability. 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
COUCHBASE INC. OR THE AUTHORS OR COPYRIGHT HOLDERS IN THE SOFTWARE BE
LIABLE FOR ANY CLAIM, DAMAGES (IINCLUDING, WITHOUT LIMITATION, DIRECT,
INDIRECT OR CONSEQUENTIAL 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.

19
vendor/github.com/couchbase/goutils/README.md generated vendored Normal file
View File

@@ -0,0 +1,19 @@
# goutils
Common utility libraries for Couchbase Go code.
* logging
Package logging implements a simple logging package. It defines a type,
Logger, with methods for formatting output. The logger writes to standard out
and prints the date and time in ISO 8601 standard with a timezone postfix
of each logged message. The logger has option to log message as Json or
Key-value or Text format.
* platform
Package platform implements common platform specific routines we often need
in our Go applications.
## Installation
git clone git@github.com:couchbase/goutils.git

View File

@@ -0,0 +1,251 @@
// Copyright (c) 2016 Couchbase, 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 audit
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"github.com/couchbase/cbauth"
"github.com/couchbase/go-couchbase"
mc "github.com/couchbase/gomemcached"
mcc "github.com/couchbase/gomemcached/client"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
log "github.com/couchbase/clog"
)
// opcode for memcached audit command
var AuditPutCommandCode = mc.CommandCode(0x27)
// write timeout
var WriteTimeout = 1000 * time.Millisecond
// read timeout
var ReadTimeout = 1000 * time.Millisecond
var PoolClients = 5
type GenericFields struct {
Timestamp string `json:"timestamp"`
RealUserid RealUserId `json:"real_userid"`
}
type RealUserId struct {
Source string `json:"source"`
Username string `json:"user"`
}
type AuditSvc struct {
uri string
u string
p string
kvaddr string
client chan *mcc.Client
m sync.Mutex // Protects the fields that follow.
initialized bool
}
func NewAuditSvc(uri string) (*AuditSvc, error) {
parsedUri, err := url.Parse(uri)
if err != nil {
return nil, err
}
u, p, err := cbauth.GetHTTPServiceAuth(parsedUri.Host)
if err != nil {
return nil, err
}
service := &AuditSvc{
uri: uri,
u: u,
p: p,
initialized: false,
client: make(chan *mcc.Client, PoolClients),
}
// Attempt to initialize the service here. No need to check for
// the err returned as if the service initialization were to
// fail because of the server not being ready yet, we will do
// this lazily when the Write API is invoked.
service.init()
log.Printf("audit: created new audit service")
return service, nil
}
func (service *AuditSvc) Write(eventId uint32, event interface{}) error {
log.Printf("audit: Writing audit event. eventId=%v, event=%v\n", eventId,
event)
err := service.init()
if err != nil {
return err
}
client, err := service.getClient()
if err != nil {
return nil
}
if !client.IsHealthy() {
newClient, err := GetNewConnection(service.kvaddr)
if err != nil {
return err
}
client = newClient
}
defer service.releaseClient(client)
return service.writeOnClient(client, eventId, event)
}
func (service *AuditSvc) writeOnClient(client *mcc.Client, eventId uint32,
event interface{}) error {
req, err := composeAuditRequest(eventId, event)
if err != nil {
return err
}
conn := client.Hijack()
conn.(*net.TCPConn).SetWriteDeadline(time.Now().Add(WriteTimeout))
if err := client.Transmit(req); err != nil {
return err
}
conn.(*net.TCPConn).SetReadDeadline(time.Now().Add(ReadTimeout))
res, err := client.Receive()
log.Printf("audit: response=%v, opcode=%v, opaque=%v, status=%v, err=%v\n",
res, res.Opcode, res.Opaque, res.Status, err)
if err != nil {
return err
} else if res.Opcode != AuditPutCommandCode {
return errors.New(fmt.Sprintf("unexpected #opcode %v", res.Opcode))
} else if req.Opaque != res.Opaque {
return errors.New(fmt.Sprintf("opaque mismatch, %v over %v",
req.Opaque, res.Opaque))
} else if res.Status != mc.SUCCESS {
return errors.New(fmt.Sprintf("unsuccessful status = %v", res.Status))
}
return nil
}
func composeAuditRequest(eventId uint32, event interface{}) (
*mc.MCRequest, error) {
eventBytes, err := json.Marshal(event)
if err != nil {
return nil, err
}
req := &mc.MCRequest{
Opcode: AuditPutCommandCode}
req.Extras = make([]byte, 4)
binary.BigEndian.PutUint32(req.Extras[:4], eventId)
req.Body = eventBytes
req.Opaque = eventId
return req, nil
}
func (service *AuditSvc) init() error {
service.m.Lock()
defer service.m.Unlock()
if !service.initialized {
client, err := couchbase.ConnectWithAuthCreds(service.uri,
service.u, service.p)
if err != nil {
log.Printf("audit :error in connecting to url %s err %v",
service.uri, err)
return err
}
pool, err := client.GetPool("default")
if err != nil {
log.Printf("audit :error in connecting to default pool %v", err)
return err
}
for _, p := range pool.Nodes {
if p.ThisNode {
port, ok := p.Ports["direct"]
if !ok {
return fmt.Errorf("Error in getting memcached port")
}
h := strings.Split(p.Hostname, ":")
if len(h) <= 1 {
return fmt.Errorf("Invalid host string")
}
service.kvaddr = h[0] + ":" + strconv.Itoa(port)
break
}
}
if service.kvaddr == "" {
return fmt.Errorf("Error in getting port")
}
for i := 0; i < PoolClients; i++ {
c, err := GetNewConnection(service.kvaddr)
if err != nil {
return fmt.Errorf("audit: Error %v", err)
}
service.client <- c
}
service.initialized = true
}
return nil
}
func (service *AuditSvc) getClient() (*mcc.Client, error) {
return <-service.client, nil
}
func (service *AuditSvc) releaseClient(client *mcc.Client) error {
service.client <- client
return nil
}
func GetAuditBasicFields(req *http.Request) GenericFields {
uid := getRealUserIdFromRequest(req)
t := time.Now().Format("2006-01-02T15:04:05.000Z07:00")
return GenericFields{t, *uid}
}
func getRealUserIdFromRequest(request *http.Request) *RealUserId {
creds, err := cbauth.AuthWebCreds(request)
if err != nil {
log.Printf("Error getting real user id from http request."+
" err=%v\n", err)
// put unknown user in the audit log.
return &RealUserId{"internal", "unknown"}
}
return &RealUserId{creds.Domain(), creds.Name()}
}
func GetNewConnection(kvAddr string) (*mcc.Client, error) {
c, err := mcc.Connect("tcp", kvAddr)
if err != nil {
return nil, fmt.Errorf("audit: Error in connection to"+
" memcached %v", err)
}
u, p, err := cbauth.GetMemcachedServiceAuth(kvAddr)
if err != nil {
return nil, fmt.Errorf("audit: Error in getting auth for"+
" memcached %v", err)
}
_, err = c.Auth(u, p)
if err != nil {
return nil, fmt.Errorf("audit: Error in auth %v", err)
}
return c, nil
}

481
vendor/github.com/couchbase/goutils/logging/logger.go generated vendored Normal file
View File

@@ -0,0 +1,481 @@
// Copyright (c) 2016 Couchbase, 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 logging
import (
"os"
"runtime"
"strings"
"sync"
)
type Level int
const (
NONE = Level(iota) // Disable all logging
FATAL // System is in severe error state and has to abort
SEVERE // System is in severe error state and cannot recover reliably
ERROR // System is in error state but can recover and continue reliably
WARN // System approaching error state, or is in a correct but undesirable state
INFO // System-level events and status, in correct states
REQUEST // Request-level events, with request-specific rlevel
TRACE // Trace detailed system execution, e.g. function entry / exit
DEBUG // Debug
)
type LogEntryFormatter int
const (
TEXTFORMATTER = LogEntryFormatter(iota)
JSONFORMATTER
KVFORMATTER
)
func (level Level) String() string {
return _LEVEL_NAMES[level]
}
var _LEVEL_NAMES = []string{
DEBUG: "DEBUG",
TRACE: "TRACE",
REQUEST: "REQUEST",
INFO: "INFO",
WARN: "WARN",
ERROR: "ERROR",
SEVERE: "SEVERE",
FATAL: "FATAL",
NONE: "NONE",
}
var _LEVEL_MAP = map[string]Level{
"debug": DEBUG,
"trace": TRACE,
"request": REQUEST,
"info": INFO,
"warn": WARN,
"error": ERROR,
"severe": SEVERE,
"fatal": FATAL,
"none": NONE,
}
func ParseLevel(name string) (level Level, ok bool) {
level, ok = _LEVEL_MAP[strings.ToLower(name)]
return
}
/*
Pair supports logging of key-value pairs. Keys beginning with _ are
reserved for the logger, e.g. _time, _level, _msg, and _rlevel. The
Pair APIs are designed to avoid heap allocation and garbage
collection.
*/
type Pairs []Pair
type Pair struct {
Name string
Value interface{}
}
/*
Map allows key-value pairs to be specified using map literals or data
structures. For example:
Errorm(msg, Map{...})
Map incurs heap allocation and garbage collection, so the Pair APIs
should be preferred.
*/
type Map map[string]interface{}
// Logger provides a common interface for logging libraries
type Logger interface {
/*
These APIs write all the given pairs in addition to standard logger keys.
*/
Logp(level Level, msg string, kv ...Pair)
Debugp(msg string, kv ...Pair)
Tracep(msg string, kv ...Pair)
Requestp(rlevel Level, msg string, kv ...Pair)
Infop(msg string, kv ...Pair)
Warnp(msg string, kv ...Pair)
Errorp(msg string, kv ...Pair)
Severep(msg string, kv ...Pair)
Fatalp(msg string, kv ...Pair)
/*
These APIs write the fields in the given kv Map in addition to standard logger keys.
*/
Logm(level Level, msg string, kv Map)
Debugm(msg string, kv Map)
Tracem(msg string, kv Map)
Requestm(rlevel Level, msg string, kv Map)
Infom(msg string, kv Map)
Warnm(msg string, kv Map)
Errorm(msg string, kv Map)
Severem(msg string, kv Map)
Fatalm(msg string, kv Map)
/*
These APIs only write _msg, _time, _level, and other logger keys. If
the msg contains other fields, use the Pair or Map APIs instead.
*/
Logf(level Level, fmt string, args ...interface{})
Debugf(fmt string, args ...interface{})
Tracef(fmt string, args ...interface{})
Requestf(rlevel Level, fmt string, args ...interface{})
Infof(fmt string, args ...interface{})
Warnf(fmt string, args ...interface{})
Errorf(fmt string, args ...interface{})
Severef(fmt string, args ...interface{})
Fatalf(fmt string, args ...interface{})
/*
These APIs control the logging level
*/
SetLevel(Level) // Set the logging level
Level() Level // Get the current logging level
}
var logger Logger = nil
var curLevel Level = DEBUG // initially set to never skip
var loggerMutex sync.RWMutex
// All the methods below first acquire the mutex (mostly in exclusive mode)
// and only then check if logging at the current level is enabled.
// This introduces a fair bottleneck for those log entries that should be
// skipped (the majority, at INFO or below levels)
// We try to predict here if we should lock the mutex at all by caching
// the current log level: while dynamically changing logger, there might
// be the odd entry skipped as the new level is cached.
// Since we seem to never change the logger, this is not an issue.
func skipLogging(level Level) bool {
if logger == nil {
return true
}
return level > curLevel
}
func SetLogger(newLogger Logger) {
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger = newLogger
if logger == nil {
curLevel = NONE
} else {
curLevel = newLogger.Level()
}
}
func Logp(level Level, msg string, kv ...Pair) {
if skipLogging(level) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Logp(level, msg, kv...)
}
func Debugp(msg string, kv ...Pair) {
if skipLogging(DEBUG) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Debugp(msg, kv...)
}
func Tracep(msg string, kv ...Pair) {
if skipLogging(TRACE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Tracep(msg, kv...)
}
func Requestp(rlevel Level, msg string, kv ...Pair) {
if skipLogging(REQUEST) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Requestp(rlevel, msg, kv...)
}
func Infop(msg string, kv ...Pair) {
if skipLogging(INFO) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Infop(msg, kv...)
}
func Warnp(msg string, kv ...Pair) {
if skipLogging(WARN) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Warnp(msg, kv...)
}
func Errorp(msg string, kv ...Pair) {
if skipLogging(ERROR) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Errorp(msg, kv...)
}
func Severep(msg string, kv ...Pair) {
if skipLogging(SEVERE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Severep(msg, kv...)
}
func Fatalp(msg string, kv ...Pair) {
if skipLogging(FATAL) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Fatalp(msg, kv...)
}
func Logm(level Level, msg string, kv Map) {
if skipLogging(level) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Logm(level, msg, kv)
}
func Debugm(msg string, kv Map) {
if skipLogging(DEBUG) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Debugm(msg, kv)
}
func Tracem(msg string, kv Map) {
if skipLogging(TRACE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Tracem(msg, kv)
}
func Requestm(rlevel Level, msg string, kv Map) {
if skipLogging(REQUEST) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Requestm(rlevel, msg, kv)
}
func Infom(msg string, kv Map) {
if skipLogging(INFO) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Infom(msg, kv)
}
func Warnm(msg string, kv Map) {
if skipLogging(WARN) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Warnm(msg, kv)
}
func Errorm(msg string, kv Map) {
if skipLogging(ERROR) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Errorm(msg, kv)
}
func Severem(msg string, kv Map) {
if skipLogging(SEVERE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Severem(msg, kv)
}
func Fatalm(msg string, kv Map) {
if skipLogging(FATAL) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Fatalm(msg, kv)
}
func Logf(level Level, fmt string, args ...interface{}) {
if skipLogging(level) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Logf(level, fmt, args...)
}
func Debugf(fmt string, args ...interface{}) {
if skipLogging(DEBUG) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Debugf(fmt, args...)
}
func Tracef(fmt string, args ...interface{}) {
if skipLogging(TRACE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Tracef(fmt, args...)
}
func Requestf(rlevel Level, fmt string, args ...interface{}) {
if skipLogging(REQUEST) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Requestf(rlevel, fmt, args...)
}
func Infof(fmt string, args ...interface{}) {
if skipLogging(INFO) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Infof(fmt, args...)
}
func Warnf(fmt string, args ...interface{}) {
if skipLogging(WARN) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Warnf(fmt, args...)
}
func Errorf(fmt string, args ...interface{}) {
if skipLogging(ERROR) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Errorf(fmt, args...)
}
func Severef(fmt string, args ...interface{}) {
if skipLogging(SEVERE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Severef(fmt, args...)
}
func Fatalf(fmt string, args ...interface{}) {
if skipLogging(FATAL) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Fatalf(fmt, args...)
}
func SetLevel(level Level) {
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.SetLevel(level)
curLevel = level
}
func LogLevel() Level {
loggerMutex.RLock()
defer loggerMutex.RUnlock()
return logger.Level()
}
func Stackf(level Level, fmt string, args ...interface{}) {
if skipLogging(level) {
return
}
buf := make([]byte, 1<<16)
n := runtime.Stack(buf, false)
s := string(buf[0:n])
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Logf(level, fmt, args...)
logger.Logf(level, s)
}
func init() {
logger = NewLogger(os.Stderr, INFO, KVFORMATTER)
SetLogger(logger)
}

View File

@@ -0,0 +1,318 @@
// Copyright (c) 2016 Couchbase, 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 logging
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"time"
)
type goLogger struct {
logger *log.Logger
level Level
entryFormatter formatter
}
const (
_LEVEL = "_level"
_MSG = "_msg"
_TIME = "_time"
_RLEVEL = "_rlevel"
)
func NewLogger(out io.Writer, lvl Level, fmtLogging LogEntryFormatter) *goLogger {
logger := &goLogger{
logger: log.New(out, "", 0),
level: lvl,
}
if fmtLogging == JSONFORMATTER {
logger.entryFormatter = &jsonFormatter{}
} else if fmtLogging == KVFORMATTER {
logger.entryFormatter = &keyvalueFormatter{}
} else {
logger.entryFormatter = &textFormatter{}
}
return logger
}
func (gl *goLogger) Logp(level Level, msg string, kv ...Pair) {
if gl.logger == nil {
return
}
if level <= gl.level {
e := newLogEntry(msg, level)
copyPairs(e, kv)
gl.log(e)
}
}
func (gl *goLogger) Debugp(msg string, kv ...Pair) {
gl.Logp(DEBUG, msg, kv...)
}
func (gl *goLogger) Tracep(msg string, kv ...Pair) {
gl.Logp(TRACE, msg, kv...)
}
func (gl *goLogger) Requestp(rlevel Level, msg string, kv ...Pair) {
if gl.logger == nil {
return
}
if REQUEST <= gl.level {
e := newLogEntry(msg, REQUEST)
e.Rlevel = rlevel
copyPairs(e, kv)
gl.log(e)
}
}
func (gl *goLogger) Infop(msg string, kv ...Pair) {
gl.Logp(INFO, msg, kv...)
}
func (gl *goLogger) Warnp(msg string, kv ...Pair) {
gl.Logp(WARN, msg, kv...)
}
func (gl *goLogger) Errorp(msg string, kv ...Pair) {
gl.Logp(ERROR, msg, kv...)
}
func (gl *goLogger) Severep(msg string, kv ...Pair) {
gl.Logp(SEVERE, msg, kv...)
}
func (gl *goLogger) Fatalp(msg string, kv ...Pair) {
gl.Logp(FATAL, msg, kv...)
}
func (gl *goLogger) Logm(level Level, msg string, kv Map) {
if gl.logger == nil {
return
}
if level <= gl.level {
e := newLogEntry(msg, level)
e.Data = kv
gl.log(e)
}
}
func (gl *goLogger) Debugm(msg string, kv Map) {
gl.Logm(DEBUG, msg, kv)
}
func (gl *goLogger) Tracem(msg string, kv Map) {
gl.Logm(TRACE, msg, kv)
}
func (gl *goLogger) Requestm(rlevel Level, msg string, kv Map) {
if gl.logger == nil {
return
}
if REQUEST <= gl.level {
e := newLogEntry(msg, REQUEST)
e.Rlevel = rlevel
e.Data = kv
gl.log(e)
}
}
func (gl *goLogger) Infom(msg string, kv Map) {
gl.Logm(INFO, msg, kv)
}
func (gl *goLogger) Warnm(msg string, kv Map) {
gl.Logm(WARN, msg, kv)
}
func (gl *goLogger) Errorm(msg string, kv Map) {
gl.Logm(ERROR, msg, kv)
}
func (gl *goLogger) Severem(msg string, kv Map) {
gl.Logm(SEVERE, msg, kv)
}
func (gl *goLogger) Fatalm(msg string, kv Map) {
gl.Logm(FATAL, msg, kv)
}
func (gl *goLogger) Logf(level Level, format string, args ...interface{}) {
if gl.logger == nil {
return
}
if level <= gl.level {
e := newLogEntry(fmt.Sprintf(format, args...), level)
gl.log(e)
}
}
func (gl *goLogger) Debugf(format string, args ...interface{}) {
gl.Logf(DEBUG, format, args...)
}
func (gl *goLogger) Tracef(format string, args ...interface{}) {
gl.Logf(TRACE, format, args...)
}
func (gl *goLogger) Requestf(rlevel Level, format string, args ...interface{}) {
if gl.logger == nil {
return
}
if REQUEST <= gl.level {
e := newLogEntry(fmt.Sprintf(format, args...), REQUEST)
e.Rlevel = rlevel
gl.log(e)
}
}
func (gl *goLogger) Infof(format string, args ...interface{}) {
gl.Logf(INFO, format, args...)
}
func (gl *goLogger) Warnf(format string, args ...interface{}) {
gl.Logf(WARN, format, args...)
}
func (gl *goLogger) Errorf(format string, args ...interface{}) {
gl.Logf(ERROR, format, args...)
}
func (gl *goLogger) Severef(format string, args ...interface{}) {
gl.Logf(SEVERE, format, args...)
}
func (gl *goLogger) Fatalf(format string, args ...interface{}) {
gl.Logf(FATAL, format, args...)
}
func (gl *goLogger) Level() Level {
return gl.level
}
func (gl *goLogger) SetLevel(level Level) {
gl.level = level
}
func (gl *goLogger) log(newEntry *logEntry) {
s := gl.entryFormatter.format(newEntry)
gl.logger.Print(s)
}
type logEntry struct {
Time string
Level Level
Rlevel Level
Message string
Data Map
}
func newLogEntry(msg string, level Level) *logEntry {
return &logEntry{
Time: time.Now().Format("2006-01-02T15:04:05.000-07:00"), // time.RFC3339 with milliseconds
Level: level,
Rlevel: NONE,
Message: msg,
}
}
func copyPairs(newEntry *logEntry, pairs []Pair) {
newEntry.Data = make(Map, len(pairs))
for _, p := range pairs {
newEntry.Data[p.Name] = p.Value
}
}
type formatter interface {
format(*logEntry) string
}
type textFormatter struct {
}
// ex. 2016-02-10T09:15:25.498-08:00 [INFO] This is a message from test in text format
func (*textFormatter) format(newEntry *logEntry) string {
b := &bytes.Buffer{}
appendValue(b, newEntry.Time)
if newEntry.Rlevel != NONE {
fmt.Fprintf(b, "[%s,%s] ", newEntry.Level.String(), newEntry.Rlevel.String())
} else {
fmt.Fprintf(b, "[%s] ", newEntry.Level.String())
}
appendValue(b, newEntry.Message)
for key, value := range newEntry.Data {
appendKeyValue(b, key, value)
}
b.WriteByte('\n')
s := bytes.NewBuffer(b.Bytes())
return s.String()
}
func appendValue(b *bytes.Buffer, value interface{}) {
if _, ok := value.(string); ok {
fmt.Fprintf(b, "%s ", value)
} else {
fmt.Fprintf(b, "%v ", value)
}
}
type keyvalueFormatter struct {
}
// ex. _time=2016-02-10T09:15:25.498-08:00 _level=INFO _msg=This is a message from test in key-value format
func (*keyvalueFormatter) format(newEntry *logEntry) string {
b := &bytes.Buffer{}
appendKeyValue(b, _TIME, newEntry.Time)
appendKeyValue(b, _LEVEL, newEntry.Level.String())
if newEntry.Rlevel != NONE {
appendKeyValue(b, _RLEVEL, newEntry.Rlevel.String())
}
appendKeyValue(b, _MSG, newEntry.Message)
for key, value := range newEntry.Data {
appendKeyValue(b, key, value)
}
b.WriteByte('\n')
s := bytes.NewBuffer(b.Bytes())
return s.String()
}
func appendKeyValue(b *bytes.Buffer, key, value interface{}) {
if _, ok := value.(string); ok {
fmt.Fprintf(b, "%v=%s ", key, value)
} else {
fmt.Fprintf(b, "%v=%v ", key, value)
}
}
type jsonFormatter struct {
}
// ex. {"_level":"INFO","_msg":"This is a message from test in json format","_time":"2016-02-10T09:12:59.518-08:00"}
func (*jsonFormatter) format(newEntry *logEntry) string {
if newEntry.Data == nil {
newEntry.Data = make(Map, 5)
}
newEntry.Data[_TIME] = newEntry.Time
newEntry.Data[_LEVEL] = newEntry.Level.String()
if newEntry.Rlevel != NONE {
newEntry.Data[_RLEVEL] = newEntry.Rlevel.String()
}
newEntry.Data[_MSG] = newEntry.Message
serialized, _ := json.Marshal(newEntry.Data)
s := bytes.NewBuffer(append(serialized, '\n'))
return s.String()
}

View File

@@ -0,0 +1,236 @@
// Copyright (c) 2016 Couchbase, 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 logging
import (
"bytes"
"fmt"
"io"
"os"
"strings"
"testing"
)
var buffer *bytes.Buffer
func setLogWriter(w io.Writer, lvl Level, fmtLogging LogEntryFormatter) {
logger = NewLogger(w, lvl, fmtLogging)
SetLogger(logger)
}
func TestStub(t *testing.T) {
logger := NewLogger(os.Stdout, DEBUG, KVFORMATTER)
SetLogger(logger)
logger.Infof("This is a message from %s", "test")
Infof("This is a message from %s", "test")
logger.Infop("This is a message from ", Pair{"name", "test"}, Pair{"Queue Size", 10}, Pair{"Debug Mode", false})
Infop("This is a message from ", Pair{"name", "test"})
logger.Infom("This is a message from ", Map{"name": "test", "Queue Size": 10, "Debug Mode": false})
Infom("This is a message from ", Map{"name": "test"})
logger.Requestf(WARN, "This is a Request from %s", "test")
Requestf(INFO, "This is a Request from %s", "test")
logger.Requestp(DEBUG, "This is a Request from ", Pair{"name", "test"})
Requestp(ERROR, "This is a Request from ", Pair{"name", "test"})
logger.SetLevel(WARN)
fmt.Printf("Log level is %s\n", logger.Level())
logger.Requestf(WARN, "This is a Request from %s", "test")
Requestf(INFO, "This is a Request from %s", "test")
logger.Requestp(DEBUG, "This is a Request from ", Pair{"name", "test"})
Requestp(ERROR, "This is a Request from ", Pair{"name", "test"})
logger.Warnf("This is a message from %s", "test")
Infof("This is a message from %s", "test")
logger.Debugp("This is a message from ", Pair{"name", "test"})
Errorp("This is a message from ", Pair{"name", "test"})
fmt.Printf("Changing to json formatter\n")
logger.entryFormatter = &jsonFormatter{}
logger.SetLevel(DEBUG)
logger.Infof("This is a message from %s", "test")
Infof("This is a message from %s", "test")
logger.Infop("This is a message from ", Pair{"name", "test"}, Pair{"Queue Size", 10}, Pair{"Debug Mode", false})
Infop("This is a message from ", Pair{"name", "test"})
logger.Infom("This is a message from ", Map{"name": "test", "Queue Size": 10, "Debug Mode": false})
Infom("This is a message from ", Map{"name": "test"})
logger.Requestf(WARN, "This is a Request from %s", "test")
Requestf(INFO, "This is a Request from %s", "test")
logger.Requestp(DEBUG, "This is a Request from ", Pair{"name", "test"})
Requestp(ERROR, "This is a Request from ", Pair{"name", "test"})
fmt.Printf("Changing to Text formatter\n")
logger.entryFormatter = &textFormatter{}
logger.SetLevel(DEBUG)
logger.Infof("This is a message from %s", "test")
Infof("This is a message from %s", "test")
logger.Infop("This is a message from ", Pair{"name", "test"}, Pair{"Queue Size", 10}, Pair{"Debug Mode", false})
Infop("This is a message from ", Pair{"name", "test"})
logger.Infom("This is a message from ", Map{"name": "test", "Queue Size": 10, "Debug Mode": false})
Infom("This is a message from ", Map{"name": "test"})
logger.Requestf(WARN, "This is a Request from %s", "test")
Requestf(INFO, "This is a Request from %s", "test")
logger.Requestp(DEBUG, "This is a Request from ", Pair{"name", "test"})
Requestp(ERROR, "This is a Request from ", Pair{"name", "test"})
buffer.Reset()
logger = NewLogger(buffer, DEBUG, KVFORMATTER)
logger.Infof("This is a message from test in key-value format")
if s := string(buffer.Bytes()); strings.Contains(s, "_msg=This is a message from test in key-value format") == false {
t.Errorf("Infof() failed %v", s)
}
buffer.Reset()
logger.entryFormatter = &jsonFormatter{}
logger.Infof("This is a message from test in jason format")
if s := string(buffer.Bytes()); strings.Contains(s, "\"_msg\":\"This is a message from test in jason format\"") == false {
t.Errorf("Infof() failed %v", s)
}
buffer.Reset()
logger.entryFormatter = &textFormatter{}
logger.Infof("This is a message from test in text format")
if s := string(buffer.Bytes()); strings.Contains(s, "[INFO] This is a message from test in text format") == false {
t.Errorf("Infof() failed %v", s)
}
}
func init() {
buffer = bytes.NewBuffer([]byte{})
buffer.Reset()
}
func TestLogNone(t *testing.T) {
buffer.Reset()
setLogWriter(buffer, DEBUG, KVFORMATTER)
Warnf("%s", "test")
if s := string(buffer.Bytes()); strings.Contains(s, "test") == false {
t.Errorf("Warnf() failed %v", s)
}
SetLevel(NONE)
Warnf("test")
if s := string(buffer.Bytes()); s == "" {
t.Errorf("Warnf() failed %v", s)
}
}
func TestLogLevelDefault(t *testing.T) {
buffer.Reset()
setLogWriter(buffer, INFO, KVFORMATTER)
SetLevel(INFO)
Warnf("%s", "warn")
Errorf("error")
Severef("severe")
Infof("info")
Debugf("debug")
Tracef("trace")
s := string(buffer.Bytes())
if strings.Contains(s, "warn") == false {
t.Errorf("Warnf() failed %v", s)
} else if strings.Contains(s, "error") == false {
t.Errorf("Errorf() failed %v", s)
} else if strings.Contains(s, "severe") == false {
t.Errorf("Severef() failed %v", s)
} else if strings.Contains(s, "info") == false {
t.Errorf("Infof() failed %v", s)
} else if strings.Contains(s, "debug") == true {
t.Errorf("Debugf() failed %v", s)
} else if strings.Contains(s, "trace") == true {
t.Errorf("Tracef() failed %v", s)
}
setLogWriter(os.Stdout, INFO, KVFORMATTER)
}
func TestLogLevelInfo(t *testing.T) {
buffer.Reset()
setLogWriter(buffer, INFO, KVFORMATTER)
Warnf("warn")
Infof("info")
Debugf("debug")
Tracef("trace")
s := string(buffer.Bytes())
if strings.Contains(s, "warn") == false {
t.Errorf("Warnf() failed %v", s)
} else if strings.Contains(s, "info") == false {
t.Errorf("Infof() failed %v", s)
} else if strings.Contains(s, "debug") == true {
t.Errorf("Debugf() failed %v", s)
} else if strings.Contains(s, "trace") == true {
t.Errorf("Tracef() failed %v", s)
}
setLogWriter(os.Stdout, INFO, KVFORMATTER)
}
func TestLogLevelDebug(t *testing.T) {
buffer.Reset()
setLogWriter(buffer, DEBUG, KVFORMATTER)
Warnf("warn")
Infof("info")
Debugf("debug")
Tracef("trace")
s := string(buffer.Bytes())
if strings.Contains(s, "warn") == false {
t.Errorf("Warnf() failed %v", s)
} else if strings.Contains(s, "info") == false {
t.Errorf("Infof() failed %v", s)
} else if strings.Contains(s, "debug") == false {
t.Errorf("Debugf() failed %v", s)
} else if strings.Contains(s, "trace") == false {
t.Errorf("Tracef() failed %v", s)
}
setLogWriter(os.Stdout, INFO, KVFORMATTER)
}
func TestLogLevelTrace(t *testing.T) {
buffer.Reset()
setLogWriter(buffer, TRACE, KVFORMATTER)
Warnf("warn")
Infof("info")
Debugf("debug")
Tracef("trace")
s := string(buffer.Bytes())
if strings.Contains(s, "warn") == false {
t.Errorf("Warnf() failed %v", s)
} else if strings.Contains(s, "info") == false {
t.Errorf("Infof() failed %v", s)
} else if strings.Contains(s, "debug") == true {
t.Errorf("Debugf() failed %v", s)
} else if strings.Contains(s, "trace") == false {
t.Errorf("Tracef() failed %v", s)
}
setLogWriter(os.Stdout, INFO, KVFORMATTER)
}
func TestDefaultLog(t *testing.T) {
buffer.Reset()
setLogWriter(buffer, TRACE, KVFORMATTER)
sl := logger
sl.Warnf("warn")
sl.Infof("info")
sl.Debugf("debug")
sl.Tracef("trace")
s := string(buffer.Bytes())
if strings.Contains(s, "warn") == false {
t.Errorf("Warnf() failed %v", s)
} else if strings.Contains(s, "info") == false {
t.Errorf("Infof() failed %v", s)
} else if strings.Contains(s, "trace") == false {
t.Errorf("Tracef() failed %v", s)
} else if strings.Contains(s, "debug") == true {
t.Errorf("Debugf() failed %v", s)
}
setLogWriter(os.Stdout, INFO, KVFORMATTER)
}

View File

@@ -0,0 +1,15 @@
// Copyright (c) 2016 Couchbase, 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 platform
func HideConsole(_ bool) {
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) 2013 Couchbase, 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 platform
import "syscall"
// Hide console on windows without removing it unlike -H windowsgui.
func HideConsole(hide bool) {
var k32 = syscall.NewLazyDLL("kernel32.dll")
var cw = k32.NewProc("GetConsoleWindow")
var u32 = syscall.NewLazyDLL("user32.dll")
var sw = u32.NewProc("ShowWindow")
hwnd, _, _ := cw.Call()
if hwnd == 0 {
return
}
if hide {
var SW_HIDE uintptr = 0
sw.Call(hwnd, SW_HIDE)
} else {
var SW_RESTORE uintptr = 9
sw.Call(hwnd, SW_RESTORE)
}
}