From af4587478b36f73c1e224e3b0face1642c445df5 Mon Sep 17 00:00:00 2001 From: Eugene Lisitsky Date: Thu, 14 Dec 2017 16:24:57 +0300 Subject: [PATCH 1/5] Added UDPOPtionSetters: ClientNet and ClientAddr. Setters bug fixed. Added tests. Added tests for UDPHook.Fire() method. Need fixing tests TestHooks and TestTrace. --- .gitignore | 3 ++ udphook.go | 17 ++++++++- udphook_test.go | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index daf913b..887a1b8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ _testmain.go *.exe *.test *.prof + +# IDE +.idea/ \ No newline at end of file diff --git a/udphook.go b/udphook.go index a2139ee..ed1bad4 100644 --- a/udphook.go +++ b/udphook.go @@ -19,6 +19,21 @@ const ( // UDPOptionSetter represents functional arguments passed to ELKHook type UDPOptionSetter func(f *UDPHook) +// ClientNet sets clientNet option in UDPHook +// Usage: hook, err := NewUDPHook(ClientNet("tcp")) +func ClientNet(clientNet string) UDPOptionSetter { + return func(f *UDPHook) { + f.clientNet = clientNet + } +} +// ClientAddr sets clientAddr option in UDPHook +// Usage: hook, err := NewUDPHook(ClientAddr("192.168.1.1:65000")) +func ClientAddr(clientAddr string) UDPOptionSetter { + return func(f *UDPHook) { + f.clientAddr = clientAddr + } +} + // NewUDPHook returns logrus-compatible hook that sends data to UDP socket func NewUDPHook(opts ...UDPOptionSetter) (*UDPHook, error) { f := &UDPHook{} @@ -89,7 +104,7 @@ func (elk *UDPHook) Fire(e *log.Entry) error { } defer conn.Close() - resolvedAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5000") + resolvedAddr, err := net.ResolveUDPAddr(elk.clientNet, elk.clientAddr) if err != nil { return Wrap(err) } diff --git a/udphook_test.go b/udphook_test.go index d5574a5..e7dbf6e 100644 --- a/udphook_test.go +++ b/udphook_test.go @@ -18,7 +18,10 @@ package trace import ( "io/ioutil" + "net" + "sync" "testing" + "time" "github.com/jonboulle/clockwork" log "github.com/sirupsen/logrus" @@ -44,3 +47,98 @@ func (s *HooksSuite) TestSafeForConcurrentAccess(c *C) { }(entry) } } + +func TestClientNet(t *testing.T) { + type args struct { + clientNet string + } + tests := []struct { + name string + clientNet string + want string + }{ + {"Empty value", "", "", }, + {"UDP", "udp", "udp", }, + {"TCP", "tcp", "tcp", }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := ClientNet(tt.clientNet) + hook := UDPHook{} + f(&hook) + + if hook.clientNet!= tt.want /*!reflect.DeepEqual(got, tt.want) */{ + t.Errorf("ClientNet() = %v, want %v", hook.clientNet, tt.want) + } + }) + } +} + +func TestClientAddr(t *testing.T) { + type args struct { + clientNet string + } + tests := []struct { + name string + clientAddr string + want string + }{ + {"Empty value", "", "", }, + {"Localhost and another port", "127.0.0.1:9999", "127.0.0.1:9999", }, + {"Another host", "192.168.0.1:9999", "192.168.0.1:9999", }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := ClientAddr(tt.clientAddr) + hook := UDPHook{} + f(&hook) + + if hook.clientAddr != tt.want /*!reflect.DeepEqual(got, tt.want) */{ + t.Errorf("ClientAddr() = %v, want %v", hook.clientNet, tt.want) + } + }) + } +} + +func TestUDPHook_Fire(t *testing.T) { + remoteAddr := "127.0.0.1:5501" + raddr, err := net.ResolveUDPAddr("udp", remoteAddr) + UDPConn, err := net.ListenUDP("udp", raddr) + if err != nil { + t.Errorf("Cannot listen given address %v, error: %v", remoteAddr, err) + return + } + defer UDPConn.Close() + + var ok bool + + var ( + wg sync.WaitGroup + bytesRead int + serverReadError error + ) + wg.Add(1) + go func() { + defer wg.Done() + var b = make([]byte, 1024) + UDPConn.SetDeadline(time.Now().Add(100*time.Millisecond)) + bytesRead, _, serverReadError = UDPConn.ReadFromUDP(b) + if bytesRead > 0 { + ok = true + } + serverReadError = err + }() + + hook, err := NewUDPHook(ClientAddr(remoteAddr+"")) + logger := log.New() + entry := log.NewEntry(logger) + + err = hook.Fire(entry) + if err != nil { + t.Errorf("Fire() error: %v", err) + } + wg.Wait() + if !ok { + t.Errorf("UDP server read error: %v. Bytes read: %v", serverReadError, bytesRead) + } +} \ No newline at end of file From 3f76d21cec3d6ebf441a605c58109aa1feeb498a Mon Sep 17 00:00:00 2001 From: Eugene Lisitsky Date: Fri, 15 Dec 2017 09:34:34 +0300 Subject: [PATCH 2/5] Code cleanup: - removed unnecessary types - removed leftover comments --- udphook_test.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/udphook_test.go b/udphook_test.go index e7dbf6e..0752f7c 100644 --- a/udphook_test.go +++ b/udphook_test.go @@ -49,9 +49,6 @@ func (s *HooksSuite) TestSafeForConcurrentAccess(c *C) { } func TestClientNet(t *testing.T) { - type args struct { - clientNet string - } tests := []struct { name string clientNet string @@ -67,7 +64,7 @@ func TestClientNet(t *testing.T) { hook := UDPHook{} f(&hook) - if hook.clientNet!= tt.want /*!reflect.DeepEqual(got, tt.want) */{ + if hook.clientNet!= tt.want { t.Errorf("ClientNet() = %v, want %v", hook.clientNet, tt.want) } }) @@ -75,9 +72,6 @@ func TestClientNet(t *testing.T) { } func TestClientAddr(t *testing.T) { - type args struct { - clientNet string - } tests := []struct { name string clientAddr string @@ -93,7 +87,7 @@ func TestClientAddr(t *testing.T) { hook := UDPHook{} f(&hook) - if hook.clientAddr != tt.want /*!reflect.DeepEqual(got, tt.want) */{ + if hook.clientAddr != tt.want { t.Errorf("ClientAddr() = %v, want %v", hook.clientNet, tt.want) } }) From f790038f182059cb46193faf2c3c1264309d167a Mon Sep 17 00:00:00 2001 From: Eugene Lisitsky Date: Tue, 19 Dec 2017 10:43:01 +0300 Subject: [PATCH 3/5] Remove Type field (and corresponding "type" in json output) because it conflicts with reserved fiedlds in Elastic. --- udphook.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/udphook.go b/udphook.go index ed1bad4..acfd608 100644 --- a/udphook.go +++ b/udphook.go @@ -72,7 +72,6 @@ type UDPHook struct { type Frame struct { Time time.Time `json:"time"` - Type string `json:"type"` Entry map[string]interface{} `json:"entry"` Message string `json:"message"` Level string `json:"level"` @@ -89,7 +88,6 @@ func (elk *UDPHook) Fire(e *log.Entry) error { } data, err := json.Marshal(Frame{ Time: elk.Clock.Now().UTC(), - Type: "trace", Entry: entry.Data, Message: entry.Message, Level: entry.Level.String(), From 67aba509b1b9b5d0d258091b6688aee1fa90d875 Mon Sep 17 00:00:00 2001 From: Eugene Lisitsky Date: Tue, 19 Dec 2017 10:53:16 +0300 Subject: [PATCH 4/5] Add Target func to set UDPHook clientNet and clientAdd options at one call. --- udphook.go | 9 +++++++ udphook_test.go | 67 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/udphook.go b/udphook.go index acfd608..31c9aba 100644 --- a/udphook.go +++ b/udphook.go @@ -34,6 +34,15 @@ func ClientAddr(clientAddr string) UDPOptionSetter { } } +// Target sets clientNet and clientAddr option in UDPHook in one call +// Usage: hook, err := NewUDPHook(Target("udp", "192.168.1.1:65000")) +func Target(network, addr string) UDPOptionSetter { + return func(f *UDPHook) { + f.clientNet = network + f.clientAddr = addr + } +} + // NewUDPHook returns logrus-compatible hook that sends data to UDP socket func NewUDPHook(opts ...UDPOptionSetter) (*UDPHook, error) { f := &UDPHook{} diff --git a/udphook_test.go b/udphook_test.go index 0752f7c..304490b 100644 --- a/udphook_test.go +++ b/udphook_test.go @@ -50,13 +50,13 @@ func (s *HooksSuite) TestSafeForConcurrentAccess(c *C) { func TestClientNet(t *testing.T) { tests := []struct { - name string + name string clientNet string - want string + want string }{ - {"Empty value", "", "", }, - {"UDP", "udp", "udp", }, - {"TCP", "tcp", "tcp", }, + {"Empty value", "", ""}, + {"UDP", "udp", "udp"}, + {"TCP", "tcp", "tcp"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -64,7 +64,7 @@ func TestClientNet(t *testing.T) { hook := UDPHook{} f(&hook) - if hook.clientNet!= tt.want { + if hook.clientNet != tt.want { t.Errorf("ClientNet() = %v, want %v", hook.clientNet, tt.want) } }) @@ -73,13 +73,13 @@ func TestClientNet(t *testing.T) { func TestClientAddr(t *testing.T) { tests := []struct { - name string + name string clientAddr string - want string + want string }{ - {"Empty value", "", "", }, - {"Localhost and another port", "127.0.0.1:9999", "127.0.0.1:9999", }, - {"Another host", "192.168.0.1:9999", "192.168.0.1:9999", }, + {"Empty value", "", ""}, + {"Localhost and another port", "127.0.0.1:9999", "127.0.0.1:9999"}, + {"Another host", "192.168.0.1:9999", "192.168.0.1:9999"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -88,12 +88,45 @@ func TestClientAddr(t *testing.T) { f(&hook) if hook.clientAddr != tt.want { - t.Errorf("ClientAddr() = %v, want %v", hook.clientNet, tt.want) + t.Errorf("ClientAddr() = %v, want %v", hook.clientAddr, tt.want) } }) } } +func TestTarget(t *testing.T) { + type args struct { + network string + addr string + } + tests := []struct { + name string + args args + wantNet string + wantAddr string + }{ + {"Empty value", args{"", ""}, "", ""}, + {"Localhost and another port", args{"udp", "127.0.0.1:9999"}, "udp", "127.0.0.1:9999", }, + {"Another host", args{"tcp", "192.168.0.1:9999"}, "tcp","192.168.0.1:9999"}, + + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := Target(tt.args.network, tt.args.addr) + hook := UDPHook{} + f(&hook) + + if hook.clientAddr != tt.wantAddr { + t.Errorf("Target() addr = %v, want %v", hook.clientAddr, tt.wantAddr) + } + if hook.clientNet != tt.wantNet { + t.Errorf("ClientAddr() = %v, want %v", hook.clientNet, tt.wantNet) + } + }) + } +} + + func TestUDPHook_Fire(t *testing.T) { remoteAddr := "127.0.0.1:5501" raddr, err := net.ResolveUDPAddr("udp", remoteAddr) @@ -107,15 +140,15 @@ func TestUDPHook_Fire(t *testing.T) { var ok bool var ( - wg sync.WaitGroup - bytesRead int + wg sync.WaitGroup + bytesRead int serverReadError error ) wg.Add(1) go func() { defer wg.Done() var b = make([]byte, 1024) - UDPConn.SetDeadline(time.Now().Add(100*time.Millisecond)) + UDPConn.SetDeadline(time.Now().Add(100 * time.Millisecond)) bytesRead, _, serverReadError = UDPConn.ReadFromUDP(b) if bytesRead > 0 { ok = true @@ -123,7 +156,7 @@ func TestUDPHook_Fire(t *testing.T) { serverReadError = err }() - hook, err := NewUDPHook(ClientAddr(remoteAddr+"")) + hook, err := NewUDPHook(ClientAddr(remoteAddr + "")) logger := log.New() entry := log.NewEntry(logger) @@ -135,4 +168,4 @@ func TestUDPHook_Fire(t *testing.T) { if !ok { t.Errorf("UDP server read error: %v. Bytes read: %v", serverReadError, bytesRead) } -} \ No newline at end of file +} From 7b5be6fec9478c8c253b7118015ef859b54030ee Mon Sep 17 00:00:00 2001 From: Eugene Lisitsky Date: Tue, 19 Dec 2017 12:36:22 +0300 Subject: [PATCH 5/5] Bugfix, in specific situations logger stacktracer sees filename as """, skip it. --- log.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/log.go b/log.go index df89bac..1467de3 100644 --- a/log.go +++ b/log.go @@ -152,7 +152,8 @@ func (j *JSONFormatter) Format(e *log.Entry) ([]byte, error) { return (&j.JSONFormatter).Format(e) } -var r = regexp.MustCompile(`github\.com/(S|s)irupsen/logrus`) +var r = regexp.MustCompile(`github\.com/(S|s)irupsen/logrus|\`) + func findFrame() int { for i := 3; i < 10; i++ {