如何筛选错误日志写入程序:TLS握手错误



如何在错误日志中过滤掉这类错误消息?这些消息充斥着错误日志,很难监控应用程序。

消息主要发生在尝试在没有任何HTTP请求的情况下建立TLS连接时

2022/10/23 01:05:26 server.go:3230: http: TLS handshake error from xx.xx.xx.xx: read tcp xx.xx.xx.xx:x->xx.xx.xx.xx: read: connection reset by peer
2022/10/23 01:05:26 server.go:3230: http: TLS handshake error from xx.xx.xx.xx: tls: client requested unsupported application protocols ([http/0.9 http/1.0 spdy/1 spdy/2 spdy/3 h2c hq])
2022/10/23 02:58:54 server.go:3230: http: TLS handshake error from xx.xx.xx.xx: EOF

http.Server具有字段ErrorLog。您可以将其底层编写器替换为一个自定义编写器,该编写器过滤掉包含"的字符串;TLS握手错误";

下面是一个带有两个服务器的简单示例。一台服务器侦听端口8443并使用完整日志。另一个服务器使用过滤日志并侦听端口8444。

客户端连接到服务器。具有完整日志的服务器打印http: TLS handshake error from 127.0.0.1:xxxxx: remote error: tls: bad certificate。具有筛选日志的服务器什么也不查询。

该示例演示了最简单的过滤记录器,它过滤掉带有固定子字符串的行。

package main
import (
"bytes"
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"sync"
"time"
)
// Filters out lines that contain substring
type FilteringWriter struct {
writer    io.Writer
substring []byte
}
func (fw FilteringWriter) Write(b []byte) (n int, err error) {
if bytes.Index(b, fw.substring) > -1 {
// Filter out the line that matches the pattern
return len(b), nil
}
return fw.writer.Write(b)
}
func NewFilteringWriter(writer io.Writer, pattern string) FilteringWriter {
return FilteringWriter{
writer:    writer,
substring: []byte(pattern),
}
}
// Server handler function
func HelloWorld(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("Hello, world!n"))
}
// Trivial server executor
func runServer(server *http.Server, wg *sync.WaitGroup) {
server.ListenAndServeTLS("server.crt", "server.key")
wg.Done()
}
// Shutdown server
func shutdownServer(server *http.Server) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second))
server.Shutdown(ctx)
cancel()
}
func main() {
fullLogger := log.New(
os.Stderr,
"full: ",
log.LstdFlags,
)
// Log that filters "TLS handshake error"
errorLogger := log.New(
NewFilteringWriter(
os.Stderr,
"http: TLS handshake error",
),
"filtered: ",
log.LstdFlags,
)
serverMux := http.NewServeMux()
serverMux.HandleFunc("/hello", HelloWorld)
server1 := &http.Server{
Addr:     "localhost:8443",
Handler:  serverMux,
ErrorLog: fullLogger,
}
server2 := &http.Server{
Addr:     "localhost:8444",
Handler:  serverMux,
ErrorLog: errorLogger,
}
wg := sync.WaitGroup{}
wg.Add(2)
go runServer(server1, &wg)
go runServer(server2, &wg)
// Test loggers
// Client connects to the servers
// The server with the full log prints
// `http: TLS handshake error from 127.0.0.1:53182: remote error: tls: bad certificate`
// the server with the filtering log pints nothing
client := http.Client{}
time.Sleep(100 * time.Millisecond)
log.Println("Client connects to the server with full log")
reponse, err := client.Get(fmt.Sprintf("https://%s/hello", server1.Addr))
if err != nil {
log.Printf("Client failed: %v", err)
} else {
log.Printf("Server returned: %v", reponse)
}
time.Sleep(100 * time.Millisecond)
log.Println("Client connects to the server with filtered log")
reponse, err = client.Get(fmt.Sprintf("https://%s/hello", server2.Addr))
if err != nil {
log.Printf("Client failed: %v", err)
} else {
log.Printf("Server returned: %v", reponse)
}
shutdownServer(server1)
shutdownServer(server2)
wg.Wait()
}

输出:

2022/10/27 19:20:52 Client connects to the server with full log
2022/10/27 19:20:52 Client failed: Get "https://localhost:8443/hello": x509: certificate is not valid for any names, but wanted to match localhost
full: 2022/10/27 19:20:52 http: TLS handshake error from 127.0.0.1:53182: remote error: tls: bad certificate
2022/10/27 19:20:52 Client connects to the server with filtered log
2022/10/27 19:20:52 Client failed: Get "https://localhost:8444/hello": x509: certificate is not valid for any names, but wanted to match localhost

正如您所看到的,有来自服务器1的日志行,而没有服务器2的日志行。

最新更新