새로운 Go 1.21의 패키지는 표준 라이브러리에 구조화된 로그를 가져옵니다. 구조화된 로그는 키 값 쌍을 사용하여 빠르고 신뢰할 수 있도록 파스팅, 필터링, 검색 및 분석할 수 있습니다. 서버의 경우 로그링은 개발자가 시스템의 상세한 행동을 관찰하는 중요한 방법이며, 종종 첫 번째 장소는 그것을 디버그하는 것입니다. log/slog 표준 도서관에는 로깅 패키지가 있었고, , Go의 초기 출시 이후 10 년이 넘었습니다. 시간이 지남에 따라 우리는 구조화 된 로깅이 Go 프로그래머에게 중요하다는 것을 배웠습니다. 그것은 지속적으로 우리의 연례 설문 조사에서 높은 순위를 차지하고 있으며 Go 생태계의 많은 패키지는 그것을 제공합니다. , 100,000개가 넘는 다른 패키지에서 사용됩니다. log 성취 많은 구조화된 로그링 패키지를 선택할 수 있기 때문에 대형 프로그램은 종종 그들의 의존성을 통해 하나 이상을 포함하는 경우가 많습니다. 주요 프로그램은 로그 출력이 일관되도록 이러한 로그링 패키지를 각각 구성해야 할 수 있습니다 : 모두 같은 장소, 같은 형식으로 이동합니다. A Tour of slog 슬라이드 여기 사용하는 가장 간단한 프로그램입니다. : slog package main import "log/slog" func main() { slog.Info("hello, world") } 이 글을 읽으면서, 그것은 인쇄한다: 2023/08/04 16:09:19 INFO hello, world 이 함수는 기본 로그를 사용하여 Info 로그 수준에서 메시지를 인쇄합니다.function prints a message at the Info log level using the default logger, which in this case is the default logger from the 패키지 - 당신이 쓸 때 얻는 동일한 로거 이것은 출력이 왜 그렇게 비슷하게 보이는지 설명합니다 : "INFO"만 새롭습니다. 그리고 원본 패키지는 함께 작동하여 쉽게 시작할 수 있습니다. Info log log.Printf slog log 이외에도 , 세 가지 다른 레벨에 대한 기능이 있습니다 - , 그리고 뿐만 아니라 더 일반적인 레벨을 논쟁으로 삼는 함수.In , 레벨은 단지 전체 숫자이므로 네 개의 이름을 지정한 레벨에 국한되지 않습니다. 0 이고 그리고 로깅 시스템이 그 사이에 레벨이 있다면, 그것을 위해 2를 사용할 수 있습니다. Info Debug Warn Error Log slog Info Warn 이와 달리, the 패키지, 우리는 쉽게 메시지 후에 그들을 작성하여 우리의 출력에 키 값 쌍을 추가 할 수 있습니다 : log slog.Info("hello, world", "user", os.Getenv("USER")) 이제 출력은 이렇게 보입니다: The output now looks like this: 2023/08/04 16:27:19 INFO hello, world user=jba 우리가 언급한 것처럼, 's 최고 수준의 함수는 기본 로그인을 사용할 수 있습니다.We can get this logger explicitly, and call its methods: slog logger := slog.Default() logger.Info("hello, world", "user", os.Getenv("USER")) 각 상위 레벨 함수는 a의 방법에 해당합니다.Each top-level function corresponds to a method on a 출력은 이전과 동일합니다. slog.Logger 처음에는 slog의 출력이 기본값을 통과합니다.Initially, slog's output goes through the default 우리가 위에서 본 출력을 생산합니다.우리는 출력을 변경하여 출력을 변경할 수 있습니다. logger에 의해 사용됩니다. 2 개의 내장된 핸들러와 함께 제공됩니다. a 폼에 있는 모든 로그 정보를 발송합니다.Emmits all log information in the form 이 프로그램은 A를 사용하여 새 로거를 만듭니다.This program creates a new logger using a 이와 동일한 호소를 하여 방법 : log.Logger 거래 slog TextHandler key=value TextHandler Info logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) logger.Info("hello, world", "user", os.Getenv("USER")) 이제 출력은 이렇게 보입니다 : time=2023-08-04T16:56:03.786-04:00 level=INFO msg="hello, world" user=jba 모든 것이 키 값 쌍으로 변환되었으며 구조를 유지하기 위해 필요에 따라 문자열을 인용했습니다. JSON 출력의 경우, 내장된 대신 : JSONHandler logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) logger.Info("hello, world", "user", os.Getenv("USER")) 이제 우리의 출력은 JSON 개체의 시퀀스이며, 로그 호출 당 하나입니다.Now our output is a sequence of JSON objects, one per logging call: {"time":"2023-08-04T16:58:02.939245411-04:00","level":"INFO","msg":"hello, world","user":"jba"} 당신은 내장된 핸들러에 국한되지 않습니다.누구나 핸들러를 구현하여 핸들러를 작성할 수 있습니다. 컨트롤러는 특정 형식으로 출력을 생성하거나, 기능을 추가하기 위해 다른 컨트롤러를 포장할 수 있습니다. 에서 The 문서는 로그 메시지가 표시되는 최소 수준을 변경하는 포장 처리기를 작성하는 방법을 보여줍니다.documentation shows how to write a wrapping handler that changes the minimum level at which log messages will be displayed. slog.Handler 예제들 slog 우리가 지금까지 사용해 왔던 속성에 대한 대체 키 값 구문은 편리하지만, 자주 실행되는 로그 문에 대해서는 해당 속성을 사용하는 것이 더 효율적일 수 있습니다. Type 및 Call the 메모리 할당을 최소화하기 위해 함께 작동합니다. s는 문자열, 숫자 및 다른 일반적인 유형을 제외합니다. Attr LogAttrs Attr 이 호출은 위와 동일한 출력을 생산하지만 더 빨라집니다: LogAttrs slog.LogAttrs(context.Background(), slog.LevelInfo, "hello, world", slog.String("user", os.Getenv("USER"))) 더 많은 것들이 있어요 : slog LogAttrs에 대한 호출이 보여 주듯, 일부 로그 함수에 컨텍스트를 전달할 수 있으므로 컨텍스트 ID와 같은 컨텍스트 정보를 추출할 수 있습니다.As the call to LogAttrs shows, you can pass a context.Context to some log functions so a handler can extract context information such as trace IDs. (Canceling the context does not prevent the log entry from being written.) Logger.With를 호출하면 모든 출력에 나타날 로그에 속성을 추가하여 여러 로그 문자의 공통 부분을 효과적으로 계산할 수 있습니다.이것은 편리할뿐만 아니라 아래에서 논의한 것처럼 성능을 도울 수 있습니다. 이로써 로그 출력에 더 많은 구조를 추가할 수 있으며, 그렇지 않으면 동일한 키를 분명히 할 수 있습니다.This can add more structure to your log output and can help to disambiguate keys that would otherwise be identical. LogValue 메서드를 사용하여 로그에 표시되는 값을 제어할 수 있습니다.You can control how a value appears in the logs by providing its type with a LogValue method. That can be used to log the fields of a struct as a group or edit sensitive data, among other things. 모든 것에 대해 배우는 가장 좋은 장소 그것은 The . slog 패키지 문서 성능 우리는 원했던 대규모 성능 상승을 위해, 우리는 설계 최적화의 기회를 제공하는 인터페이스.The 메서드는 각 로그 이벤트의 시작 부분에서 호출되며, 처리자에게 원치 않는 로그 이벤트를 빠르게 떨어 뜨릴 수 있는 기회를 제공합니다. 그리고 methods let the handler format attributes added by 를 사용하여 추가할 수 있습니다. 이 사전 포맷은 대규모 속성, 예를 들어 로그 호출을 할 때 상당한 속도를 제공할 수 있습니다. A 는 A 를 추가합니다. 그리고 그 후에 많은 호출에 사용되었습니다. slog 이 Handler Enabled WithAttrs WithGroup Logger.With http.Request Logger 성능 최적화 작업을 통보하기 위해 기존 오픈소스 프로젝트에서 일반적인 로그링 패턴을 조사했습니다. 로그링 방법에 대한 호출의 95 % 이상이 5개 이상의 속성을 통과하는 것으로 나타났습니다. 그런 다음 우리는 일반적인 사례를 캡처하는 벤치마크를 썼고, 시간이 어디로 갔는지 알기 위해 가이드로 사용했습니다.The biggest gains came from paying careful attention to memory allocation. 디자인 프로세스 이 패키지는 Go 1이 2012 년에 출시 된 이후 표준 라이브러리에 가장 큰 추가 중 하나입니다.We wanted to take our time designing it, and we knew community feedback would be essential. slog 2022년 4월까지 우리는 Go 커뮤니티에 대한 구조화된 로깅의 중요성을 입증하기에 충분한 데이터를 수집했으며 Go 팀은 표준 라이브러리에 추가하는 것을 탐구하기로 결정했습니다. 우리는 기존의 구조화된 로그링 패키지가 어떻게 설계되었는지 살펴보면서 시작했습니다.우리는 또한 Go 모듈 프록시에 저장된 오픈 소스 Go 코드의 대규모 컬렉션을 활용하여 이러한 패키지를 실제로 사용하는 방법을 배웠습니다.우리의 첫 번째 디자인은 이 연구뿐만 아니라 Go의 단순성 정신에 의해 알려졌습니다.우리는 성능을 희생하지 않고도 페이지에 가볍고 이해하기 쉬운 API를 원했습니다. 그들은 모두 그들이하는 일을 잘하고 있으며 잘 작동하는 기존 코드를 대체하는 것은 개발자의 시간을 잘 사용하는 것이 거의 아닙니다. 백엔드 인터페이스라고 불리면, 이러한 방식으로 기존의 로그링 패키지는 공통적인 백엔드와 대화할 수 있으므로 그들을 사용하는 패키지는 다시 작성할 필요 없이 상호 작용할 수 있습니다.Handlers are written or in progress for many common logging packages, including , 그리고 . Logger Handler 로저 HCL로 우리는 Go 팀과 광범위한 재배 경험을 가진 다른 개발자들과 우리의 초기 디자인을 공유했습니다.우리는 그들의 피드백을 바탕으로 변경을 했고, 2022년 8월까지 우리는 우리가 실행 가능한 디자인을 가지고 있다고 느꼈습니다. 공개 및 시작 a 커뮤니티가 무엇을 말해야 하는지 듣기 위해 반응은 열정적이고 대부분 긍정적이었습니다.다른 구조화된 로깅 패키지의 디자이너와 사용자들로부터의 통찰력있는 의견 덕분에 우리는 몇 가지 변경을 했고 그룹과 같은 기능을 추가했습니다. 인터페이스: 로그 레벨에서 인테리어로 두 번 매핑을 변경했습니다. 실험 실행 GitHub 토론 LogValuer 2 개월과 약 300 개의 의견이 끝난 후, 우리는 실제로 준비가되어 있다고 느꼈습니다. 그리고 동행하는 제안 문제는 800개가 넘는 의견을 얻었으며 API와 구현에 많은 개선을 가져왔습니다. : 제안 디자인 DOC context.Context 원래 API는 컨텍스트에 로그인을 추가하는 것을 지원했습니다.많은 사람들은 이것이 코드 수준을 쉽게 통과하는 편리한 방법이라고 생각했습니다.그러나 다른 사람들은 코드를 이해하기 어려워 암시적인 의존성으로 밀수하고 있다고 생각했습니다. 우리는 또한 여러 가지 디자인을 시도하여 컨텍스트를 로깅 방법으로 전달하는 관련 질문과 싸웠습니다.We initially resisted the standard pattern of passing the context as the first argument because we didn't want every logging call to require a context, but ultimately created two sets of logging methods, one with a context and one without. 특성을 표현하는 키와 값 구문을 교체하는 한 가지 변화는 우리가 걱정하지 않았습니다.One change we did not concern the alternating key-and-value syntax for expressing attributes: slog.Info("message", "k1", v1, "k2", v2) 많은 사람들이 이것이 나쁜 생각이라고 강하게 느꼈다.그들은 열쇠 또는 값을 놓치면 읽기가 어렵고 잘못되기 쉽다고 생각했다.그들은 구조를 표현하기 위해 명시적인 특성을 선호했다. slog.Info("message", slog.Int("k1", v1), slog.String("k2", v2)) 그러나 우리는 가벼운 구문이 Go를 사용하기 쉽고 재미있게 유지하기 위해 특히 새로운 Go 프로그래머에게 중요하다고 생각했습니다. , 그리고 (그리고 그의 ) 성공적으로 대체 키와 값을 사용했습니다.We added a 일반적인 실수를 잡을 수 있지만 디자인을 변경하지 않았습니다. logr go-kit/log zap SugaredLogger 체크 아웃 2023년 3월 15일에 제안이 승인되었지만 여전히 몇 가지 작은 해결되지 않은 문제들이 남아있다.다음 몇 주 동안 10개의 추가적인 변경 사항이 제안되고 해결되었습니다. 패키지는 완료되었으며, 또한 컨트롤러를 검증하는 패키지와 교환 키와 값의 올바른 사용을위한 수의사 검사. log/slog testing/slogtest 그리고 8월 8일 Go 1.21이 출시되었으며, 우리는 당신이 그것을 유용하고, 그것을 구축하는 것처럼 사용하는 것이 재미 있기를 바랍니다. slog 그리고 토론과 제안 프로세스에 참여한 모든 사람들에게 큰 감사드립니다. 엄청나게 slog 자원 이 를 위한 패키지는 그것을 사용하는 방법을 설명하고 몇 가지 예를 제공합니다. 문서화 log/slog 이 Go 커뮤니티가 제공하는 추가 리소스가 있으며, 다양한 관리자를 포함합니다. 위키 페이지 만약 당신이 핸들러를 쓰고 싶다면, consult the . Handling Writing 가이드 Jonathan Amsterdam에 의해 사진: Jeff Smith on Unsplash 제프 스미스 Unsplash에 대하여 이 문서는 CC BY 4.0 DEED 라이선스 아래 The Go Blog에서 사용할 수 있습니다. Go 블로그 Go 블로그