347 lines
8.1 KiB
Go
347 lines
8.1 KiB
Go
package logrus
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestErrorNotLost(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["error"] != "wild walrus" {
|
|
t.Fatal("Error field not set")
|
|
}
|
|
}
|
|
|
|
func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["omg"] != "wild walrus" {
|
|
t.Fatal("Error field not set")
|
|
}
|
|
}
|
|
|
|
func TestFieldClashWithTime(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("time", "right now!"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["fields.time"] != "right now!" {
|
|
t.Fatal("fields.time not set to original time field")
|
|
}
|
|
|
|
if entry["time"] != "0001-01-01T00:00:00Z" {
|
|
t.Fatal("time field not set to current time, was: ", entry["time"])
|
|
}
|
|
}
|
|
|
|
func TestFieldClashWithMsg(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("msg", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["fields.msg"] != "something" {
|
|
t.Fatal("fields.msg not set to original msg field")
|
|
}
|
|
}
|
|
|
|
func TestFieldClashWithLevel(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("level", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["fields.level"] != "something" {
|
|
t.Fatal("fields.level not set to original level field")
|
|
}
|
|
}
|
|
|
|
func TestFieldClashWithRemappedFields(t *testing.T) {
|
|
formatter := &JSONFormatter{
|
|
FieldMap: FieldMap{
|
|
FieldKeyTime: "@timestamp",
|
|
FieldKeyLevel: "@level",
|
|
FieldKeyMsg: "@message",
|
|
},
|
|
}
|
|
|
|
b, err := formatter.Format(WithFields(Fields{
|
|
"@timestamp": "@timestamp",
|
|
"@level": "@level",
|
|
"@message": "@message",
|
|
"timestamp": "timestamp",
|
|
"level": "level",
|
|
"msg": "msg",
|
|
}))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
for _, field := range []string{"timestamp", "level", "msg"} {
|
|
if entry[field] != field {
|
|
t.Errorf("Expected field %v to be untouched; got %v", field, entry[field])
|
|
}
|
|
|
|
remappedKey := fmt.Sprintf("fields.%s", field)
|
|
if remapped, ok := entry[remappedKey]; ok {
|
|
t.Errorf("Expected %s to be empty; got %v", remappedKey, remapped)
|
|
}
|
|
}
|
|
|
|
for _, field := range []string{"@timestamp", "@level", "@message"} {
|
|
if entry[field] == field {
|
|
t.Errorf("Expected field %v to be mapped to an Entry value", field)
|
|
}
|
|
|
|
remappedKey := fmt.Sprintf("fields.%s", field)
|
|
if remapped, ok := entry[remappedKey]; ok {
|
|
if remapped != field {
|
|
t.Errorf("Expected field %v to be copied to %s; got %v", field, remappedKey, remapped)
|
|
}
|
|
} else {
|
|
t.Errorf("Expected field %v to be copied to %s; was absent", field, remappedKey)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFieldsInNestedDictionary(t *testing.T) {
|
|
formatter := &JSONFormatter{
|
|
DataKey: "args",
|
|
}
|
|
|
|
logEntry := WithFields(Fields{
|
|
"level": "level",
|
|
"test": "test",
|
|
})
|
|
logEntry.Level = InfoLevel
|
|
|
|
b, err := formatter.Format(logEntry)
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
args := entry["args"].(map[string]interface{})
|
|
|
|
for _, field := range []string{"test", "level"} {
|
|
if value, present := args[field]; !present || value != field {
|
|
t.Errorf("Expected field %v to be present under 'args'; untouched", field)
|
|
}
|
|
}
|
|
|
|
for _, field := range []string{"test", "fields.level"} {
|
|
if _, present := entry[field]; present {
|
|
t.Errorf("Expected field %v not to be present at top level", field)
|
|
}
|
|
}
|
|
|
|
// with nested object, "level" shouldn't clash
|
|
if entry["level"] != "info" {
|
|
t.Errorf("Expected 'level' field to contain 'info'")
|
|
}
|
|
}
|
|
|
|
func TestJSONEntryEndsWithNewline(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("level", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
if b[len(b)-1] != '\n' {
|
|
t.Fatal("Expected JSON log entry to end with a newline")
|
|
}
|
|
}
|
|
|
|
func TestJSONMessageKey(t *testing.T) {
|
|
formatter := &JSONFormatter{
|
|
FieldMap: FieldMap{
|
|
FieldKeyMsg: "message",
|
|
},
|
|
}
|
|
|
|
b, err := formatter.Format(&Entry{Message: "oh hai"})
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
s := string(b)
|
|
if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) {
|
|
t.Fatal("Expected JSON to format message key")
|
|
}
|
|
}
|
|
|
|
func TestJSONLevelKey(t *testing.T) {
|
|
formatter := &JSONFormatter{
|
|
FieldMap: FieldMap{
|
|
FieldKeyLevel: "somelevel",
|
|
},
|
|
}
|
|
|
|
b, err := formatter.Format(WithField("level", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
s := string(b)
|
|
if !strings.Contains(s, "somelevel") {
|
|
t.Fatal("Expected JSON to format level key")
|
|
}
|
|
}
|
|
|
|
func TestJSONTimeKey(t *testing.T) {
|
|
formatter := &JSONFormatter{
|
|
FieldMap: FieldMap{
|
|
FieldKeyTime: "timeywimey",
|
|
},
|
|
}
|
|
|
|
b, err := formatter.Format(WithField("level", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
s := string(b)
|
|
if !strings.Contains(s, "timeywimey") {
|
|
t.Fatal("Expected JSON to format time key")
|
|
}
|
|
}
|
|
|
|
func TestFieldDoesNotClashWithCaller(t *testing.T) {
|
|
SetReportCaller(false)
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("func", "howdy pardner"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["func"] != "howdy pardner" {
|
|
t.Fatal("func field replaced when ReportCaller=false")
|
|
}
|
|
}
|
|
|
|
func TestFieldClashWithCaller(t *testing.T) {
|
|
SetReportCaller(true)
|
|
formatter := &JSONFormatter{}
|
|
e := WithField("func", "howdy pardner")
|
|
e.Caller = &runtime.Frame{Function: "somefunc"}
|
|
b, err := formatter.Format(e)
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
|
|
entry := make(map[string]interface{})
|
|
err = json.Unmarshal(b, &entry)
|
|
if err != nil {
|
|
t.Fatal("Unable to unmarshal formatted entry: ", err)
|
|
}
|
|
|
|
if entry["fields.func"] != "howdy pardner" {
|
|
t.Fatalf("fields.func not set to original func field when ReportCaller=true (got '%s')",
|
|
entry["fields.func"])
|
|
}
|
|
|
|
if entry["func"] != "somefunc" {
|
|
t.Fatalf("func not set as expected when ReportCaller=true (got '%s')",
|
|
entry["func"])
|
|
}
|
|
|
|
SetReportCaller(false) // return to default value
|
|
}
|
|
|
|
func TestJSONDisableTimestamp(t *testing.T) {
|
|
formatter := &JSONFormatter{
|
|
DisableTimestamp: true,
|
|
}
|
|
|
|
b, err := formatter.Format(WithField("level", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
s := string(b)
|
|
if strings.Contains(s, FieldKeyTime) {
|
|
t.Error("Did not prevent timestamp", s)
|
|
}
|
|
}
|
|
|
|
func TestJSONEnableTimestamp(t *testing.T) {
|
|
formatter := &JSONFormatter{}
|
|
|
|
b, err := formatter.Format(WithField("level", "something"))
|
|
if err != nil {
|
|
t.Fatal("Unable to format entry: ", err)
|
|
}
|
|
s := string(b)
|
|
if !strings.Contains(s, FieldKeyTime) {
|
|
t.Error("Timestamp not present", s)
|
|
}
|
|
}
|