github.com/Finschia/ostracon@v1.1.5/libs/log/zerolog_logger_test.go (about)

     1  package log_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"regexp"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/Finschia/ostracon/libs/log"
    13  )
    14  
    15  func TestZeroLogLoggerLogsItsErrors(t *testing.T) {
    16  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
    17  	if err != nil {
    18  		t.Fatal(err)
    19  	}
    20  	filepath := dir + "/app.log"
    21  
    22  	var buf bytes.Buffer
    23  	config := log.NewZeroLogConfig(true, "*:info", filepath, 0, 100, 0)
    24  	logger, err := log.NewZeroLogLogger(config, &buf)
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	logger.Info("foo", "baz baz", "bar")
    29  
    30  	msg := strings.TrimSpace(buf.String())
    31  	if !strings.Contains(msg, "foo") {
    32  		t.Errorf("expected logger msg to contain ErrInvalidKey, got %s", msg)
    33  	}
    34  
    35  	str, err := os.ReadFile(filepath)
    36  	if err != nil {
    37  		t.Fatal(err)
    38  	}
    39  	if !strings.Contains(string(str), "foo") {
    40  		t.Errorf("expected file logger msg to contain ErrInvalidKey, got %s", msg)
    41  	}
    42  }
    43  
    44  func TestZeroLogInfo(t *testing.T) {
    45  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	filepath := dir + "/app.log"
    50  
    51  	var buf bytes.Buffer
    52  	config := log.NewZeroLogConfig(true, "*:info", filepath, 0, 100, 0)
    53  	logger, err := log.NewZeroLogLogger(config, &buf)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	logger.Info("Client initialized with old header (trusted is more recent)",
    58  		"old", 42,
    59  		"trustedHeight", "forty two",
    60  		"trustedHash", fmt.Sprintf("%x", []byte("test me")))
    61  
    62  	msg := strings.TrimSpace(buf.String())
    63  	msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
    64  	const expectedMsg = `Client initialized with old header (trusted is more recent) old=42 trustedHash=74657374206d65 trustedHeight="forty two"`
    65  	if !strings.Contains(msg, expectedMsg) {
    66  		t.Fatalf("received %s, expected %s", msg, expectedMsg)
    67  	}
    68  
    69  	str, err := os.ReadFile(filepath)
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	msg = strings.TrimSpace(string(str))
    74  	if !strings.Contains(msg, expectedMsg) {
    75  		t.Fatalf("received %s, expected %s", msg, expectedMsg)
    76  	}
    77  }
    78  
    79  func TestZeroLogDebug(t *testing.T) {
    80  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  	filepath := dir + "/app.log"
    85  
    86  	var buf bytes.Buffer
    87  	config := log.NewZeroLogConfig(true, "*:debug", filepath, 0, 100, 0)
    88  	logger, err := log.NewZeroLogLogger(config, &buf)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	logger.Debug("Client initialized with old header (trusted is more recent)",
    93  		"old", 42,
    94  		"trustedHeight", "forty two",
    95  		"trustedHash", fmt.Sprintf("%x", []byte("test me")))
    96  
    97  	msg := strings.TrimSpace(buf.String())
    98  	msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
    99  	const expectedMsg = `Client initialized with old header (trusted is more recent) old=42 trustedHash=74657374206d65 trustedHeight="forty two"`
   100  	if !strings.Contains(msg, expectedMsg) {
   101  		t.Fatalf("received %s, expected %s", msg, expectedMsg)
   102  	}
   103  
   104  	str, err := os.ReadFile(filepath)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  	msg = strings.TrimSpace(string(str))
   109  	if !strings.Contains(msg, expectedMsg) {
   110  		t.Fatalf("received %s, expected %s", msg, expectedMsg)
   111  	}
   112  }
   113  
   114  func TestZeroLogError(t *testing.T) {
   115  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	filepath := dir + "/app.log"
   120  
   121  	var buf bytes.Buffer
   122  	config := log.NewZeroLogConfig(true, "*:error", filepath, 0, 100, 0)
   123  	logger, err := log.NewZeroLogLogger(config, &buf)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	logger.Error("Client initialized with old header (trusted is more recent)",
   128  		"old", 42,
   129  		"trustedHeight", "forty two",
   130  		"trustedHash", fmt.Sprintf("%x", []byte("test me")))
   131  
   132  	msg := strings.TrimSpace(buf.String())
   133  	msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   134  	const expectedMsg = `Client initialized with old header (trusted is more recent) old=42 trustedHash=74657374206d65 trustedHeight="forty two"`
   135  	if !strings.Contains(msg, expectedMsg) {
   136  		t.Fatalf("received %s, expected %s", msg, expectedMsg)
   137  	}
   138  
   139  	str, err := os.ReadFile(filepath)
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  	msg = strings.TrimSpace(string(str))
   144  	if !strings.Contains(msg, expectedMsg) {
   145  		t.Fatalf("received %s, expected %s", msg, expectedMsg)
   146  	}
   147  }
   148  
   149  func TestZeroLogLevelForModules(t *testing.T) {
   150  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  	filepath := dir + "/app.log"
   155  
   156  	var buf bytes.Buffer
   157  	config := log.NewZeroLogConfig(true, "module1:debug,module2:info,*:error", filepath, 0, 100, 0)
   158  	logger, err := log.NewZeroLogLogger(config, &buf)
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  
   163  	// logger level = debug
   164  	// debug O, info O, error O
   165  	{
   166  		loggerForModule1 := logger.With("module", "module1")
   167  
   168  		// debug O
   169  		loggerForModule1.Debug("a1", "b1", "c1")
   170  		msg := strings.TrimSpace(buf.String())
   171  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   172  		expectedMsg := "a1 b1=c1"
   173  		if !strings.Contains(msg, expectedMsg) {
   174  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   175  		}
   176  		str, err := os.ReadFile(filepath)
   177  		if err != nil {
   178  			t.Fatal(err)
   179  		}
   180  		msg = strings.TrimSpace(string(str))
   181  		if !strings.Contains(msg, expectedMsg) {
   182  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   183  		}
   184  
   185  		// info O
   186  		loggerForModule1.Info("a2", "b2", "c2")
   187  		msg = strings.TrimSpace(buf.String())
   188  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   189  		expectedMsg = "a2 b2=c2"
   190  		if !strings.Contains(msg, expectedMsg) {
   191  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   192  		}
   193  		str, err = os.ReadFile(filepath)
   194  		if err != nil {
   195  			t.Fatal(err)
   196  		}
   197  		msg = strings.TrimSpace(string(str))
   198  		if !strings.Contains(msg, expectedMsg) {
   199  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   200  		}
   201  
   202  		// error O
   203  		loggerForModule1.Error("a3", "b3", "c3")
   204  		msg = strings.TrimSpace(buf.String())
   205  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   206  		expectedMsg = "a3 b3=c3"
   207  		if !strings.Contains(msg, expectedMsg) {
   208  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   209  		}
   210  		str, err = os.ReadFile(filepath)
   211  		if err != nil {
   212  			t.Fatal(err)
   213  		}
   214  		msg = strings.TrimSpace(string(str))
   215  		if !strings.Contains(msg, expectedMsg) {
   216  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   217  		}
   218  	}
   219  
   220  	// logger level = info
   221  	// debug X, info O, error O
   222  	{
   223  		loggerForModule2 := logger.With("module", "module2")
   224  
   225  		// debug X
   226  		loggerForModule2.Debug("a4", "b4", "c4")
   227  		msg := strings.TrimSpace(buf.String())
   228  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   229  		expectedMsg := "a4 b4=c4"
   230  		if strings.Contains(msg, expectedMsg) {
   231  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   232  		}
   233  		str, err := os.ReadFile(filepath)
   234  		if err != nil {
   235  			t.Fatal(err)
   236  		}
   237  		msg = strings.TrimSpace(string(str))
   238  		if strings.Contains(msg, expectedMsg) {
   239  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   240  		}
   241  
   242  		// info O
   243  		loggerForModule2.Info("a5", "b5", "c5")
   244  		msg = strings.TrimSpace(buf.String())
   245  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   246  		expectedMsg = "a5 b5=c5"
   247  		if !strings.Contains(msg, expectedMsg) {
   248  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   249  		}
   250  		str, err = os.ReadFile(filepath)
   251  		if err != nil {
   252  			t.Fatal(err)
   253  		}
   254  		msg = strings.TrimSpace(string(str))
   255  		if !strings.Contains(msg, expectedMsg) {
   256  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   257  		}
   258  
   259  		// error O
   260  		loggerForModule2.Error("a6", "b6", "c6")
   261  		msg = strings.TrimSpace(buf.String())
   262  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   263  		expectedMsg = "a6 b6=c6"
   264  		if !strings.Contains(msg, expectedMsg) {
   265  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   266  		}
   267  		str, err = os.ReadFile(filepath)
   268  		if err != nil {
   269  			t.Fatal(err)
   270  		}
   271  		msg = strings.TrimSpace(string(str))
   272  		if !strings.Contains(msg, expectedMsg) {
   273  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   274  		}
   275  	}
   276  
   277  	// logger level = error
   278  	// debug X, info X, error O
   279  	{
   280  		loggerForModule3 := logger.With("module", "module3")
   281  
   282  		// debug X
   283  		loggerForModule3.Debug("a7", "b7", "c7")
   284  		msg := strings.TrimSpace(buf.String())
   285  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   286  		expectedMsg := "a7 b7=c7"
   287  		if strings.Contains(msg, expectedMsg) {
   288  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   289  		}
   290  		str, err := os.ReadFile(filepath)
   291  		if err != nil {
   292  			t.Fatal(err)
   293  		}
   294  		msg = strings.TrimSpace(string(str))
   295  		if strings.Contains(msg, expectedMsg) {
   296  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   297  		}
   298  
   299  		// info X
   300  		loggerForModule3.Info("a8", "b8", "c8")
   301  		msg = strings.TrimSpace(buf.String())
   302  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   303  		expectedMsg = "a8 b8=c8"
   304  		if strings.Contains(msg, expectedMsg) {
   305  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   306  		}
   307  		str, err = os.ReadFile(filepath)
   308  		if err != nil {
   309  			t.Fatal(err)
   310  		}
   311  		msg = strings.TrimSpace(string(str))
   312  		if strings.Contains(msg, expectedMsg) {
   313  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   314  		}
   315  
   316  		// error O
   317  		loggerForModule3.Error("a9", "b9", "c9")
   318  		msg = strings.TrimSpace(buf.String())
   319  		msg = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`).ReplaceAllString(msg, "")
   320  		expectedMsg = "a9 b9=c9"
   321  		if !strings.Contains(msg, expectedMsg) {
   322  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   323  		}
   324  		str, err = os.ReadFile(filepath)
   325  		if err != nil {
   326  			t.Fatal(err)
   327  		}
   328  		msg = strings.TrimSpace(string(str))
   329  		if !strings.Contains(msg, expectedMsg) {
   330  			t.Fatalf("received %s, expected %s", msg, expectedMsg)
   331  		}
   332  	}
   333  }
   334  
   335  func TestZeroLogRotateFiles(t *testing.T) {
   336  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	filepath := dir + "/app.log"
   341  
   342  	var buf bytes.Buffer
   343  	config := log.NewZeroLogConfig(true, "*:info", filepath, 1, 1, 2)
   344  	logger, err := log.NewZeroLogLogger(config, &buf)
   345  	if err != nil {
   346  		t.Fatal(err)
   347  	}
   348  
   349  	// it writes more than 1M logs so that two log files are created
   350  	msg := "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
   351  	for i := 0; i < 6000; i++ {
   352  		logger.Info(msg)
   353  	}
   354  
   355  	// check if only two log files is created
   356  	// ex) app.log, app-2022-12-16T10-21-41.295.log
   357  	files, err := os.ReadDir(dir)
   358  	if err != nil {
   359  		t.Fatal(err)
   360  	}
   361  	if len(files) != 2 {
   362  		t.Fatalf("file count created %d, expected %d", len(files), 2)
   363  	}
   364  
   365  	// change the filename of the backed up log file to one created 2 days ago
   366  	// ex) app-2022-12-16T10-21-41.295.log -> app-2022-12-14T10-21-41.295.log
   367  	now := time.Now().Add(-time.Hour * 48)
   368  	filename2 := fmt.Sprintf("app-%d-%02d-%02dT%02d-%02d-%02d.000.log", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
   369  	for _, f := range files {
   370  		if f.Name() == "app.log" {
   371  			continue
   372  		}
   373  
   374  		err = os.Rename(dir+"/"+f.Name(), dir+"/"+filename2)
   375  		if err != nil {
   376  			t.Fatalf("file rename failed old filename: %s, new filename: %s", dir+"/"+f.Name(), dir+"/"+filename2)
   377  		}
   378  	}
   379  
   380  	// write new logs for rotating log file(remove old log file)
   381  	// ex) app.log, app-2022-12-16T10-21-43.374.log
   382  	for i := 0; i < 6000; i++ {
   383  		logger.Info(msg)
   384  	}
   385  
   386  	// check if old log file is removed
   387  	files, err = os.ReadDir(dir)
   388  	if err != nil {
   389  		t.Fatal(err)
   390  	}
   391  	if len(files) != 2 {
   392  		t.Fatalf("created %d, expected %d", len(files), 2)
   393  	}
   394  	for _, f := range files {
   395  		if f.Name() == filename2 {
   396  			t.Fatalf("The log file has not been removed yet")
   397  		}
   398  	}
   399  }
   400  
   401  func BenchmarkZeroLogLoggerSimple(b *testing.B) {
   402  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
   403  	if err != nil {
   404  		b.Fatal(err)
   405  	}
   406  	filepath := dir + "/app.log"
   407  
   408  	var buf bytes.Buffer
   409  	config := log.NewZeroLogConfig(true, "*:info", filepath, 0, 100, 0)
   410  	logger, err := log.NewZeroLogLogger(config, &buf)
   411  	if err != nil {
   412  		b.Fatal(err)
   413  	}
   414  
   415  	benchmarkRunner(b, logger, baseInfoMessage)
   416  }
   417  
   418  func BenchmarkZeroLogLoggerContextual(b *testing.B) {
   419  	dir, err := os.MkdirTemp("/tmp", "zerolog-test")
   420  	if err != nil {
   421  		b.Fatal(err)
   422  	}
   423  	filepath := dir + "/app.log"
   424  
   425  	var buf bytes.Buffer
   426  	config := log.NewZeroLogConfig(true, "*:info", filepath, 0, 100, 0)
   427  	logger, err := log.NewZeroLogLogger(config, &buf)
   428  	if err != nil {
   429  		b.Fatal(err)
   430  	}
   431  
   432  	benchmarkRunner(b, logger, withInfoMessage)
   433  }