Browse Source

Add a DeferExitHandler function

Useful for running exit handlers in the same order as defer statements
tags/v1.4.0
Georgi Dimitrov 8 months ago
parent
commit
4ea4861398
2 changed files with 70 additions and 6 deletions
  1. 15
    3
      alt_exit.go
  2. 55
    3
      alt_exit_test.go

+ 15
- 3
alt_exit.go View File

@@ -51,9 +51,9 @@ func Exit(code int) {
51 51
 	os.Exit(code)
52 52
 }
53 53
 
54
-// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
55
-// all handlers. The handlers will also be invoked when any Fatal log entry is
56
-// made.
54
+// RegisterExitHandler appends a Logrus Exit handler to the list of handlers,
55
+// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
56
+// any Fatal log entry is made.
57 57
 //
58 58
 // This method is useful when a caller wishes to use logrus to log a fatal
59 59
 // message but also needs to gracefully shutdown. An example usecase could be
@@ -62,3 +62,15 @@ func Exit(code int) {
62 62
 func RegisterExitHandler(handler func()) {
63 63
 	handlers = append(handlers, handler)
64 64
 }
65
+
66
+// DeferExitHandler prepends a Logrus Exit handler to the list of handlers,
67
+// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
68
+// any Fatal log entry is made.
69
+//
70
+// This method is useful when a caller wishes to use logrus to log a fatal
71
+// message but also needs to gracefully shutdown. An example usecase could be
72
+// closing database connections, or sending a alert that the application is
73
+// closing.
74
+func DeferExitHandler(handler func()) {
75
+	handlers = append([]func(){handler}, handlers...)
76
+}

+ 55
- 3
alt_exit_test.go View File

@@ -14,9 +14,61 @@ import (
14 14
 
15 15
 func TestRegister(t *testing.T) {
16 16
 	current := len(handlers)
17
-	RegisterExitHandler(func() {})
18
-	if len(handlers) != current+1 {
19
-		t.Fatalf("expected %d handlers, got %d", current+1, len(handlers))
17
+
18
+	var results []string
19
+
20
+	h1 := func() { results = append(results, "first") }
21
+	h2 := func() { results = append(results, "second") }
22
+
23
+	RegisterExitHandler(h1)
24
+	RegisterExitHandler(h2)
25
+
26
+	if len(handlers) != current+2 {
27
+		t.Fatalf("expected %d handlers, got %d", current+2, len(handlers))
28
+	}
29
+
30
+	runHandlers()
31
+
32
+	if len(results) != 2 {
33
+		t.Fatalf("expected 2 handlers to be run, ran %d", len(results))
34
+	}
35
+
36
+	if results[0] != "first" {
37
+		t.Fatal("expected handler h1 to be run first, but it wasn't")
38
+	}
39
+
40
+	if results[1] != "second" {
41
+		t.Fatal("expected handler h2 to be run second, but it wasn't")
42
+	}
43
+}
44
+
45
+func TestDefer(t *testing.T) {
46
+	current := len(handlers)
47
+
48
+	var results []string
49
+
50
+	h1 := func() { results = append(results, "first") }
51
+	h2 := func() { results = append(results, "second") }
52
+
53
+	DeferExitHandler(h1)
54
+	DeferExitHandler(h2)
55
+
56
+	if len(handlers) != current+2 {
57
+		t.Fatalf("expected %d handlers, got %d", current+2, len(handlers))
58
+	}
59
+
60
+	runHandlers()
61
+
62
+	if len(results) != 2 {
63
+		t.Fatalf("expected 2 handlers to be run, ran %d", len(results))
64
+	}
65
+
66
+	if results[0] != "second" {
67
+		t.Fatal("expected handler h2 to be run first, but it wasn't")
68
+	}
69
+
70
+	if results[1] != "first" {
71
+		t.Fatal("expected handler h1 to be run second, but it wasn't")
20 72
 	}
21 73
 }
22 74
 

Loading…
Cancel
Save