Add new example: logging with the log and log/slog packages
This commit is contained in:
parent
146bd9cce2
commit
15d8fe75b8
@ -71,6 +71,7 @@ Command-Line Arguments
|
||||
Command-Line Flags
|
||||
Command-Line Subcommands
|
||||
Environment Variables
|
||||
Logging
|
||||
HTTP Client
|
||||
HTTP Server
|
||||
Context
|
||||
|
77
examples/logging/logging.go
Normal file
77
examples/logging/logging.go
Normal file
@ -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)
|
||||
}
|
2
examples/logging/logging.hash
Normal file
2
examples/logging/logging.hash
Normal file
@ -0,0 +1,2 @@
|
||||
38a7ef451859bb4c163df938b3a9d0e5ac293bef
|
||||
Qd0uCqBlYUn
|
18
examples/logging/logging.sh
Normal file
18
examples/logging/logging.sh
Normal file
@ -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}
|
4
public/environment-variables
generated
4
public/environment-variables
generated
@ -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.</p>
|
||||
|
||||
|
||||
<p class="next">
|
||||
Next example: <a href="http-client">HTTP Client</a>.
|
||||
Next example: <a href="logging">Logging</a>.
|
||||
</p>
|
||||
|
||||
|
||||
|
2
public/http-client
generated
2
public/http-client
generated
@ -9,7 +9,7 @@
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'environment-variables';
|
||||
window.location.href = 'logging';
|
||||
}
|
||||
|
||||
|
||||
|
2
public/index.html
generated
2
public/index.html
generated
@ -173,6 +173,8 @@
|
||||
|
||||
<li><a href="environment-variables">Environment Variables</a></li>
|
||||
|
||||
<li><a href="logging">Logging</a></li>
|
||||
|
||||
<li><a href="http-client">HTTP Client</a></li>
|
||||
|
||||
<li><a href="http-server">HTTP Server</a></li>
|
||||
|
276
public/logging
generated
Normal file
276
public/logging
generated
Normal file
@ -0,0 +1,276 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Go by Example: Logging</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'environment-variables';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'http-client';
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="logging">
|
||||
<h2><a href="./">Go by Example</a>: Logging</h2>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>The Go standard library provides straightforward
|
||||
tools for outputting logs from Go programs, with
|
||||
the <a href="https://pkg.go.dev/log">log</a> package for
|
||||
free-form output and the
|
||||
<a href="https://pkg.go.dev/log/slog">log/slog</a> package for
|
||||
structured output.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
<a href="https://go.dev/play/p/Qd0uCqBlYUn"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="s">"bytes"</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="s">"log"</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="s">"log/slog"</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Simply invoking functions like <code>Println</code> from the
|
||||
<code>log</code> package uses the <em>standard</em> logger, which
|
||||
is already pre-configured for reasonable logging
|
||||
output to <code>os.Stderr</code>. Additional methods like
|
||||
<code>Fatal*</code> or <code>Panic*</code> will exit the program after
|
||||
logging.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"standard logger"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Loggers can be configured with <em>flags</em> to set
|
||||
their output format. By default, the standard
|
||||
logger has the <code>log.Ldate</code> and <code>log.Ltime</code> flags
|
||||
set, and these are collected in <code>log.LstdFlags</code>.
|
||||
We can change its flags to emit time with
|
||||
microsecond accuracy, for example.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">SetFlags</span><span class="p">(</span><span class="nx">log</span><span class="p">.</span><span class="nx">LstdFlags</span> <span class="p">|</span> <span class="nx">log</span><span class="p">.</span><span class="nx">Lmicroseconds</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"with micro"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>It also supports emitting the file name and
|
||||
line from which the <code>log</code> function is called.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">SetFlags</span><span class="p">(</span><span class="nx">log</span><span class="p">.</span><span class="nx">LstdFlags</span> <span class="p">|</span> <span class="nx">log</span><span class="p">.</span><span class="nx">Lshortfile</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">log</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"with file/line"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>It may be useful to create a custom logger and
|
||||
pass it around. When creating a new logger, we
|
||||
can set a <em>prefix</em> to distinguish its output
|
||||
from other loggers.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">mylog</span> <span class="o">:=</span> <span class="nx">log</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stdout</span><span class="p">,</span> <span class="s">"my:"</span><span class="p">,</span> <span class="nx">log</span><span class="p">.</span><span class="nx">LstdFlags</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">mylog</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"from mylog"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>We can set the prefix
|
||||
on existing loggers (including the standard one)
|
||||
with the <code>SetPrefix</code> method.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">mylog</span><span class="p">.</span><span class="nf">SetPrefix</span><span class="p">(</span><span class="s">"ohmy:"</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">mylog</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"from mylog"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Loggers can have custom output targets;
|
||||
any <code>io.Writer</code> works.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">buf</span> <span class="nx">bytes</span><span class="p">.</span><span class="nx">Buffer</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">buflog</span> <span class="o">:=</span> <span class="nx">log</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="o">&</span><span class="nx">buf</span><span class="p">,</span> <span class="s">"buf:"</span><span class="p">,</span> <span class="nx">log</span><span class="p">.</span><span class="nx">LstdFlags</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>This call writes the log output into <code>buf</code>.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">buflog</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>This will actually show it on standard output.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Print</span><span class="p">(</span><span class="s">"from buflog:"</span><span class="p">,</span> <span class="nx">buf</span><span class="p">.</span><span class="nf">String</span><span class="p">())</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>The <code>slog</code> package provides
|
||||
<em>structured</em> log output. For example, logging
|
||||
in JSON format is straightforward.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">jsonHandler</span> <span class="o">:=</span> <span class="nx">slog</span><span class="p">.</span><span class="nf">NewJSONHandler</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="kc">nil</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">myslog</span> <span class="o">:=</span> <span class="nx">slog</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">jsonHandler</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"> <span class="nx">myslog</span><span class="p">.</span><span class="nf">Info</span><span class="p">(</span><span class="s">"hi there"</span><span class="p">)</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>In addition to the message, <code>slog</code> output can
|
||||
contain an arbitrary number of key=value
|
||||
pairs.</p>
|
||||
|
||||
</td>
|
||||
<td class="code">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"> <span class="nx">myslog</span><span class="p">.</span><span class="nf">Info</span><span class="p">(</span><span class="s">"hello again"</span><span class="p">,</span> <span class="s">"key"</span><span class="p">,</span> <span class="s">"val"</span><span class="p">,</span> <span class="s">"age"</span><span class="p">,</span> <span class="mi">25</span><span class="p">)</span>
|
||||
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Sample output; the date and time
|
||||
emitted will depend on when the example ran.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="gp">$</span> go run logging.go
|
||||
</span></span><span class="line"><span class="cl"><span class="go">2023/08/22 10:45:16 standard logger
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">2023/08/22 10:45:16.904141 with micro
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">2023/08/22 10:45:16 logging.go:40: with file/line
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">my:2023/08/22 10:45:16 from mylog
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">ohmy:2023/08/22 10:45:16 from mylog
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">from buflog:buf:2023/08/22 10:45:16 hello</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>These are wrapped for clarity of presentation
|
||||
on the website; in reality they are emitted
|
||||
on a single line.</p>
|
||||
|
||||
</td>
|
||||
<td class="code">
|
||||
|
||||
<pre class="chroma"><code><span class="line"><span class="cl"><span class="go">{"time":"2023-08-22T10:45:16.904166391-07:00",
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go"> "level":"INFO","msg":"hi there"}
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go">{"time":"2023-08-22T10:45:16.904178985-07:00",
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go"> "level":"INFO","msg":"hello again",
|
||||
</span></span></span><span class="line"><span class="cl"><span class="go"> "key":"val","age":25}</span></span></span></code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<p class="next">
|
||||
Next example: <a href="http-client">HTTP Client</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<p class="footer">
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> and <a href="https://eli.thegreenplace.net">Eli Bendersky</a> | <a href="https://github.com/mmcgrana/gobyexample">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('package main\u000A');codeLines.push('import (\u000A \"bytes\"\u000A \"fmt\"\u000A \"log\"\u000A \"os\"\u000A');codeLines.push(' \"log/slog\"\u000A)\u000A');codeLines.push('func main() {\u000A');codeLines.push(' log.Println(\"standard logger\")\u000A');codeLines.push(' log.SetFlags(log.LstdFlags | log.Lmicroseconds)\u000A log.Println(\"with micro\")\u000A');codeLines.push(' log.SetFlags(log.LstdFlags | log.Lshortfile)\u000A log.Println(\"with file/line\")\u000A');codeLines.push(' mylog :\u003D log.New(os.Stdout, \"my:\", log.LstdFlags)\u000A mylog.Println(\"from mylog\")\u000A');codeLines.push(' mylog.SetPrefix(\"ohmy:\")\u000A mylog.Println(\"from mylog\")\u000A');codeLines.push(' var buf bytes.Buffer\u000A buflog :\u003D log.New(\u0026buf, \"buf:\", log.LstdFlags)\u000A');codeLines.push(' buflog.Println(\"hello\")\u000A');codeLines.push(' fmt.Print(\"from buflog:\", buf.String())\u000A');codeLines.push(' jsonHandler :\u003D slog.NewJSONHandler(os.Stderr, nil)\u000A myslog :\u003D slog.New(jsonHandler)\u000A myslog.Info(\"hi there\")\u000A');codeLines.push(' myslog.Info(\"hello again\", \"key\", \"val\", \"age\", 25)\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user