From 5ec737c0b5500a80f4bbca8b418b8ccf2cf2fa8d Mon Sep 17 00:00:00 2001 From: Atsushi Watanabe Date: Thu, 8 Nov 2018 00:05:26 +0900 Subject: [PATCH 1/4] Control debug output by Option.Debug --- connection.go | 21 ++++++++++---------- debug.go | 36 +++++++++++++++++++++++++++++++++ debug_test.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ device.go | 9 ++++----- 4 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 debug.go create mode 100644 debug_test.go diff --git a/connection.go b/connection.go index e136933a..577eda8c 100644 --- a/connection.go +++ b/connection.go @@ -15,7 +15,6 @@ package awsiotdev import ( - "log" "time" "github.com/seqsense/aws-iot-device-sdk-go/pubqueue" @@ -70,11 +69,11 @@ func connectionHandler(c *DeviceClient) { } case <-c.stableTimerCh: - log.Print("Stable timer reached\n") + c.debugPrint("Stable timer reached\n") c.stateUpdateCh <- stable case state = <-c.stateUpdateCh: - log.Printf("State updated to %s\n", state.String()) + c.debugPrintf("State updated to %s\n", state.String()) switch state { case inactive: @@ -83,7 +82,7 @@ func connectionHandler(c *DeviceClient) { if c.reconnectPeriod > c.opt.MaximumReconnectTime { c.reconnectPeriod = c.opt.MaximumReconnectTime } - log.Printf("Trying to reconnect (%d ms)\n", c.reconnectPeriod/time.Millisecond) + c.debugPrintf("Trying to reconnect (%d ms)\n", c.reconnectPeriod/time.Millisecond) go func() { time.Sleep(c.reconnectPeriod) @@ -95,7 +94,7 @@ func connectionHandler(c *DeviceClient) { psq.resubscribe() case established: - log.Print("Processing queued operations\n") + c.debugPrint("Processing queued operations\n") go func() { time.Sleep(c.opt.MinimumConnectionTime) c.stableTimerCh <- true @@ -104,12 +103,12 @@ func connectionHandler(c *DeviceClient) { case stable: if statePrev == established { - log.Print("Connection is stable\n") + c.debugPrint("Connection is stable\n") c.reconnectPeriod = c.opt.BaseReconnectTime } case terminating: - log.Print("Terminating connection\n") + c.debugPrint("Terminating connection\n") c.cli.Disconnect(250) return @@ -125,7 +124,7 @@ func (s *pubSubQueues) publishOrEnqueue(d *pubqueue.Data) { go func() { token.Wait() if token.Error() != nil { - log.Printf("Failed to publish (%s)\n", token.Error()) + s.cli.debugPrintf("Failed to publish (%s)\n", token.Error()) // MQTT doesn't guarantee receive order; just append to the last s.cli.publishCh <- d } @@ -136,7 +135,7 @@ func (s *pubSubQueues) subscribeOrEnqueue(d *subqueue.Subscription) { go func() { token.Wait() if token.Error() != nil { - log.Printf("Failed to subscribe (%s)\n", token.Error()) + s.cli.debugPrintf("Failed to subscribe (%s)\n", token.Error()) s.cli.subscribeCh <- d } else { s.activeSubs[d.Topic] = d @@ -148,7 +147,7 @@ func (s *pubSubQueues) unsubscribeOrEnqueue(d *subqueue.Subscription) { go func() { token.Wait() if token.Error() != nil { - log.Printf("Failed to unsubscribe (%s)\n", token.Error()) + s.cli.debugPrintf("Failed to unsubscribe (%s)\n", token.Error()) s.cli.subscribeCh <- d } else { delete(s.activeSubs, d.Topic) @@ -183,7 +182,7 @@ func (s *pubSubQueues) resubscribe() { go func(d *subqueue.Subscription) { token.Wait() if token.Error() != nil { - log.Printf("Failed to subscribe (%s)\n", token.Error()) + s.cli.debugPrintf("Failed to subscribe (%s)\n", token.Error()) s.cli.subscribeCh <- d } else { s.activeSubs[d.Topic] = d diff --git a/debug.go b/debug.go new file mode 100644 index 00000000..69475f55 --- /dev/null +++ b/debug.go @@ -0,0 +1,36 @@ +package awsiotdev + +import ( + "log" +) + +var ( + // Backend function of debug print output. This can be replaced by custom logger. + DebugPrintBackend func(...interface{}) + // Backend function of debug printf output. This can be replaced by custom logger. + DebugPrintfBackend func(string, ...interface{}) + // Backend function of debug println output. This can be replaced by custom logger. + DebugPrintlnBackend func(...interface{}) +) + +func init() { + DebugPrintBackend = log.Print + DebugPrintfBackend = log.Printf + DebugPrintlnBackend = log.Println +} + +func (s *DeviceClient) debugPrint(a ...interface{}) { + if s.opt.Debug { + DebugPrintBackend(a...) + } +} +func (s *DeviceClient) debugPrintf(format string, a ...interface{}) { + if s.opt.Debug { + DebugPrintfBackend(format, a...) + } +} +func (s *DeviceClient) debugPrintln(a ...interface{}) { + if s.opt.Debug { + DebugPrintlnBackend(a...) + } +} diff --git a/debug_test.go b/debug_test.go new file mode 100644 index 00000000..b3f9f156 --- /dev/null +++ b/debug_test.go @@ -0,0 +1,55 @@ +package awsiotdev + +import ( + "errors" + "fmt" + "log" +) + +func Example_debugPrint() { + DebugPrintBackend = func(a ...interface{}) { + fmt.Print(a...) + } + + s := &DeviceClient{opt: &Options{Debug: true}} + s.debugPrint("Test1:", true) + s = &DeviceClient{opt: &Options{Debug: false}} + s.debugPrint("Test2:", false) + + DebugPrintBackend = log.Print + + // Output: + // Test1:true +} + +func Example_debugPrintf() { + DebugPrintfBackend = func(format string, a ...interface{}) { + fmt.Printf(format, a...) + } + + s := &DeviceClient{opt: &Options{Debug: true}} + s.debugPrintf("Formatted value 1 (%d)", 10) + s = &DeviceClient{opt: &Options{Debug: false}} + s.debugPrintf("Formatted value 2 (%d)", 11) + + DebugPrintfBackend = log.Printf + + // Output: + // Formatted value 1 (10) +} + +func Example_debugPrintln() { + DebugPrintlnBackend = func(a ...interface{}) { + fmt.Println(a...) + } + + s := &DeviceClient{opt: &Options{Debug: true}} + s.debugPrintln(errors.New("Error string 1")) + s = &DeviceClient{opt: &Options{Debug: false}} + s.debugPrintln(errors.New("Error string 2")) + + DebugPrintlnBackend = log.Println + + // Output: + // Error string 1 +} diff --git a/device.go b/device.go index 25610444..9301f9c0 100644 --- a/device.go +++ b/device.go @@ -18,7 +18,6 @@ Package awsiotdev implements offline queueing and reconnecting features of MQTT package awsiotdev import ( - "log" "time" mqtt "github.com/eclipse/paho.mqtt.golang" @@ -51,7 +50,7 @@ type DeviceClient struct { func New(opt *Options) *DeviceClient { if opt.Protocol != "" || opt.Host != "" { - log.Printf("Options.Protocol and Options.Host is deprecated. Use Options.URL instead.") + (&DeviceClient{opt: opt}).debugPrint("Options.Protocol and Options.Host are deprecated. Use Options.URL instead.") opt.Url = opt.Protocol + "://" + opt.Host } p, err := awsiotprotocol.ByUrl(opt.Url) @@ -83,11 +82,11 @@ func New(opt *Options) *DeviceClient { } connectionLost := func(client mqtt.Client, err error) { - log.Printf("Connection lost (%s)\n", err.Error()) + d.debugPrintf("Connection lost (%s)\n", err.Error()) d.stateUpdateCh <- inactive } onConnect := func(client mqtt.Client) { - log.Printf("Connection established\n") + d.debugPrintf("Connection established\n") d.stateUpdateCh <- established } @@ -120,7 +119,7 @@ func (s *DeviceClient) connect() { go func() { token.Wait() if token.Error() != nil { - log.Printf("Failed to connect (%s)\n", token.Error()) + s.debugPrintf("Failed to connect (%s)\n", token.Error()) s.stateUpdateCh <- inactive } }() From 9f87946defff8216455532266e190d19f55a8024 Mon Sep 17 00:00:00 2001 From: Atsushi Watanabe Date: Thu, 8 Nov 2018 10:07:46 +0900 Subject: [PATCH 2/4] Enable debug output in the sample --- sample/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample/main.go b/sample/main.go index ba46bdbd..b119b529 100644 --- a/sample/main.go +++ b/sample/main.go @@ -62,7 +62,7 @@ func main() { MinimumConnectionTime: time.Second * 2, Keepalive: time.Second * 2, Url: *url, - Debug: false, + Debug: true, Qos: 1, Retain: false, Will: &awsiot.TopicPayload{Topic: "notification", Payload: "{\"status\": \"dead\"}"}, From e3c95f3d97606815a180c71369cfdb5acf1455ba Mon Sep 17 00:00:00 2001 From: Atsushi Watanabe Date: Thu, 8 Nov 2018 11:02:14 +0900 Subject: [PATCH 3/4] Move default debug print backend to var() --- debug.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/debug.go b/debug.go index 69475f55..d7791ebb 100644 --- a/debug.go +++ b/debug.go @@ -6,19 +6,13 @@ import ( var ( // Backend function of debug print output. This can be replaced by custom logger. - DebugPrintBackend func(...interface{}) + DebugPrintBackend func(...interface{}) = log.Print // Backend function of debug printf output. This can be replaced by custom logger. - DebugPrintfBackend func(string, ...interface{}) + DebugPrintfBackend func(string, ...interface{}) = log.Printf // Backend function of debug println output. This can be replaced by custom logger. - DebugPrintlnBackend func(...interface{}) + DebugPrintlnBackend func(...interface{}) = log.Println ) -func init() { - DebugPrintBackend = log.Print - DebugPrintfBackend = log.Printf - DebugPrintlnBackend = log.Println -} - func (s *DeviceClient) debugPrint(a ...interface{}) { if s.opt.Debug { DebugPrintBackend(a...) From cd1cb10aef9e0b02370f56fd8212a4a9c8e90e5b Mon Sep 17 00:00:00 2001 From: Atsushi Watanabe Date: Thu, 8 Nov 2018 12:03:22 +0900 Subject: [PATCH 4/4] Unexpose example test for internal debug output --- connection.go | 20 ++++++++++---------- debug.go | 16 ++++++++++------ debug_test.go | 30 +++++++++++++++--------------- device.go | 10 ++++++---- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/connection.go b/connection.go index 237a59a1..715ccb55 100644 --- a/connection.go +++ b/connection.go @@ -69,11 +69,11 @@ func connectionHandler(c *DeviceClient) { } case <-c.stableTimerCh: - c.debugPrint("Stable timer reached\n") + c.dbg.print("Stable timer reached\n") c.stateUpdateCh <- stable case state = <-c.stateUpdateCh: - c.debugPrintf("State updated to %s\n", state.String()) + c.dbg.printf("State updated to %s\n", state.String()) switch state { case inactive: @@ -82,7 +82,7 @@ func connectionHandler(c *DeviceClient) { if c.reconnectPeriod > c.opt.MaximumReconnectTime { c.reconnectPeriod = c.opt.MaximumReconnectTime } - c.debugPrintf("Trying to reconnect (%d ms)\n", c.reconnectPeriod/time.Millisecond) + c.dbg.printf("Trying to reconnect (%d ms)\n", c.reconnectPeriod/time.Millisecond) if c.opt.OnConnectionLost != nil { c.opt.OnConnectionLost(c.opt) } @@ -97,7 +97,7 @@ func connectionHandler(c *DeviceClient) { psq.resubscribe() case established: - c.debugPrint("Processing queued operations\n") + c.dbg.print("Processing queued operations\n") go func() { time.Sleep(c.opt.MinimumConnectionTime) c.stableTimerCh <- true @@ -106,12 +106,12 @@ func connectionHandler(c *DeviceClient) { case stable: if statePrev == established { - c.debugPrint("Connection is stable\n") + c.dbg.print("Connection is stable\n") c.reconnectPeriod = c.opt.BaseReconnectTime } case terminating: - c.debugPrint("Terminating connection\n") + c.dbg.print("Terminating connection\n") c.cli.Disconnect(250) return @@ -127,7 +127,7 @@ func (s *pubSubQueues) publishOrEnqueue(d *pubqueue.Data) { go func() { token.Wait() if token.Error() != nil { - s.cli.debugPrintf("Failed to publish (%s)\n", token.Error()) + s.cli.dbg.printf("Failed to publish (%s)\n", token.Error()) // MQTT doesn't guarantee receive order; just append to the last s.cli.publishCh <- d } @@ -138,7 +138,7 @@ func (s *pubSubQueues) subscribeOrEnqueue(d *subqueue.Subscription) { go func() { token.Wait() if token.Error() != nil { - s.cli.debugPrintf("Failed to subscribe (%s)\n", token.Error()) + s.cli.dbg.printf("Failed to subscribe (%s)\n", token.Error()) s.cli.subscribeCh <- d } else { s.activeSubs[d.Topic] = d @@ -150,7 +150,7 @@ func (s *pubSubQueues) unsubscribeOrEnqueue(d *subqueue.Subscription) { go func() { token.Wait() if token.Error() != nil { - s.cli.debugPrintf("Failed to unsubscribe (%s)\n", token.Error()) + s.cli.dbg.printf("Failed to unsubscribe (%s)\n", token.Error()) s.cli.subscribeCh <- d } else { delete(s.activeSubs, d.Topic) @@ -185,7 +185,7 @@ func (s *pubSubQueues) resubscribe() { go func(d *subqueue.Subscription) { token.Wait() if token.Error() != nil { - s.cli.debugPrintf("Failed to subscribe (%s)\n", token.Error()) + s.cli.dbg.printf("Failed to subscribe (%s)\n", token.Error()) s.cli.subscribeCh <- d } else { s.activeSubs[d.Topic] = d diff --git a/debug.go b/debug.go index d7791ebb..8fc9b015 100644 --- a/debug.go +++ b/debug.go @@ -13,18 +13,22 @@ var ( DebugPrintlnBackend func(...interface{}) = log.Println ) -func (s *DeviceClient) debugPrint(a ...interface{}) { - if s.opt.Debug { +type debugOut struct { + enable bool +} + +func (s *debugOut) print(a ...interface{}) { + if s.enable { DebugPrintBackend(a...) } } -func (s *DeviceClient) debugPrintf(format string, a ...interface{}) { - if s.opt.Debug { +func (s *debugOut) printf(format string, a ...interface{}) { + if s.enable { DebugPrintfBackend(format, a...) } } -func (s *DeviceClient) debugPrintln(a ...interface{}) { - if s.opt.Debug { +func (s *debugOut) println(a ...interface{}) { + if s.enable { DebugPrintlnBackend(a...) } } diff --git a/debug_test.go b/debug_test.go index b3f9f156..caf49278 100644 --- a/debug_test.go +++ b/debug_test.go @@ -6,15 +6,15 @@ import ( "log" ) -func Example_debugPrint() { +func Example_debugOut_print() { DebugPrintBackend = func(a ...interface{}) { fmt.Print(a...) } - s := &DeviceClient{opt: &Options{Debug: true}} - s.debugPrint("Test1:", true) - s = &DeviceClient{opt: &Options{Debug: false}} - s.debugPrint("Test2:", false) + s := &debugOut{true} + s.print("Test1:", true) + s = &debugOut{false} + s.print("Test2:", false) DebugPrintBackend = log.Print @@ -22,15 +22,15 @@ func Example_debugPrint() { // Test1:true } -func Example_debugPrintf() { +func Example_debugOut_printf() { DebugPrintfBackend = func(format string, a ...interface{}) { fmt.Printf(format, a...) } - s := &DeviceClient{opt: &Options{Debug: true}} - s.debugPrintf("Formatted value 1 (%d)", 10) - s = &DeviceClient{opt: &Options{Debug: false}} - s.debugPrintf("Formatted value 2 (%d)", 11) + s := &debugOut{true} + s.printf("Formatted value 1 (%d)", 10) + s = &debugOut{false} + s.printf("Formatted value 2 (%d)", 11) DebugPrintfBackend = log.Printf @@ -38,15 +38,15 @@ func Example_debugPrintf() { // Formatted value 1 (10) } -func Example_debugPrintln() { +func Example_debugOut_println() { DebugPrintlnBackend = func(a ...interface{}) { fmt.Println(a...) } - s := &DeviceClient{opt: &Options{Debug: true}} - s.debugPrintln(errors.New("Error string 1")) - s = &DeviceClient{opt: &Options{Debug: false}} - s.debugPrintln(errors.New("Error string 2")) + s := &debugOut{true} + s.println(errors.New("Error string 1")) + s = &debugOut{false} + s.println(errors.New("Error string 2")) DebugPrintlnBackend = log.Println diff --git a/device.go b/device.go index 9301f9c0..d72518b8 100644 --- a/device.go +++ b/device.go @@ -46,11 +46,12 @@ type DeviceClient struct { stableTimerCh chan bool publishCh chan *pubqueue.Data subscribeCh chan *subqueue.Subscription + dbg *debugOut } func New(opt *Options) *DeviceClient { if opt.Protocol != "" || opt.Host != "" { - (&DeviceClient{opt: opt}).debugPrint("Options.Protocol and Options.Host are deprecated. Use Options.URL instead.") + (&debugOut{opt.Debug}).print("Options.Protocol and Options.Host are deprecated. Use Options.URL instead.") opt.Url = opt.Protocol + "://" + opt.Host } p, err := awsiotprotocol.ByUrl(opt.Url) @@ -79,14 +80,15 @@ func New(opt *Options) *DeviceClient { stableTimerCh: make(chan bool), publishCh: make(chan *pubqueue.Data, publishChCap), subscribeCh: make(chan *subqueue.Subscription, subscribeChCap), + dbg: &debugOut{opt.Debug}, } connectionLost := func(client mqtt.Client, err error) { - d.debugPrintf("Connection lost (%s)\n", err.Error()) + d.dbg.printf("Connection lost (%s)\n", err.Error()) d.stateUpdateCh <- inactive } onConnect := func(client mqtt.Client) { - d.debugPrintf("Connection established\n") + d.dbg.printf("Connection established\n") d.stateUpdateCh <- established } @@ -119,7 +121,7 @@ func (s *DeviceClient) connect() { go func() { token.Wait() if token.Error() != nil { - s.debugPrintf("Failed to connect (%s)\n", token.Error()) + s.dbg.printf("Failed to connect (%s)\n", token.Error()) s.stateUpdateCh <- inactive } }()