diff --git a/examples.txt b/examples.txt index de7120784..b637704b8 100644 --- a/examples.txt +++ b/examples.txt @@ -71,6 +71,7 @@ Command-Line Arguments Command-Line Flags Command-Line Subcommands Environment Variables +Logging HTTP Client HTTP Server Context diff --git a/examples/logging/logging.go b/examples/logging/logging.go new file mode 100644 index 000000000..18bbaf76d --- /dev/null +++ b/examples/logging/logging.go @@ -0,0 +1,77 @@ +// The Go standard library provides straightforward +// tools for outputting logs from Go programs, with +// the [log](https://pkg.go.dev/log) package for +// free-form output and the +// [log/slog](https://pkg.go.dev/log/slog) package for +// structured output. +package main + +import ( + "bytes" + "fmt" + "log" + "os" + + "log/slog" +) + +func main() { + + // Simply invoking functions like `Println` from the + // `log` package uses the _standard_ logger, which + // is already pre-configured for reasonable logging + // output to `os.Stderr`. Additional methods like + // `Fatal*` or `Panic*` will exit the program after + // logging. + log.Println("standard logger") + + // Loggers can be configured with _flags_ to set + // their output format. By default, the standard + // logger has the `log.Ldate` and `log.Ltime` flags + // set, and these are collected in `log.LstdFlags`. + // We can change its flags to emit time with + // microsecond accuracy, for example. + log.SetFlags(log.LstdFlags | log.Lmicroseconds) + log.Println("with micro") + + // It also supports emitting the file name and + // line from which the `log` function is called. + log.SetFlags(log.LstdFlags | log.Lshortfile) + log.Println("with file/line") + + // It may be useful to create a custom logger and + // pass it around. When creating a new logger, we + // can set a _prefix_ to distinguish its output + // from other loggers. + mylog := log.New(os.Stdout, "my:", log.LstdFlags) + mylog.Println("from mylog") + + // We can set the prefix + // on existing loggers (including the standard one) + // with the `SetPrefix` method. + mylog.SetPrefix("ohmy:") + mylog.Println("from mylog") + + // Loggers can have custom output targets; + // any `io.Writer` works. + var buf bytes.Buffer + buflog := log.New(&buf, "buf:", log.LstdFlags) + + // This call writes the log output into `buf`. + buflog.Println("hello") + + // This will actually show it on standard output. + fmt.Print("from buflog:", buf.String()) + + // The `slog` package provides + // _structured_ log output. For example, logging + // in JSON format is straightforward. + jsonHandler := slog.NewJSONHandler(os.Stderr, nil) + myslog := slog.New(jsonHandler) + myslog.Info("hi there") + + // In addition to the message, `slog` output can + // contain an arbitrary number of key=value + // pairs. + myslog.Info("hello again", "key", "val", "age", 25) +} diff --git a/examples/logging/logging.hash b/examples/logging/logging.hash new file mode 100644 index 000000000..4d1c7a70e --- /dev/null +++ b/examples/logging/logging.hash @@ -0,0 +1,2 @@ +38a7ef451859bb4c163df938b3a9d0e5ac293bef +Qd0uCqBlYUn diff --git a/examples/logging/logging.sh b/examples/logging/logging.sh new file mode 100644 index 000000000..00bcc76c1 --- /dev/null +++ b/examples/logging/logging.sh @@ -0,0 +1,18 @@ +# Sample output; the date and time +# emitted will depend on when the example ran. +$ go run logging.go +2023/08/22 10:45:16 standard logger +2023/08/22 10:45:16.904141 with micro +2023/08/22 10:45:16 logging.go:40: with file/line +my:2023/08/22 10:45:16 from mylog +ohmy:2023/08/22 10:45:16 from mylog +from buflog:buf:2023/08/22 10:45:16 hello + +# These are wrapped for clarity of presentation +# on the website; in reality they are emitted +# on a single line. +{"time":"2023-08-22T10:45:16.904166391-07:00", + "level":"INFO","msg":"hi there"} +{"time":"2023-08-22T10:45:16.904178985-07:00", + "level":"INFO","msg":"hello again", + "key":"val","age":25} diff --git a/public/environment-variables b/public/environment-variables index eb0ccb78d..ad03f4a1f 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -14,7 +14,7 @@ if (e.key == "ArrowRight") { - window.location.href = 'http-client'; + window.location.href = 'logging'; } } @@ -162,7 +162,7 @@ program picks that value up.
- Next example: HTTP Client. + Next example: Logging.
diff --git a/public/http-client b/public/http-client index b693af7c2..c00245320 100644 --- a/public/http-client +++ b/public/http-client @@ -9,7 +9,7 @@ onkeydown = (e) => { if (e.key == "ArrowLeft") { - window.location.href = 'environment-variables'; + window.location.href = 'logging'; } diff --git a/public/index.html b/public/index.html index 98549d651..54853fec8 100644 --- a/public/index.html +++ b/public/index.html @@ -173,6 +173,8 @@
+ The Go standard library provides straightforward +tools for outputting logs from Go programs, with +the log package for +free-form output and the +log/slog package for +structured output. + + |
+
+
+
+ |
+
+ + | +
+
+
+ |
+
+ + | +
+
+
+ |
+
+ + | +
+
+
+ |
+
+ Simply invoking functions like |
+
+
+
+ |
+
+ Loggers can be configured with flags to set
+their output format. By default, the standard
+logger has the |
+
+
+
+ |
+
+ It also supports emitting the file name and
+line from which the |
+
+
+
+ |
+
+ It may be useful to create a custom logger and +pass it around. When creating a new logger, we +can set a prefix to distinguish its output +from other loggers. + + |
+
+
+
+ |
+
+ We can set the prefix
+on existing loggers (including the standard one)
+with the |
+
+
+
+ |
+
+ Loggers can have custom output targets;
+any |
+
+
+
+ |
+
+ This call writes the log output into |
+
+
+
+ |
+
+ This will actually show it on standard output. + + |
+
+
+
+ |
+
+ The |
+
+
+
+ |
+
+ In addition to the message, |
+
+
+
+ |
+
+ Sample output; the date and time +emitted will depend on when the example ran. + + |
+
+
+
+ |
+
+ These are wrapped for clarity of presentation +on the website; in reality they are emitted +on a single line. + + |
+
+
+
+ |
+
+ Next example: HTTP Client. +
+ + + + +