http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_constraints.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/common_constraints.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_constraints.go
new file mode 100644
index 0000000..7ec2fe5
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_constraints.go
@@ -0,0 +1,162 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "errors"
+       "fmt"
+       "strings"
+)
+
+// Represents constraints which form a general rule for log levels selection
+type logLevelConstraints interface {
+       IsAllowed(level LogLevel) bool
+}
+
+// A minMaxConstraints represents constraints which use minimal and maximal 
allowed log levels.
+type minMaxConstraints struct {
+       min LogLevel
+       max LogLevel
+}
+
+// NewMinMaxConstraints creates a new minMaxConstraints struct with the 
specified min and max levels.
+func NewMinMaxConstraints(min LogLevel, max LogLevel) (*minMaxConstraints, 
error) {
+       if min > max {
+               return nil, fmt.Errorf("min level can't be greater than max. 
Got min: %d, max: %d", min, max)
+       }
+       if min < TraceLvl || min > CriticalLvl {
+               return nil, fmt.Errorf("min level can't be less than Trace or 
greater than Critical. Got min: %d", min)
+       }
+       if max < TraceLvl || max > CriticalLvl {
+               return nil, fmt.Errorf("max level can't be less than Trace or 
greater than Critical. Got max: %d", max)
+       }
+
+       return &minMaxConstraints{min, max}, nil
+}
+
+// IsAllowed returns true, if log level is in [min, max] range (inclusive).
+func (minMaxConstr *minMaxConstraints) IsAllowed(level LogLevel) bool {
+       return level >= minMaxConstr.min && level <= minMaxConstr.max
+}
+
+func (minMaxConstr *minMaxConstraints) String() string {
+       return fmt.Sprintf("Min: %s. Max: %s", minMaxConstr.min, 
minMaxConstr.max)
+}
+
+//=======================================================
+
+// A listConstraints represents constraints which use allowed log levels list.
+type listConstraints struct {
+       allowedLevels map[LogLevel]bool
+}
+
+// NewListConstraints creates a new listConstraints struct with the specified 
allowed levels.
+func NewListConstraints(allowList []LogLevel) (*listConstraints, error) {
+       if allowList == nil {
+               return nil, errors.New("list can't be nil")
+       }
+
+       allowLevels, err := createMapFromList(allowList)
+       if err != nil {
+               return nil, err
+       }
+       err = validateOffLevel(allowLevels)
+       if err != nil {
+               return nil, err
+       }
+
+       return &listConstraints{allowLevels}, nil
+}
+
+func (listConstr *listConstraints) String() string {
+       allowedList := "List: "
+
+       listLevel := make([]string, len(listConstr.allowedLevels))
+
+       var logLevel LogLevel
+       i := 0
+       for logLevel = TraceLvl; logLevel <= Off; logLevel++ {
+               if listConstr.allowedLevels[logLevel] {
+                       listLevel[i] = logLevel.String()
+                       i++
+               }
+       }
+
+       allowedList += strings.Join(listLevel, ",")
+
+       return allowedList
+}
+
+func createMapFromList(allowedList []LogLevel) (map[LogLevel]bool, error) {
+       allowedLevels := make(map[LogLevel]bool, 0)
+       for _, level := range allowedList {
+               if level < TraceLvl || level > Off {
+                       return nil, fmt.Errorf("level can't be less than Trace 
or greater than Critical. Got level: %d", level)
+               }
+               allowedLevels[level] = true
+       }
+       return allowedLevels, nil
+}
+func validateOffLevel(allowedLevels map[LogLevel]bool) error {
+       if _, ok := allowedLevels[Off]; ok && len(allowedLevels) > 1 {
+               return errors.New("logLevel Off cant be mixed with other 
levels")
+       }
+
+       return nil
+}
+
+// IsAllowed returns true, if log level is in allowed log levels list.
+// If the list contains the only item 'common.Off' then IsAllowed will always 
return false for any input values.
+func (listConstr *listConstraints) IsAllowed(level LogLevel) bool {
+       for l := range listConstr.allowedLevels {
+               if l == level && level != Off {
+                       return true
+               }
+       }
+
+       return false
+}
+
+// AllowedLevels returns allowed levels configuration as a map.
+func (listConstr *listConstraints) AllowedLevels() map[LogLevel]bool {
+       return listConstr.allowedLevels
+}
+
+//=======================================================
+
+type offConstraints struct {
+}
+
+func NewOffConstraints() (*offConstraints, error) {
+       return &offConstraints{}, nil
+}
+
+func (offConstr *offConstraints) IsAllowed(level LogLevel) bool {
+       return false
+}
+
+func (offConstr *offConstraints) String() string {
+       return "Off constraint"
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_constraints_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/common_constraints_test.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_constraints_test.go
new file mode 100644
index 0000000..bb9918e
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_constraints_test.go
@@ -0,0 +1,196 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "testing"
+)
+
+func TestInvalidminMaxConstraints(t *testing.T) {
+       constr, err := NewMinMaxConstraints(CriticalLvl, WarnLvl)
+
+       if err == nil || constr != nil {
+               t.Errorf("expected an error and a nil value for minmax 
constraints: min = %d, max = %d. Got: %v, %v",
+                       CriticalLvl, WarnLvl, err, constr)
+               return
+       }
+}
+
+func TestInvalidLogLevels(t *testing.T) {
+       var invalidMin uint8 = 123
+       var invalidMax uint8 = 124
+       minMaxConstr, errMinMax := NewMinMaxConstraints(LogLevel(invalidMin), 
LogLevel(invalidMax))
+
+       if errMinMax == nil || minMaxConstr != nil {
+               t.Errorf("expected an error and a nil value for minmax 
constraints: min = %d, max = %d. Got: %v, %v",
+                       invalidMin, invalidMax, errMinMax, minMaxConstr)
+               return
+       }
+
+       invalidList := []LogLevel{145}
+
+       listConstr, errList := NewListConstraints(invalidList)
+
+       if errList == nil || listConstr != nil {
+               t.Errorf("expected an error and a nil value for constraints 
list: %v. Got: %v, %v",
+                       invalidList, errList, listConstr)
+               return
+       }
+}
+
+func TestlistConstraintsWithDuplicates(t *testing.T) {
+       duplicateList := []LogLevel{TraceLvl, DebugLvl, InfoLvl,
+               WarnLvl, ErrorLvl, CriticalLvl, CriticalLvl, CriticalLvl}
+
+       listConstr, errList := NewListConstraints(duplicateList)
+
+       if errList != nil || listConstr == nil {
+               t.Errorf("expected a valid constraints list struct for: %v, got 
error: %v, value: %v",
+                       duplicateList, errList, listConstr)
+               return
+       }
+
+       listLevels := listConstr.AllowedLevels()
+
+       if listLevels == nil {
+               t.Fatalf("listConstr.AllowedLevels() == nil")
+               return
+       }
+
+       if len(listLevels) != 6 {
+               t.Errorf("expected: listConstr.AllowedLevels() length == 6. 
Got: %d", len(listLevels))
+               return
+       }
+}
+
+func TestlistConstraintsWithOffInList(t *testing.T) {
+       offList := []LogLevel{TraceLvl, DebugLvl, Off}
+
+       listConstr, errList := NewListConstraints(offList)
+
+       if errList == nil || listConstr != nil {
+               t.Errorf("expected an error and a nil value for constraints 
list with 'Off':  %v. Got: %v, %v",
+                       offList, errList, listConstr)
+               return
+       }
+}
+
+type logLevelTestCase struct {
+       level   LogLevel
+       allowed bool
+}
+
+var minMaxTests = []logLevelTestCase{
+       {TraceLvl, false},
+       {DebugLvl, false},
+       {InfoLvl, true},
+       {WarnLvl, true},
+       {ErrorLvl, false},
+       {CriticalLvl, false},
+       {123, false},
+       {6, false},
+}
+
+func TestValidminMaxConstraints(t *testing.T) {
+
+       constr, err := NewMinMaxConstraints(InfoLvl, WarnLvl)
+
+       if err != nil || constr == nil {
+               t.Errorf("expected a valid constraints struct for minmax 
constraints: min = %d, max = %d. Got: %v, %v",
+                       InfoLvl, WarnLvl, err, constr)
+               return
+       }
+
+       for _, minMaxTest := range minMaxTests {
+               allowed := constr.IsAllowed(minMaxTest.level)
+               if allowed != minMaxTest.allowed {
+                       t.Errorf("expected IsAllowed() = %t for level = %d. 
Got: %t",
+                               minMaxTest.allowed, minMaxTest.level, allowed)
+                       return
+               }
+       }
+}
+
+var listTests = []logLevelTestCase{
+       {TraceLvl, true},
+       {DebugLvl, false},
+       {InfoLvl, true},
+       {WarnLvl, true},
+       {ErrorLvl, false},
+       {CriticalLvl, true},
+       {123, false},
+       {6, false},
+}
+
+func TestValidlistConstraints(t *testing.T) {
+       validList := []LogLevel{TraceLvl, InfoLvl, WarnLvl, CriticalLvl}
+       constr, err := NewListConstraints(validList)
+
+       if err != nil || constr == nil {
+               t.Errorf("expected a valid constraints list struct for: %v. Got 
error: %v, value: %v",
+                       validList, err, constr)
+               return
+       }
+
+       for _, minMaxTest := range listTests {
+               allowed := constr.IsAllowed(minMaxTest.level)
+               if allowed != minMaxTest.allowed {
+                       t.Errorf("expected IsAllowed() = %t for level = %d. 
Got: %t",
+                               minMaxTest.allowed, minMaxTest.level, allowed)
+                       return
+               }
+       }
+}
+
+var offTests = []logLevelTestCase{
+       {TraceLvl, false},
+       {DebugLvl, false},
+       {InfoLvl, false},
+       {WarnLvl, false},
+       {ErrorLvl, false},
+       {CriticalLvl, false},
+       {123, false},
+       {6, false},
+}
+
+func TestValidListoffConstraints(t *testing.T) {
+       validList := []LogLevel{Off}
+       constr, err := NewListConstraints(validList)
+
+       if err != nil || constr == nil {
+               t.Errorf("expected a valid constraints list struct for: %v. Got 
error: %v, value: %v",
+                       validList, err, constr)
+               return
+       }
+
+       for _, minMaxTest := range offTests {
+               allowed := constr.IsAllowed(minMaxTest.level)
+               if allowed != minMaxTest.allowed {
+                       t.Errorf("expected IsAllowed() = %t for level = %d. 
Got: %t",
+                               minMaxTest.allowed, minMaxTest.level, allowed)
+                       return
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_context.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/common_context.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_context.go
new file mode 100644
index 0000000..04bc223
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_context.go
@@ -0,0 +1,194 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "fmt"
+       "os"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "time"
+)
+
+var workingDir = "/"
+
+func init() {
+       wd, err := os.Getwd()
+       if err == nil {
+               workingDir = filepath.ToSlash(wd) + "/"
+       }
+}
+
+// Represents runtime caller context.
+type LogContextInterface interface {
+       // Caller's function name.
+       Func() string
+       // Caller's line number.
+       Line() int
+       // Caller's file short path (in slashed form).
+       ShortPath() string
+       // Caller's file full path (in slashed form).
+       FullPath() string
+       // Caller's file name (without path).
+       FileName() string
+       // True if the context is correct and may be used.
+       // If false, then an error in context evaluation occurred and
+       // all its other data may be corrupted.
+       IsValid() bool
+       // Time when log function was called.
+       CallTime() time.Time
+       // Custom context that can be set by calling logger.SetContext
+       CustomContext() interface{}
+}
+
+// Returns context of the caller
+func currentContext(custom interface{}) (LogContextInterface, error) {
+       return specifyContext(1, custom)
+}
+
+func extractCallerInfo(skip int) (fullPath string, shortPath string, funcName 
string, line int, err error) {
+       pc, fp, ln, ok := runtime.Caller(skip)
+       if !ok {
+               err = fmt.Errorf("error during runtime.Caller")
+               return
+       }
+       line = ln
+       fullPath = fp
+       if strings.HasPrefix(fp, workingDir) {
+               shortPath = fp[len(workingDir):]
+       } else {
+               shortPath = fp
+       }
+       funcName = runtime.FuncForPC(pc).Name()
+       if strings.HasPrefix(funcName, workingDir) {
+               funcName = funcName[len(workingDir):]
+       }
+       return
+}
+
+// Returns context of the function with placed "skip" stack frames of the 
caller
+// If skip == 0 then behaves like currentContext
+// Context is returned in any situation, even if error occurs. But, if an error
+// occurs, the returned context is an error context, which contains no paths
+// or names, but states that they can't be extracted.
+func specifyContext(skip int, custom interface{}) (LogContextInterface, error) 
{
+       callTime := time.Now()
+       if skip < 0 {
+               err := fmt.Errorf("can not skip negative stack frames")
+               return &errorContext{callTime, err}, err
+       }
+       fullPath, shortPath, funcName, line, err := extractCallerInfo(skip + 2)
+       if err != nil {
+               return &errorContext{callTime, err}, err
+       }
+       _, fileName := filepath.Split(fullPath)
+       return &logContext{funcName, line, shortPath, fullPath, fileName, 
callTime, custom}, nil
+}
+
+// Represents a normal runtime caller context.
+type logContext struct {
+       funcName  string
+       line      int
+       shortPath string
+       fullPath  string
+       fileName  string
+       callTime  time.Time
+       custom    interface{}
+}
+
+func (context *logContext) IsValid() bool {
+       return true
+}
+
+func (context *logContext) Func() string {
+       return context.funcName
+}
+
+func (context *logContext) Line() int {
+       return context.line
+}
+
+func (context *logContext) ShortPath() string {
+       return context.shortPath
+}
+
+func (context *logContext) FullPath() string {
+       return context.fullPath
+}
+
+func (context *logContext) FileName() string {
+       return context.fileName
+}
+
+func (context *logContext) CallTime() time.Time {
+       return context.callTime
+}
+
+func (context *logContext) CustomContext() interface{} {
+       return context.custom
+}
+
+// Represents an error context
+type errorContext struct {
+       errorTime time.Time
+       err       error
+}
+
+func (errContext *errorContext) getErrorText(prefix string) string {
+       return fmt.Sprintf("%s() error: %s", prefix, errContext.err)
+}
+
+func (errContext *errorContext) IsValid() bool {
+       return false
+}
+
+func (errContext *errorContext) Line() int {
+       return -1
+}
+
+func (errContext *errorContext) Func() string {
+       return errContext.getErrorText("Func")
+}
+
+func (errContext *errorContext) ShortPath() string {
+       return errContext.getErrorText("ShortPath")
+}
+
+func (errContext *errorContext) FullPath() string {
+       return errContext.getErrorText("FullPath")
+}
+
+func (errContext *errorContext) FileName() string {
+       return errContext.getErrorText("FileName")
+}
+
+func (errContext *errorContext) CallTime() time.Time {
+       return errContext.errorTime
+}
+
+func (errContext *errorContext) CustomContext() interface{} {
+       return nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_context_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/common_context_test.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_context_test.go
new file mode 100644
index 0000000..bd1e47a
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_context_test.go
@@ -0,0 +1,127 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "os"
+       "path/filepath"
+       "strings"
+       "testing"
+)
+
+const (
+       testShortPath = "common_context_test.go"
+)
+
+var (
+       commonPrefix string
+       testFullPath string
+)
+
+func init() {
+       // Here we remove the hardcoding of the package name which
+       // may break forks and some CI environments such as jenkins.
+       _, _, funcName, _, _ := extractCallerInfo(1)
+       preIndex := strings.Index(funcName, "init·")
+       if preIndex == -1 {
+               preIndex = strings.Index(funcName, "init")
+       }
+       commonPrefix = funcName[:preIndex]
+       wd, err := os.Getwd()
+       if err == nil {
+               // Transform the file path into a slashed form:
+               // This is the proper platform-neutral way.
+               testFullPath = filepath.ToSlash(filepath.Join(wd, 
testShortPath))
+       }
+}
+
+func TestContext(t *testing.T) {
+       context, err := currentContext(nil)
+       if err != nil {
+               t.Fatalf("unexpected error: %s", err)
+       }
+       if context == nil {
+               t.Fatalf("unexpected error: context is nil")
+       }
+       if fn, funcName := context.Func(), commonPrefix+"TestContext"; fn != 
funcName {
+               // Account for a case when the func full path is longer than 
commonPrefix but includes it.
+               if !strings.HasSuffix(fn, funcName) {
+                       t.Errorf("expected context.Func == %s ; got %s", 
funcName, context.Func())
+               }
+       }
+       if context.ShortPath() != testShortPath {
+               t.Errorf("expected context.ShortPath == %s ; got %s", 
testShortPath, context.ShortPath())
+       }
+       if len(testFullPath) == 0 {
+               t.Fatal("working directory seems invalid")
+       }
+       if context.FullPath() != testFullPath {
+               t.Errorf("expected context.FullPath == %s ; got %s", 
testFullPath, context.FullPath())
+       }
+}
+
+func innerContext() (context LogContextInterface, err error) {
+       return currentContext(nil)
+}
+
+func TestInnerContext(t *testing.T) {
+       context, err := innerContext()
+       if err != nil {
+               t.Fatalf("unexpected error: %s", err)
+       }
+       if context == nil {
+               t.Fatalf("unexpected error: context is nil")
+       }
+       if fn, funcName := context.Func(), commonPrefix+"innerContext"; fn != 
funcName {
+               // Account for a case when the func full path is longer than 
commonPrefix but includes it.
+               if !strings.HasSuffix(fn, funcName) {
+                       t.Errorf("expected context.Func == %s ; got %s", 
funcName, context.Func())
+               }
+       }
+       if context.ShortPath() != testShortPath {
+               t.Errorf("expected context.ShortPath == %s ; got %s", 
testShortPath, context.ShortPath())
+       }
+       if len(testFullPath) == 0 {
+               t.Fatal("working directory seems invalid")
+       }
+       if context.FullPath() != testFullPath {
+               t.Errorf("expected context.FullPath == %s ; got %s", 
testFullPath, context.FullPath())
+       }
+}
+
+type testContext struct {
+       field string
+}
+
+func TestCustomContext(t *testing.T) {
+       expected := "testStr"
+       context, err := currentContext(&testContext{expected})
+       if err != nil {
+               t.Fatalf("unexpected error: %s", err)
+       }
+       if st, _ := context.CustomContext().(*testContext); st.field != 
expected {
+               t.Errorf("expected context.CustomContext == %s ; got %s", 
expected, st.field)
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_exception.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/common_exception.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_exception.go
new file mode 100644
index 0000000..9acc275
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_exception.go
@@ -0,0 +1,194 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "errors"
+       "fmt"
+       "regexp"
+       "strings"
+)
+
+// Used in rules creation to validate input file and func filters
+var (
+       fileFormatValidator = regexp.MustCompile(`[a-zA-Z0-9\\/ _\*\.]*`)
+       funcFormatValidator = regexp.MustCompile(`[a-zA-Z0-9_\*\.]*`)
+)
+
+// LogLevelException represents an exceptional case used when you need some 
specific files or funcs to
+// override general constraints and to use their own.
+type LogLevelException struct {
+       funcPatternParts []string
+       filePatternParts []string
+
+       funcPattern string
+       filePattern string
+
+       constraints logLevelConstraints
+}
+
+// NewLogLevelException creates a new exception.
+func NewLogLevelException(funcPattern string, filePattern string, constraints 
logLevelConstraints) (*LogLevelException, error) {
+       if constraints == nil {
+               return nil, errors.New("constraints can not be nil")
+       }
+
+       exception := new(LogLevelException)
+
+       err := exception.initFuncPatternParts(funcPattern)
+       if err != nil {
+               return nil, err
+       }
+       exception.funcPattern = strings.Join(exception.funcPatternParts, "")
+
+       err = exception.initFilePatternParts(filePattern)
+       if err != nil {
+               return nil, err
+       }
+       exception.filePattern = strings.Join(exception.filePatternParts, "")
+
+       exception.constraints = constraints
+
+       return exception, nil
+}
+
+// MatchesContext returns true if context matches the patterns of this 
LogLevelException
+func (logLevelEx *LogLevelException) MatchesContext(context 
LogContextInterface) bool {
+       return logLevelEx.match(context.Func(), context.FullPath())
+}
+
+// IsAllowed returns true if log level is allowed according to the constraints 
of this LogLevelException
+func (logLevelEx *LogLevelException) IsAllowed(level LogLevel) bool {
+       return logLevelEx.constraints.IsAllowed(level)
+}
+
+// FuncPattern returns the function pattern of a exception
+func (logLevelEx *LogLevelException) FuncPattern() string {
+       return logLevelEx.funcPattern
+}
+
+// FuncPattern returns the file pattern of a exception
+func (logLevelEx *LogLevelException) FilePattern() string {
+       return logLevelEx.filePattern
+}
+
+// initFuncPatternParts checks whether the func filter has a correct format 
and splits funcPattern on parts
+func (logLevelEx *LogLevelException) initFuncPatternParts(funcPattern string) 
(err error) {
+
+       if funcFormatValidator.FindString(funcPattern) != funcPattern {
+               return errors.New("func path \"" + funcPattern + "\" contains 
incorrect symbols. Only a-z A-Z 0-9 _ * . allowed)")
+       }
+
+       logLevelEx.funcPatternParts = splitPattern(funcPattern)
+       return nil
+}
+
+// Checks whether the file filter has a correct format and splits file 
patterns using splitPattern.
+func (logLevelEx *LogLevelException) initFilePatternParts(filePattern string) 
(err error) {
+
+       if fileFormatValidator.FindString(filePattern) != filePattern {
+               return errors.New("file path \"" + filePattern + "\" contains 
incorrect symbols. Only a-z A-Z 0-9 \\ / _ * . allowed)")
+       }
+
+       logLevelEx.filePatternParts = splitPattern(filePattern)
+       return err
+}
+
+func (logLevelEx *LogLevelException) match(funcPath string, filePath string) 
bool {
+       if !stringMatchesPattern(logLevelEx.funcPatternParts, funcPath) {
+               return false
+       }
+       return stringMatchesPattern(logLevelEx.filePatternParts, filePath)
+}
+
+func (logLevelEx *LogLevelException) String() string {
+       str := fmt.Sprintf("Func: %s File: %s", logLevelEx.funcPattern, 
logLevelEx.filePattern)
+
+       if logLevelEx.constraints != nil {
+               str += fmt.Sprintf("Constr: %s", logLevelEx.constraints)
+       } else {
+               str += "nil"
+       }
+
+       return str
+}
+
+// splitPattern splits pattern into strings and asterisks. Example: 
"ab*cde**f" -> ["ab", "*", "cde", "*", "f"]
+func splitPattern(pattern string) []string {
+       var patternParts []string
+       var lastChar rune
+       for _, char := range pattern {
+               if char == '*' {
+                       if lastChar != '*' {
+                               patternParts = append(patternParts, "*")
+                       }
+               } else {
+                       if len(patternParts) != 0 && lastChar != '*' {
+                               patternParts[len(patternParts)-1] += 
string(char)
+                       } else {
+                               patternParts = append(patternParts, 
string(char))
+                       }
+               }
+               lastChar = char
+       }
+
+       return patternParts
+}
+
+// stringMatchesPattern check whether testString matches pattern with 
asterisks.
+// Standard regexp functionality is not used here because of performance 
issues.
+func stringMatchesPattern(patternparts []string, testString string) bool {
+       if len(patternparts) == 0 {
+               return len(testString) == 0
+       }
+
+       part := patternparts[0]
+       if part != "*" {
+               index := strings.Index(testString, part)
+               if index == 0 {
+                       return stringMatchesPattern(patternparts[1:], 
testString[len(part):])
+               }
+       } else {
+               if len(patternparts) == 1 {
+                       return true
+               }
+
+               newTestString := testString
+               part = patternparts[1]
+               for {
+                       index := strings.Index(newTestString, part)
+                       if index == -1 {
+                               break
+                       }
+
+                       newTestString = newTestString[index+len(part):]
+                       result := stringMatchesPattern(patternparts[2:], 
newTestString)
+                       if result {
+                               return true
+                       }
+               }
+       }
+       return false
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_exception_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/common_exception_test.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_exception_test.go
new file mode 100644
index 0000000..d98c280
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_exception_test.go
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "testing"
+)
+
+type exceptionTestCase struct {
+       funcPattern string
+       filePattern string
+       funcName    string
+       fileName    string
+       match       bool
+}
+
+var exceptionTestCases = []exceptionTestCase{
+       {"*", "*", "func", "file", true},
+       {"func*", "*", "func", "file", true},
+       {"*func", "*", "func", "file", true},
+       {"*func", "*", "1func", "file", true},
+       {"func*", "*", "func1", "file", true},
+       {"fu*nc", "*", "func", "file", true},
+       {"fu*nc", "*", "fu1nc", "file", true},
+       {"fu*nc", "*", "func1nc", "file", true},
+       {"*fu*nc*", "*", "somefuntonc", "file", true},
+       {"fu*nc", "*", "f1nc", "file", false},
+       {"func*", "*", "fun", "file", false},
+       {"fu*nc", "*", "func1n", "file", false},
+       {"**f**u**n**c**", "*", "func1n", "file", true},
+}
+
+func TestMatchingCorrectness(t *testing.T) {
+       constraints, err := NewListConstraints([]LogLevel{TraceLvl})
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       for _, testCase := range exceptionTestCases {
+               rule, ruleError := NewLogLevelException(testCase.funcPattern, 
testCase.filePattern, constraints)
+               if ruleError != nil {
+                       t.Fatalf("Unexpected error on rule creation: [ %v, %v 
]. %v",
+                               testCase.funcPattern, testCase.filePattern, 
ruleError)
+               }
+
+               match := rule.match(testCase.funcName, testCase.fileName)
+               if match != testCase.match {
+                       t.Errorf("incorrect matching for [ %v, %v ] [ %v, %v ] 
Expected: %t. Got: %t",
+                               testCase.funcPattern, testCase.filePattern, 
testCase.funcName, testCase.fileName, testCase.match, match)
+               }
+       }
+}
+
+func TestAsterisksReducing(t *testing.T) {
+       constraints, err := NewListConstraints([]LogLevel{TraceLvl})
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       rule, err := NewLogLevelException("***func**", "fi*****le", constraints)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+       expectFunc := "*func*"
+       if rule.FuncPattern() != expectFunc {
+               t.Errorf("asterisks must be reduced. Expect:%v, Got:%v", 
expectFunc, rule.FuncPattern())
+       }
+
+       expectFile := "fi*le"
+       if rule.FilePattern() != expectFile {
+               t.Errorf("asterisks must be reduced. Expect:%v, Got:%v", 
expectFile, rule.FilePattern())
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_flusher.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/common_flusher.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_flusher.go
new file mode 100644
index 0000000..0ef077c
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_flusher.go
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+// flusherInterface represents all objects that have to do cleanup
+// at certain moments of time (e.g. before app shutdown to avoid data loss)
+type flusherInterface interface {
+       Flush()
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/common_loglevel.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/common_loglevel.go 
b/traffic_stats/vendor/github.com/cihub/seelog/common_loglevel.go
new file mode 100644
index 0000000..d54ecf2
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/common_loglevel.go
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+// Log level type
+type LogLevel uint8
+
+// Log levels
+const (
+       TraceLvl = iota
+       DebugLvl
+       InfoLvl
+       WarnLvl
+       ErrorLvl
+       CriticalLvl
+       Off
+)
+
+// Log level string representations (used in configuration files)
+const (
+       TraceStr    = "trace"
+       DebugStr    = "debug"
+       InfoStr     = "info"
+       WarnStr     = "warn"
+       ErrorStr    = "error"
+       CriticalStr = "critical"
+       OffStr      = "off"
+)
+
+var levelToStringRepresentations = map[LogLevel]string{
+       TraceLvl:    TraceStr,
+       DebugLvl:    DebugStr,
+       InfoLvl:     InfoStr,
+       WarnLvl:     WarnStr,
+       ErrorLvl:    ErrorStr,
+       CriticalLvl: CriticalStr,
+       Off:         OffStr,
+}
+
+// LogLevelFromString parses a string and returns a corresponding log level, 
if sucessfull.
+func LogLevelFromString(levelStr string) (level LogLevel, found bool) {
+       for lvl, lvlStr := range levelToStringRepresentations {
+               if lvlStr == levelStr {
+                       return lvl, true
+               }
+       }
+
+       return 0, false
+}
+
+// LogLevelToString returns seelog string representation for a specified 
level. Returns "" for invalid log levels.
+func (level LogLevel) String() string {
+       levelStr, ok := levelToStringRepresentations[level]
+       if ok {
+               return levelStr
+       }
+
+       return ""
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_custom.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_custom.go 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_custom.go
new file mode 100644
index 0000000..383a770
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_custom.go
@@ -0,0 +1,242 @@
+// Copyright (c) 2013 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "errors"
+       "fmt"
+       "reflect"
+       "sort"
+)
+
+var registeredReceivers = make(map[string]reflect.Type)
+
+// RegisterReceiver records a custom receiver type, identified by a value
+// of that type (second argument), under the specified name. Registered
+// names can be used in the "name" attribute of <custom> config items.
+//
+// RegisterReceiver takes the type of the receiver argument, without taking
+// the value into the account. So do NOT enter any data to the second argument
+// and only call it like:
+//     RegisterReceiver("somename", &MyReceiverType{})
+//
+// After that, when a '<custom>' config tag with this name is used,
+// a receiver of the specified type would be instantiated. Check
+// CustomReceiver comments for interface details.
+//
+// NOTE 1: RegisterReceiver fails if you attempt to register different types
+// with the same name.
+//
+// NOTE 2: RegisterReceiver registers those receivers that must be used in
+// the configuration files (<custom> items). Basically it is just the way
+// you tell seelog config parser what should it do when it meets a
+// <custom> tag with a specific name and data attributes.
+//
+// But If you are only using seelog as a proxy to an already instantiated
+// CustomReceiver (via LoggerFromCustomReceiver func), you should not call 
RegisterReceiver.
+func RegisterReceiver(name string, receiver CustomReceiver) {
+       newType := reflect.TypeOf(reflect.ValueOf(receiver).Elem().Interface())
+       if t, ok := registeredReceivers[name]; ok && t != newType {
+               panic(fmt.Sprintf("duplicate types for %s: %s != %s", name, t, 
newType))
+       }
+       registeredReceivers[name] = newType
+}
+
+func customReceiverByName(name string) (creceiver CustomReceiver, err error) {
+       rt, ok := registeredReceivers[name]
+       if !ok {
+               return nil, fmt.Errorf("custom receiver name not registered: 
'%s'", name)
+       }
+       v, ok := reflect.New(rt).Interface().(CustomReceiver)
+       if !ok {
+               return nil, fmt.Errorf("cannot instantiate receiver with 
name='%s'", name)
+       }
+       return v, nil
+}
+
+// CustomReceiverInitArgs represent arguments passed to the CustomReceiver.Init
+// func when custom receiver is being initialized.
+type CustomReceiverInitArgs struct {
+       // XmlCustomAttrs represent '<custom>' xml config item attributes that
+       // start with "data-". Map keys will be the attribute names without the 
"data-".
+       // Map values will the those attribute values.
+       //
+       // E.g. if you have a '<custom name="somename" data-attr1="a1" 
data-attr2="a2"/>'
+       // you will get map with 2 key-value pairs: "attr1"->"a1", "attr2"->"a2"
+       //
+       // Note that in custom items you can only use allowed attributes, like 
"name" and
+       // your custom attributes, starting with "data-". Any other will lead 
to a
+       // parsing error.
+       XmlCustomAttrs map[string]string
+}
+
+// CustomReceiver is the interface that external custom seelog message 
receivers
+// must implement in order to be able to process seelog messages. Those 
receivers
+// are set in the xml config file using the <custom> tag. Check receivers 
reference
+// wiki section on that.
+//
+// Use seelog.RegisterReceiver on the receiver type before using it.
+type CustomReceiver interface {
+       // ReceiveMessage is called when the custom receiver gets seelog 
message from
+       // a parent dispatcher.
+       //
+       // Message, level and context args represent all data that was included 
in the seelog
+       // message at the time it was logged.
+       //
+       // The formatting is already applied to the message and depends on the 
config
+       // like with any other receiver.
+       //
+       // If you would like to inform seelog of an error that happened during 
the handling of
+       // the message, return a non-nil error. This way you'll end up seeing 
your error like
+       // any other internal seelog error.
+       ReceiveMessage(message string, level LogLevel, context 
LogContextInterface) error
+
+       // AfterParse is called immediately after your custom receiver is 
instantiated by
+       // the xml config parser. So, if you need to do any startup logic after 
config parsing,
+       // like opening file or allocating any resources after the receiver is 
instantiated, do it here.
+       //
+       // If this func returns a non-nil error, then the loading procedure 
will fail. E.g.
+       // if you are loading a seelog xml config, the parser would not finish 
the loading
+       // procedure and inform about an error like with any other config error.
+       //
+       // If your custom logger needs some configuration, you can use custom 
attributes in
+       // your config. Check CustomReceiverInitArgs.XmlCustomAttrs comments.
+       //
+       // IMPORTANT: This func is NOT called when the LoggerFromCustomReceiver 
func is used
+       // to create seelog proxy logger using the custom receiver. This func 
is only called when
+       // receiver is instantiated from a config.
+       AfterParse(initArgs CustomReceiverInitArgs) error
+
+       // Flush is called when the custom receiver gets a 'flush' directive 
from a
+       // parent receiver. If custom receiver implements some kind of 
buffering or
+       // queing, then the appropriate reaction on a flush message is 
synchronous
+       // flushing of all those queues/buffers. If custom receiver doesn't have
+       // such mechanisms, then flush implementation may be left empty.
+       Flush()
+
+       // Close is called when the custom receiver gets a 'close' directive 
from a
+       // parent receiver. This happens when a top-level seelog dispatcher is 
sending
+       // 'close' to all child nodes and it means that current seelog logger 
is being closed.
+       // If you need to do any cleanup after your custom receiver is done, 
you should do
+       // it here.
+       Close() error
+}
+
+type customReceiverDispatcher struct {
+       formatter          *formatter
+       innerReceiver      CustomReceiver
+       customReceiverName string
+       usedArgs           CustomReceiverInitArgs
+}
+
+// NewCustomReceiverDispatcher creates a customReceiverDispatcher which 
dispatches data to a specific receiver created
+// using a <custom> tag in the config file.
+func NewCustomReceiverDispatcher(formatter *formatter, customReceiverName 
string, cArgs CustomReceiverInitArgs) (*customReceiverDispatcher, error) {
+       if formatter == nil {
+               return nil, errors.New("formatter cannot be nil")
+       }
+       if len(customReceiverName) == 0 {
+               return nil, errors.New("custom receiver name cannot be empty")
+       }
+
+       creceiver, err := customReceiverByName(customReceiverName)
+       if err != nil {
+               return nil, err
+       }
+       err = creceiver.AfterParse(cArgs)
+       if err != nil {
+               return nil, err
+       }
+       disp := &customReceiverDispatcher{formatter, creceiver, 
customReceiverName, cArgs}
+
+       return disp, nil
+}
+
+// NewCustomReceiverDispatcherByValue is basically the same as 
NewCustomReceiverDispatcher, but using
+// a specific CustomReceiver value instead of instantiating a new one by type.
+func NewCustomReceiverDispatcherByValue(formatter *formatter, customReceiver 
CustomReceiver, name string, cArgs CustomReceiverInitArgs) 
(*customReceiverDispatcher, error) {
+       if formatter == nil {
+               return nil, errors.New("formatter cannot be nil")
+       }
+       if customReceiver == nil {
+               return nil, errors.New("customReceiver cannot be nil")
+       }
+       disp := &customReceiverDispatcher{formatter, customReceiver, name, 
cArgs}
+
+       return disp, nil
+}
+
+// CustomReceiver implementation. Check CustomReceiver comments.
+func (disp *customReceiverDispatcher) Dispatch(
+       message string,
+       level LogLevel,
+       context LogContextInterface,
+       errorFunc func(err error)) {
+
+       defer func() {
+               if err := recover(); err != nil {
+                       errorFunc(fmt.Errorf("panic in custom receiver 
'%s'.Dispatch: %s", reflect.TypeOf(disp.innerReceiver), err))
+               }
+       }()
+
+       err := disp.innerReceiver.ReceiveMessage(disp.formatter.Format(message, 
level, context), level, context)
+       if err != nil {
+               errorFunc(err)
+       }
+}
+
+// CustomReceiver implementation. Check CustomReceiver comments.
+func (disp *customReceiverDispatcher) Flush() {
+       disp.innerReceiver.Flush()
+}
+
+// CustomReceiver implementation. Check CustomReceiver comments.
+func (disp *customReceiverDispatcher) Close() error {
+       disp.innerReceiver.Flush()
+
+       err := disp.innerReceiver.Close()
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func (disp *customReceiverDispatcher) String() string {
+       datas := ""
+       skeys := make([]string, 0, len(disp.usedArgs.XmlCustomAttrs))
+       for i := range disp.usedArgs.XmlCustomAttrs {
+               skeys = append(skeys, i)
+       }
+       sort.Strings(skeys)
+       for _, key := range skeys {
+               datas += fmt.Sprintf("<%s, %s> ", key, 
disp.usedArgs.XmlCustomAttrs[key])
+       }
+
+       str := fmt.Sprintf("Custom receiver %s 
[fmt='%s'],[data='%s'],[inner='%s']\n",
+               disp.customReceiverName, disp.formatter.String(), datas, 
disp.innerReceiver)
+
+       return str
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_customdispatcher_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_customdispatcher_test.go
 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_customdispatcher_test.go
new file mode 100644
index 0000000..23f631a
--- /dev/null
+++ 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_customdispatcher_test.go
@@ -0,0 +1,177 @@
+// Copyright (c) 2013 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "testing"
+)
+
+type testCustomDispatcherMessageReceiver struct {
+       customTestReceiver
+}
+
+func TestCustomDispatcher_Message(t *testing.T) {
+       recName := "TestCustomDispatcher_Message"
+       RegisterReceiver(recName, &testCustomDispatcherMessageReceiver{})
+
+       customDispatcher, err := 
NewCustomReceiverDispatcher(onlyMessageFormatForTest, recName, 
CustomReceiverInitArgs{
+               XmlCustomAttrs: map[string]string{
+                       "test": "testdata",
+               },
+       })
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       context, err := currentContext(nil)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       bytes := []byte("Hello")
+       customDispatcher.Dispatch(string(bytes), TraceLvl, context, func(err 
error) {})
+
+       cout := 
customDispatcher.innerReceiver.(*testCustomDispatcherMessageReceiver).customTestReceiver.co
+       if cout.initCalled != true {
+               t.Error("Init not called")
+               return
+       }
+       if cout.dataPassed != "testdata" {
+               t.Errorf("wrong data passed: '%s'", cout.dataPassed)
+               return
+       }
+       if cout.messageOutput != string(bytes) {
+               t.Errorf("wrong message output: '%s'", cout.messageOutput)
+               return
+       }
+       if cout.levelOutput != TraceLvl {
+               t.Errorf("wrong log level: '%s'", cout.levelOutput)
+               return
+       }
+       if cout.flushed {
+               t.Error("Flush was not expected")
+               return
+       }
+       if cout.closed {
+               t.Error("Closing was not expected")
+               return
+       }
+}
+
+type testCustomDispatcherFlushReceiver struct {
+       customTestReceiver
+}
+
+func TestCustomDispatcher_Flush(t *testing.T) {
+       recName := "TestCustomDispatcher_Flush"
+       RegisterReceiver(recName, &testCustomDispatcherFlushReceiver{})
+
+       customDispatcher, err := 
NewCustomReceiverDispatcher(onlyMessageFormatForTest, recName, 
CustomReceiverInitArgs{
+               XmlCustomAttrs: map[string]string{
+                       "test": "testdata",
+               },
+       })
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       customDispatcher.Flush()
+
+       cout := 
customDispatcher.innerReceiver.(*testCustomDispatcherFlushReceiver).customTestReceiver.co
+       if cout.initCalled != true {
+               t.Error("Init not called")
+               return
+       }
+       if cout.dataPassed != "testdata" {
+               t.Errorf("wrong data passed: '%s'", cout.dataPassed)
+               return
+       }
+       if cout.messageOutput != "" {
+               t.Errorf("wrong message output: '%s'", cout.messageOutput)
+               return
+       }
+       if cout.levelOutput != TraceLvl {
+               t.Errorf("wrong log level: '%s'", cout.levelOutput)
+               return
+       }
+       if !cout.flushed {
+               t.Error("Flush was expected")
+               return
+       }
+       if cout.closed {
+               t.Error("Closing was not expected")
+               return
+       }
+}
+
+type testCustomDispatcherCloseReceiver struct {
+       customTestReceiver
+}
+
+func TestCustomDispatcher_Close(t *testing.T) {
+       recName := "TestCustomDispatcher_Close"
+       RegisterReceiver(recName, &testCustomDispatcherCloseReceiver{})
+
+       customDispatcher, err := 
NewCustomReceiverDispatcher(onlyMessageFormatForTest, recName, 
CustomReceiverInitArgs{
+               XmlCustomAttrs: map[string]string{
+                       "test": "testdata",
+               },
+       })
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       customDispatcher.Close()
+
+       cout := 
customDispatcher.innerReceiver.(*testCustomDispatcherCloseReceiver).customTestReceiver.co
+       if cout.initCalled != true {
+               t.Error("Init not called")
+               return
+       }
+       if cout.dataPassed != "testdata" {
+               t.Errorf("wrong data passed: '%s'", cout.dataPassed)
+               return
+       }
+       if cout.messageOutput != "" {
+               t.Errorf("wrong message output: '%s'", cout.messageOutput)
+               return
+       }
+       if cout.levelOutput != TraceLvl {
+               t.Errorf("wrong log level: '%s'", cout.levelOutput)
+               return
+       }
+       if !cout.flushed {
+               t.Error("Flush was expected")
+               return
+       }
+       if !cout.closed {
+               t.Error("Closing was expected")
+               return
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_dispatcher.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_dispatcher.go 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_dispatcher.go
new file mode 100644
index 0000000..2bd3b4a
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_dispatcher.go
@@ -0,0 +1,189 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "errors"
+       "fmt"
+       "io"
+)
+
+// A dispatcherInterface is used to dispatch message to all underlying 
receivers.
+// Dispatch logic depends on given context and log level. Any errors are 
reported using errorFunc.
+// Also, as underlying receivers may have a state, dispatcher has a 
ShuttingDown method which performs
+// an immediate cleanup of all data that is stored in the receivers
+type dispatcherInterface interface {
+       flusherInterface
+       io.Closer
+       Dispatch(message string, level LogLevel, context LogContextInterface, 
errorFunc func(err error))
+}
+
+type dispatcher struct {
+       formatter   *formatter
+       writers     []*formattedWriter
+       dispatchers []dispatcherInterface
+}
+
+// Creates a dispatcher which dispatches data to a list of receivers.
+// Each receiver should be either a Dispatcher or io.Writer, otherwise an 
error will be returned
+func createDispatcher(formatter *formatter, receivers []interface{}) 
(*dispatcher, error) {
+       if formatter == nil {
+               return nil, errors.New("formatter cannot be nil")
+       }
+       if receivers == nil || len(receivers) == 0 {
+               return nil, errors.New("receivers cannot be nil or empty")
+       }
+
+       disp := &dispatcher{formatter, make([]*formattedWriter, 0), 
make([]dispatcherInterface, 0)}
+       for _, receiver := range receivers {
+               writer, ok := receiver.(*formattedWriter)
+               if ok {
+                       disp.writers = append(disp.writers, writer)
+                       continue
+               }
+
+               ioWriter, ok := receiver.(io.Writer)
+               if ok {
+                       writer, err := NewFormattedWriter(ioWriter, 
disp.formatter)
+                       if err != nil {
+                               return nil, err
+                       }
+                       disp.writers = append(disp.writers, writer)
+                       continue
+               }
+
+               dispInterface, ok := receiver.(dispatcherInterface)
+               if ok {
+                       disp.dispatchers = append(disp.dispatchers, 
dispInterface)
+                       continue
+               }
+
+               return nil, errors.New("method can receive either io.Writer or 
dispatcherInterface")
+       }
+
+       return disp, nil
+}
+
+func (disp *dispatcher) Dispatch(
+       message string,
+       level LogLevel,
+       context LogContextInterface,
+       errorFunc func(err error)) {
+
+       for _, writer := range disp.writers {
+               err := writer.Write(message, level, context)
+               if err != nil {
+                       errorFunc(err)
+               }
+       }
+
+       for _, dispInterface := range disp.dispatchers {
+               dispInterface.Dispatch(message, level, context, errorFunc)
+       }
+}
+
+// Flush goes through all underlying writers which implement flusherInterface 
interface
+// and closes them. Recursively performs the same action for underlying 
dispatchers
+func (disp *dispatcher) Flush() {
+       for _, disp := range disp.Dispatchers() {
+               disp.Flush()
+       }
+
+       for _, formatWriter := range disp.Writers() {
+               flusher, ok := formatWriter.Writer().(flusherInterface)
+               if ok {
+                       flusher.Flush()
+               }
+       }
+}
+
+// Close goes through all underlying writers which implement io.Closer 
interface
+// and closes them. Recursively performs the same action for underlying 
dispatchers
+// Before closing, writers are flushed to prevent loss of any buffered data, so
+// a call to Flush() func before Close() is not necessary
+func (disp *dispatcher) Close() error {
+       for _, disp := range disp.Dispatchers() {
+               disp.Flush()
+               err := disp.Close()
+               if err != nil {
+                       return err
+               }
+       }
+
+       for _, formatWriter := range disp.Writers() {
+               flusher, ok := formatWriter.Writer().(flusherInterface)
+               if ok {
+                       flusher.Flush()
+               }
+
+               closer, ok := formatWriter.Writer().(io.Closer)
+               if ok {
+                       err := closer.Close()
+                       if err != nil {
+                               return err
+                       }
+               }
+       }
+
+       return nil
+}
+
+func (disp *dispatcher) Writers() []*formattedWriter {
+       return disp.writers
+}
+
+func (disp *dispatcher) Dispatchers() []dispatcherInterface {
+       return disp.dispatchers
+}
+
+func (disp *dispatcher) String() string {
+       str := "formatter: " + disp.formatter.String() + "\n"
+
+       str += "    ->Dispatchers:"
+
+       if len(disp.dispatchers) == 0 {
+               str += "none\n"
+       } else {
+               str += "\n"
+
+               for _, disp := range disp.dispatchers {
+                       str += fmt.Sprintf("        ->%s", disp)
+               }
+       }
+
+       str += "    ->Writers:"
+
+       if len(disp.writers) == 0 {
+               str += "none\n"
+       } else {
+               str += "\n"
+
+               for _, writer := range disp.writers {
+                       str += fmt.Sprintf("        ->%s\n", writer)
+               }
+       }
+
+       return str
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher.go 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher.go
new file mode 100644
index 0000000..9de8a72
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher.go
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "fmt"
+)
+
+// A filterDispatcher writes the given message to underlying receivers only if 
message log level
+// is in the allowed list.
+type filterDispatcher struct {
+       *dispatcher
+       allowList map[LogLevel]bool
+}
+
+// NewFilterDispatcher creates a new filterDispatcher using a list of allowed 
levels.
+func NewFilterDispatcher(formatter *formatter, receivers []interface{}, 
allowList ...LogLevel) (*filterDispatcher, error) {
+       disp, err := createDispatcher(formatter, receivers)
+       if err != nil {
+               return nil, err
+       }
+
+       allows := make(map[LogLevel]bool)
+       for _, allowLevel := range allowList {
+               allows[allowLevel] = true
+       }
+
+       return &filterDispatcher{disp, allows}, nil
+}
+
+func (filter *filterDispatcher) Dispatch(
+       message string,
+       level LogLevel,
+       context LogContextInterface,
+       errorFunc func(err error)) {
+       isAllowed, ok := filter.allowList[level]
+       if ok && isAllowed {
+               filter.dispatcher.Dispatch(message, level, context, errorFunc)
+       }
+}
+
+func (filter *filterDispatcher) String() string {
+       return fmt.Sprintf("filterDispatcher ->\n%s", filter.dispatcher)
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher_test.go
 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher_test.go
new file mode 100644
index 0000000..c1894a7
--- /dev/null
+++ 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_filterdispatcher_test.go
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "testing"
+)
+
+func TestfilterDispatcher_Pass(t *testing.T) {
+       writer, _ := newBytesVerifier(t)
+       filter, err := NewFilterDispatcher(onlyMessageFormatForTest, 
[]interface{}{writer}, TraceLvl)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       context, err := currentContext(nil)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       bytes := []byte("Hello")
+       writer.ExpectBytes(bytes)
+       filter.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
+       writer.MustNotExpect()
+}
+
+func TestfilterDispatcher_Deny(t *testing.T) {
+       writer, _ := newBytesVerifier(t)
+       filter, err := NewFilterDispatcher(DefaultFormatter, 
[]interface{}{writer})
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       context, err := currentContext(nil)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       bytes := []byte("Hello")
+       filter.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher.go 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher.go
new file mode 100644
index 0000000..1d0fe7e
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher.go
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "fmt"
+)
+
+// A splitDispatcher just writes the given message to underlying receivers. 
(Splits the message stream.)
+type splitDispatcher struct {
+       *dispatcher
+}
+
+func NewSplitDispatcher(formatter *formatter, receivers []interface{}) 
(*splitDispatcher, error) {
+       disp, err := createDispatcher(formatter, receivers)
+       if err != nil {
+               return nil, err
+       }
+
+       return &splitDispatcher{disp}, nil
+}
+
+func (splitter *splitDispatcher) String() string {
+       return fmt.Sprintf("splitDispatcher ->\n%s", 
splitter.dispatcher.String())
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher_test.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git 
a/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher_test.go 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher_test.go
new file mode 100644
index 0000000..fc4651c
--- /dev/null
+++ 
b/traffic_stats/vendor/github.com/cihub/seelog/dispatch_splitdispatcher_test.go
@@ -0,0 +1,64 @@
+// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package seelog
+
+import (
+       "fmt"
+       "testing"
+)
+
+var onlyMessageFormatForTest *formatter
+
+func init() {
+       var err error
+       onlyMessageFormatForTest, err = NewFormatter("%Msg")
+       if err != nil {
+               fmt.Println("Can not create only message format: " + 
err.Error())
+       }
+}
+
+func TestsplitDispatcher(t *testing.T) {
+       writer1, _ := newBytesVerifier(t)
+       writer2, _ := newBytesVerifier(t)
+       spliter, err := NewSplitDispatcher(onlyMessageFormatForTest, 
[]interface{}{writer1, writer2})
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       context, err := currentContext(nil)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       bytes := []byte("Hello")
+
+       writer1.ExpectBytes(bytes)
+       writer2.ExpectBytes(bytes)
+       spliter.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
+       writer1.MustNotExpect()
+       writer2.MustNotExpect()
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d969e13b/traffic_stats/vendor/github.com/cihub/seelog/doc.go
----------------------------------------------------------------------
diff --git a/traffic_stats/vendor/github.com/cihub/seelog 
b/traffic_stats/vendor/github.com/cihub/seelog
deleted file mode 160000
index 175e6e3..0000000
--- a/traffic_stats/vendor/github.com/cihub/seelog
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 175e6e3d439fe2e1cee7ab652b12eb546c145a13
diff --git a/traffic_stats/vendor/github.com/cihub/seelog/doc.go 
b/traffic_stats/vendor/github.com/cihub/seelog/doc.go
new file mode 100644
index 0000000..2734c9c
--- /dev/null
+++ b/traffic_stats/vendor/github.com/cihub/seelog/doc.go
@@ -0,0 +1,175 @@
+// Copyright (c) 2014 - Cloud Instruments Co., Ltd.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, 
this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package seelog implements logging functionality with flexible dispatching, 
filtering, and formatting.
+
+Creation
+
+To create a logger, use one of the following constructors:
+  func LoggerFromConfigAsBytes
+  func LoggerFromConfigAsFile
+  func LoggerFromConfigAsString
+  func LoggerFromWriterWithMinLevel
+  func LoggerFromWriterWithMinLevelAndFormat
+  func LoggerFromCustomReceiver (check 
https://github.com/cihub/seelog/wiki/Custom-receivers)
+Example:
+  import log "github.com/cihub/seelog"
+
+  func main() {
+      logger, err := log.LoggerFromConfigAsFile("seelog.xml")
+      if err != nil {
+          panic(err)
+      }
+      defer logger.Flush()
+      ... use logger ...
+  }
+The "defer" line is important because if you are using asynchronous logger 
behavior, without this line you may end up losing some
+messages when you close your application because they are processed in another 
non-blocking goroutine. To avoid that you
+explicitly defer flushing all messages before closing.
+
+Usage
+
+Logger created using one of the LoggerFrom* funcs can be used directly by 
calling one of the main log funcs.
+Example:
+  import log "github.com/cihub/seelog"
+
+  func main() {
+      logger, err := log.LoggerFromConfigAsFile("seelog.xml")
+      if err != nil {
+          panic(err)
+      }
+      defer logger.Flush()
+      logger.Trace("test")
+      logger.Debugf("var = %s", "abc")
+  }
+
+Having loggers as variables is convenient if you are writing your own package 
with internal logging or if you have
+several loggers with different options.
+But for most standalone apps it is more convenient to use package level funcs 
and vars. There is a package level
+var 'Current' made for it. You can replace it with another logger using 
'ReplaceLogger' and then use package level funcs:
+  import log "github.com/cihub/seelog"
+
+  func main() {
+      logger, err := log.LoggerFromConfigAsFile("seelog.xml")
+      if err != nil {
+          panic(err)
+      }
+      log.ReplaceLogger(logger)
+      defer log.Flush()
+      log.Trace("test")
+      log.Debugf("var = %s", "abc")
+  }
+Last lines
+      log.Trace("test")
+      log.Debugf("var = %s", "abc")
+do the same as
+      log.Current.Trace("test")
+      log.Current.Debugf("var = %s", "abc")
+In this example the 'Current' logger was replaced using a 'ReplaceLogger' call 
and became equal to 'logger' variable created from config.
+This way you are able to use package level funcs instead of passing the logger 
variable.
+
+Configuration
+
+Main seelog point is to configure logger via config files and not the code.
+The configuration is read by LoggerFrom* funcs. These funcs read xml 
configuration from different sources and try
+to create a logger using it.
+
+All the configuration features are covered in detail in the official wiki: 
https://github.com/cihub/seelog/wiki.
+There are many sections covering different aspects of seelog, but the most 
important for understanding configs are:
+    https://github.com/cihub/seelog/wiki/Constraints-and-exceptions
+    https://github.com/cihub/seelog/wiki/Dispatchers-and-receivers
+    https://github.com/cihub/seelog/wiki/Formatting
+    https://github.com/cihub/seelog/wiki/Logger-types
+After you understand these concepts, check the 'Reference' section on the main 
wiki page to get the up-to-date
+list of dispatchers, receivers, formats, and logger types.
+
+Here is an example config with all these features:
+    <seelog type="adaptive" mininterval="2000000" maxinterval="100000000" 
critmsgcount="500" minlevel="debug">
+        <exceptions>
+            <exception filepattern="test*" minlevel="error"/>
+        </exceptions>
+        <outputs formatid="all">
+            <file path="all.log"/>
+            <filter levels="info">
+              <console formatid="fmtinfo"/>
+            </filter>
+            <filter levels="error,critical" formatid="fmterror">
+              <console/>
+              <file path="errors.log"/>
+            </filter>
+        </outputs>
+        <formats>
+            <format id="fmtinfo" format="[%Level] [%Time] %Msg%n"/>
+            <format id="fmterror" format="[%LEVEL] [%Time] [%FuncShort @ 
%File.%Line] %Msg%n"/>
+            <format id="all" format="[%Level] [%Time] [@ %File.%Line] %Msg%n"/>
+            <format id="criticalemail" format="Critical error on our server!\n 
   %Time %Date %RelFile %Func %Msg \nSent by Seelog"/>
+        </formats>
+    </seelog>
+This config represents a logger with adaptive timeout between log messages 
(check logger types reference) which
+logs to console, all.log, and errors.log depending on the log level. Its 
output formats also depend on log level. This logger will only
+use log level 'debug' and higher (minlevel is set) for all files with names 
that don't start with 'test'. For files starting with 'test'
+this logger prohibits all levels below 'error'.
+
+Configuration using code
+
+Although configuration using code is not recommended, it is sometimes needed 
and it is possible to do with seelog. Basically, what
+you need to do to get started is to create constraints, exceptions and a 
dispatcher tree (same as with config). Most of the New*
+functions in this package are used to provide such capabilities.
+
+Here is an example of configuration in code, that demonstrates an async loop 
logger that logs to a simple split dispatcher with
+a console receiver using a specified format and is filtered using a top-level 
min-max constraints and one expection for
+the 'main.go' file. So, this is basically a demonstration of configuration of 
most of the features:
+
+  package main
+
+  import log "github.com/cihub/seelog"
+
+  func main() {
+      defer log.Flush()
+      log.Info("Hello from Seelog!")
+
+      consoleWriter, _ := log.NewConsoleWriter()
+      formatter, _ := log.NewFormatter("%Level %Msg %File%n")
+      root, _ := log.NewSplitDispatcher(formatter, 
[]interface{}{consoleWriter})
+      constraints, _ := log.NewMinMaxConstraints(log.TraceLvl, log.CriticalLvl)
+      specificConstraints, _ := 
log.NewListConstraints([]log.LogLevel{log.InfoLvl, log.ErrorLvl})
+      ex, _ := log.NewLogLevelException("*", "*main.go", specificConstraints)
+      exceptions := []*log.LogLevelException{ex}
+
+      logger := log.NewAsyncLoopLogger(log.NewLoggerConfig(constraints, 
exceptions, root))
+      log.ReplaceLogger(logger)
+
+      log.Trace("This should not be seen")
+      log.Debug("This should not be seen")
+      log.Info("Test")
+      log.Error("Test2")
+  }
+
+Examples
+
+To learn seelog features faster you should check the examples package: 
https://github.com/cihub/seelog-examples
+It contains many example configs and usecases.
+*/
+package seelog

Reply via email to