From 6c38ddadb4de91ac14fd501e2dca54662a60f15a Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 10 Sep 2024 17:02:22 -0700 Subject: [PATCH] Use slog instead of logr --- CHANGELOG.md | 16 ++ LICENSES/github.com/go-logr/zapr/LICENSE | 201 ------------------ LICENSES/go.uber.org/multierr/LICENSE.txt | 19 -- LICENSES/go.uber.org/zap/LICENSE | 19 -- cli/main.go | 73 ++++--- go.mod | 9 +- go.sum | 10 +- instrumentation.go | 85 ++------ instrumentation_test.go | 37 ---- .../instrumentation/bpf/database/sql/probe.go | 6 +- .../segmentio/kafka-go/consumer/probe.go | 6 +- .../segmentio/kafka-go/producer/probe.go | 6 +- .../otel/traceglobal/probe.go | 6 +- .../google.golang.org/grpc/client/probe.go | 6 +- .../google.golang.org/grpc/server/probe.go | 6 +- .../bpf/net/http/client/probe.go | 6 +- .../bpf/net/http/server/probe.go | 6 +- internal/pkg/instrumentation/manager.go | 27 ++- .../pkg/instrumentation/manager_load_test.go | 9 +- internal/pkg/instrumentation/manager_test.go | 20 +- internal/pkg/instrumentation/probe/probe.go | 14 +- internal/pkg/opentelemetry/controller.go | 14 +- internal/pkg/opentelemetry/controller_test.go | 14 +- internal/pkg/process/allocate.go | 21 +- internal/pkg/process/analyze.go | 6 +- internal/pkg/process/discover.go | 19 +- internal/pkg/process/ptrace/ptrace_linux.go | 18 +- internal/pkg/process/ptrace/ptrace_other.go | 4 +- internal/tools/go.mod | 4 +- internal/tools/inspect/app.go | 12 +- internal/tools/inspect/builder.go | 18 +- internal/tools/inspect/cache.go | 12 +- internal/tools/inspect/cmd/offsetgen/main.go | 22 +- internal/tools/inspect/inspector.go | 14 +- internal/tools/inspect/render.go | 17 +- level.go | 68 ------ level_test.go | 98 --------- 37 files changed, 215 insertions(+), 733 deletions(-) delete mode 100644 LICENSES/github.com/go-logr/zapr/LICENSE delete mode 100644 LICENSES/go.uber.org/multierr/LICENSE.txt delete mode 100644 LICENSES/go.uber.org/zap/LICENSE delete mode 100644 level.go delete mode 100644 level_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 13023d774..39390f017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,16 +29,32 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http - Add gRPC status code attribute for client spans (`rpc.grpc.status_code`). ([#1044](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1044)) - Support `google.golang.org/grpc` `1.68.0-dev`. ([#1044](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1044)) - Support `go.opentelemetry.io/otel@v1.30.0`. ([#1044](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1044)) +- The `WithLogger` `InstrumentationOption` is added as a replacement for `WithLogLevel`. + An `slog.Logger` can now be configured by the user any way they want and then passed to the `Instrumentation` for its logging with this option. + By default, if this is not provided, the default `slog` `Logger` will be used. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) ### Changed - The `WithSampler` option function now accepts the new `Sampler` interface instead of `trace.Sampler`. ([#982](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/982)) +- The `WithEnv` `InstrumentationOption` no longer supports the `OTEL_LOG_LEVEL` environment variable. + This is now configured by the user via the logger they pass using the added `WithLogger` option. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) ### Fixed - Fix dirty shutdown caused by panic. ([#980](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/980)) - Flush pending span exports on shutdown. ([#1028](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1028)) +### Removed + +- `WithLogLevel` is removed. + Use `WithLogger` instead. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) +- The unused `LogLevelDebug` constant is removed. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) +- The unused `LogLevelInfo` constant is removed. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) +- The unused `LogLevelWarn` constant is removed. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) +- The unused `LogLevelError` constant is removed. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) +- The unused `LogLevel` type is removed. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) +- The unused `ParseLogLevel` function is removed. ([#1080](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/1080)) + ## [v0.14.0-alpha] - 2024-07-15 ### Added diff --git a/LICENSES/github.com/go-logr/zapr/LICENSE b/LICENSES/github.com/go-logr/zapr/LICENSE deleted file mode 100644 index 8dada3eda..000000000 --- a/LICENSES/github.com/go-logr/zapr/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/LICENSES/go.uber.org/multierr/LICENSE.txt b/LICENSES/go.uber.org/multierr/LICENSE.txt deleted file mode 100644 index 413e30f7c..000000000 --- a/LICENSES/go.uber.org/multierr/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2017-2021 Uber Technologies, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/LICENSES/go.uber.org/zap/LICENSE b/LICENSES/go.uber.org/zap/LICENSE deleted file mode 100644 index 6652bed45..000000000 --- a/LICENSES/go.uber.org/zap/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016-2017 Uber Technologies, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/cli/main.go b/cli/main.go index a460e34f6..136efdf6f 100644 --- a/cli/main.go +++ b/cli/main.go @@ -8,26 +8,28 @@ import ( "errors" "flag" "fmt" - "log" + "log/slog" "os" "os/signal" + "path/filepath" "syscall" - "github.com/go-logr/logr" - "github.com/go-logr/stdr" - "github.com/go-logr/zapr" - "go.uber.org/zap" - "go.opentelemetry.io/auto" "go.opentelemetry.io/auto/internal/pkg/process" ) -const help = ` -OpenTelemetry auto-instrumentation for Go applications using eBPF +const help = `Usage of %s: + -global-impl + Record telemetry from the OpenTelemetry default global implementation + -log-level string + logging level ("debug", "info", "warn", "error") + +Runs the OpenTelemetry auto-instrumentation for Go applications using eBPF. Environment variable configuration: - OTEL_GO_AUTO_TARGET_EXE: sets the target binary + - OTEL_LOG_LEVEL: sets the log level (flag takes precedence) - OTEL_SERVICE_NAME (or OTEL_RESOURCE_ATTRIBUTES): sets the service name - OTEL_TRACES_EXPORTER: sets the trace exporter @@ -37,19 +39,34 @@ package's documentation for information on supported values and registration of custom exporters. ` +// envLogLevelKey is the key for the environment variable value containing the +// log level. +const envLogLevelKey = "OTEL_LOG_LEVEL" + func usage() { - fmt.Fprintf(os.Stderr, "%s", help) + program := filepath.Base(os.Args[0]) + fmt.Fprintf(os.Stderr, help, program) } -func newLogger() logr.Logger { - zapLog, err := zap.NewProduction() +func newLogger(lvlStr string) *slog.Logger { + levelVar := new(slog.LevelVar) // Default value of info. + opts := &slog.HandlerOptions{AddSource: true, Level: levelVar} + h := slog.NewJSONHandler(os.Stderr, opts) + logger := slog.New(h) - var logger logr.Logger - if err != nil { - // Fallback to stdr logger. - logger = stdr.New(log.New(os.Stderr, "", log.LstdFlags)) + if lvlStr == "" { + lvlStr = os.Getenv(envLogLevelKey) + } + + if lvlStr == "" { + return logger + } + + var level slog.Level + if err := level.UnmarshalText([]byte(lvlStr)); err != nil { + logger.Error("failed to parse log level", "error", err, "log-level", lvlStr) } else { - logger = zapr.NewLogger(zapLog) + levelVar.Set(level) } return logger @@ -60,12 +77,12 @@ func main() { var logLevel string flag.BoolVar(&globalImpl, "global-impl", false, "Record telemetry from the OpenTelemetry default global implementation") - flag.StringVar(&logLevel, "log-level", "", "Define log visibility level, default is `info`") + flag.StringVar(&logLevel, "log-level", "", `logging level ("debug", "info", "warn", "error")`) flag.Usage = usage flag.Parse() - logger := newLogger().WithName("go.opentelemetry.io/auto") + logger := newLogger(logLevel) // Trap Ctrl+C and SIGTERM and call cancel on the context. ctx, cancel := context.WithCancel(context.Background()) @@ -90,24 +107,18 @@ func main() { ) loadedIndicator := make(chan struct{}) - instOptions := []auto.InstrumentationOption{auto.WithEnv(), auto.WithLoadedIndicator(loadedIndicator)} + instOptions := []auto.InstrumentationOption{ + auto.WithEnv(), + auto.WithLoadedIndicator(loadedIndicator), + auto.WithLogger(logger), + } if globalImpl { instOptions = append(instOptions, auto.WithGlobal()) } - if logLevel != "" { - level, err := auto.ParseLogLevel(logLevel) - if err != nil { - logger.Error(err, "failed to parse log level") - return - } - - instOptions = append(instOptions, auto.WithLogLevel(level)) - } - inst, err := auto.NewInstrumentation(ctx, instOptions...) if err != nil { - logger.Error(err, "failed to create instrumentation") + logger.Error("failed to create instrumentation", "error", err) return } @@ -122,6 +133,6 @@ func main() { logger.Info("starting instrumentation...") if err = inst.Run(ctx); err != nil && !errors.Is(err, process.ErrInterrupted) { - logger.Error(err, "instrumentation crashed") + logger.Error("instrumentation crashed", "error", err) } } diff --git a/go.mod b/go.mod index 50343f1bc..af1adbcbc 100644 --- a/go.mod +++ b/go.mod @@ -21,9 +21,6 @@ retract ( require ( github.com/cilium/ebpf v0.16.0 - github.com/go-logr/logr v1.4.2 - github.com/go-logr/stdr v1.2.2 - github.com/go-logr/zapr v1.3.0 github.com/hashicorp/go-version v1.7.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.9.0 @@ -32,7 +29,6 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 go.opentelemetry.io/otel/sdk v1.29.0 go.opentelemetry.io/otel/trace v1.29.0 - go.uber.org/zap v1.27.0 golang.org/x/arch v0.10.0 golang.org/x/sys v0.25.0 gopkg.in/yaml.v3 v3.0.1 @@ -43,6 +39,8 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/klauspost/compress v1.17.9 // indirect @@ -67,8 +65,7 @@ require ( go.opentelemetry.io/otel/sdk/log v0.5.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/text v0.17.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect diff --git a/go.sum b/go.sum index bf3b23bdb..ad85a198b 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,6 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -101,14 +99,10 @@ go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeX go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= diff --git a/instrumentation.go b/instrumentation.go index 90f3ef9d1..259dace22 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -8,7 +8,7 @@ import ( "debug/buildinfo" "errors" "fmt" - "log" + "log/slog" "os" "path/filepath" "runtime" @@ -16,11 +16,6 @@ import ( "strings" "sync" - "github.com/go-logr/logr" - "github.com/go-logr/stdr" - "github.com/go-logr/zapr" - "go.uber.org/zap" - "go.opentelemetry.io/contrib/exporters/autoexport" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" @@ -48,8 +43,6 @@ const ( // envOtelGlobalImplKey is the key for the environment variable value enabling to opt-in for the // OpenTelemetry global implementation. It should be a boolean value. envOtelGlobalImplKey = "OTEL_GO_AUTO_GLOBAL" - // envLogLevelKey is the key for the environment variable value containing the log level. - envLogLevelKey = "OTEL_LOG_LEVEL" ) // Instrumentation manages and controls all OpenTelemetry Go @@ -68,33 +61,6 @@ type Instrumentation struct { // binary or pid. var errUndefinedTarget = fmt.Errorf("undefined target Go binary, consider setting the %s environment variable pointing to the target binary to instrument", envTargetExeKey) -func newLogger(logLevel LogLevel) logr.Logger { - level, logErr := zap.ParseAtomicLevel(logLevel.String()) - if logErr != nil { - level, _ = zap.ParseAtomicLevel(LogLevelInfo.String()) - } - - c := zap.NewProductionConfig() - - c.Level.SetLevel(level.Level()) - - zapLog, err := c.Build() - - var logger logr.Logger - if err != nil { - // Fallback to stdr logger. - logger = stdr.New(log.New(os.Stderr, "", log.LstdFlags)) - } else { - logger = zapr.NewLogger(zapLog) - } - - if logErr != nil { - logger.Error(logErr, "invalid log level; using LevelInfo instead", zap.Error(logErr), zap.String("input", logLevel.String())) - } - - return logger -} - // NewInstrumentation returns a new [Instrumentation] configured with the // provided opts. // @@ -109,12 +75,7 @@ func NewInstrumentation(ctx context.Context, opts ...InstrumentationOption) (*In return nil, err } - // We likely want to use slog instead of logr in the longterm. Wait until - // that package has enough Go version support - logger := newLogger(c.logLevel) - logger = logger.WithName("Instrumentation") - - pa := process.NewAnalyzer(logger) + pa := process.NewAnalyzer(c.logger) pid, err := pa.DiscoverProcessID(ctx, &c.target) if err != nil { return nil, err @@ -125,13 +86,13 @@ func NewInstrumentation(ctx context.Context, opts ...InstrumentationOption) (*In return nil, err } - ctrl, err := opentelemetry.NewController(logger, c.tracerProvider(pa.BuildInfo), Version()) + ctrl, err := opentelemetry.NewController(c.logger, c.tracerProvider(pa.BuildInfo), Version()) if err != nil { return nil, err } cp := convertConfigProvider(c.cp) - mngr, err := instrumentation.NewManager(logger, ctrl, c.globalImpl, c.loadIndicator, cp) + mngr, err := instrumentation.NewManager(c.logger, ctrl, c.globalImpl, c.loadIndicator, cp) if err != nil { return nil, err } @@ -141,13 +102,13 @@ func NewInstrumentation(ctx context.Context, opts ...InstrumentationOption) (*In return nil, err } - allocDetails, err := process.Allocate(logger, pid) + allocDetails, err := process.Allocate(c.logger, pid) if err != nil { return nil, err } td.AllocationDetails = allocDetails - logger.Info( + c.logger.Info( "target process analysis completed", "pid", td.PID, "go_version", td.GoVersion, @@ -220,7 +181,7 @@ type instConfig struct { additionalResAttrs []attribute.KeyValue globalImpl bool loadIndicator chan struct{} - logLevel LogLevel + logger *slog.Logger sampler Sampler cp ConfigProvider } @@ -253,8 +214,8 @@ func newInstConfig(ctx context.Context, opts []InstrumentationOption) (instConfi c.sampler = DefaultSampler() } - if c.logLevel == logLevelUndefined { - c.logLevel = LogLevelInfo + if c.logger == nil { + c.logger = slog.Default() } if c.cp == nil { @@ -402,12 +363,11 @@ var lookupEnv = os.LookupEnv // - OTEL_SERVICE_NAME (or OTEL_RESOURCE_ATTRIBUTES): sets the service name // - OTEL_TRACES_EXPORTER: sets the trace exporter // - OTEL_GO_AUTO_GLOBAL: enables the OpenTelemetry global implementation -// - OTEL_LOG_LEVEL: sets the log level // - OTEL_TRACES_SAMPLER: sets the trace sampler // - OTEL_TRACES_SAMPLER_ARG: optionally sets the trace sampler argument // // This option may conflict with [WithTarget], [WithPID], [WithTraceExporter], -// [WithServiceName], [WithGlobal], [WithLogLevel] and [WithSampler] if their respective environment variable is defined. +// [WithServiceName], [WithGlobal], and [WithSampler] if their respective environment variable is defined. // If more than one of these options are used, the last one provided to an // [Instrumentation] will be used. // @@ -441,16 +401,6 @@ func WithEnv() InstrumentationOption { c.globalImpl = boolVal } } - if l, ok := lookupEnv(envLogLevelKey); ok { - var e error - level, e := ParseLogLevel(l) - - if e == nil { - c.logLevel = level - } - - err = errors.Join(err, e) - } if s, e := newSamplerFromEnv(lookupEnv); e != nil { err = errors.Join(err, e) } else { @@ -564,16 +514,11 @@ func WithLoadedIndicator(indicator chan struct{}) InstrumentationOption { }) } -// WithLogLevel returns an [InstrumentationOption] that will configure -// an [Instrumentation] to use the provided logging level. -func WithLogLevel(level LogLevel) InstrumentationOption { - return fnOpt(func(ctx context.Context, c instConfig) (instConfig, error) { - if err := level.validate(); err != nil { - return c, err - } - - c.logLevel = level - +// WithLogger returns an [InstrumentationOption] that will configure an +// [Instrumentation] to use the provided logger. +func WithLogger(logger *slog.Logger) InstrumentationOption { + return fnOpt(func(_ context.Context, c instConfig) (instConfig, error) { + c.logger = logger return c, nil }) } diff --git a/instrumentation_test.go b/instrumentation_test.go index ce9845544..666495ed6 100644 --- a/instrumentation_test.go +++ b/instrumentation_test.go @@ -73,21 +73,6 @@ func TestWithEnv(t *testing.T) { require.NoError(t, err) assert.Equal(t, name, c.serviceName) }) - - t.Run("OTEL_LOG_LEVEL", func(t *testing.T) { - const name = "debug" - mockEnv(t, map[string]string{"OTEL_LOG_LEVEL": name}) - - c, err := newInstConfig(context.Background(), []InstrumentationOption{WithEnv()}) - require.NoError(t, err) - assert.Equal(t, LogLevelDebug, c.logLevel) - - const wrong = "invalid" - - mockEnv(t, map[string]string{"OTEL_LOG_LEVEL": wrong}) - _, err = newInstConfig(context.Background(), []InstrumentationOption{WithEnv()}) - require.Error(t, err) - }) } func TestOptionPrecedence(t *testing.T) { @@ -178,28 +163,6 @@ func TestWithResourceAttributes(t *testing.T) { }) } -func TestWithLogLevel(t *testing.T) { - t.Run("With Valid Input", func(t *testing.T) { - c, err := newInstConfig(context.Background(), []InstrumentationOption{WithLogLevel("error")}) - - require.NoError(t, err) - - assert.Equal(t, LogLevelError, c.logLevel) - - c, err = newInstConfig(context.Background(), []InstrumentationOption{WithLogLevel(LogLevelInfo)}) - - require.NoError(t, err) - - assert.Equal(t, LogLevelInfo, c.logLevel) - }) - - t.Run("Will Validate Input", func(t *testing.T) { - _, err := newInstConfig(context.Background(), []InstrumentationOption{WithLogLevel("invalid")}) - - require.Error(t, err) - }) -} - func TestWithSampler(t *testing.T) { t.Run("Default sampler", func(t *testing.T) { c, err := newInstConfig(context.Background(), []InstrumentationOption{}) diff --git a/internal/pkg/instrumentation/bpf/database/sql/probe.go b/internal/pkg/instrumentation/bpf/database/sql/probe.go index 03a45f9b5..2fb0c2f47 100644 --- a/internal/pkg/instrumentation/bpf/database/sql/probe.go +++ b/internal/pkg/instrumentation/bpf/database/sql/probe.go @@ -4,10 +4,10 @@ package sql import ( + "log/slog" "os" "strconv" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" "go.opentelemetry.io/otel/trace" @@ -28,14 +28,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindClient, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go index 980e7509b..19ceb298c 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer/probe.go @@ -5,9 +5,9 @@ package consumer import ( "fmt" + "log/slog" "strconv" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" "go.opentelemetry.io/otel/trace" @@ -26,14 +26,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindConsumer, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go index 863eed88a..fbf393d0d 100644 --- a/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go +++ b/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer/probe.go @@ -5,8 +5,8 @@ package producer import ( "fmt" + "log/slog" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" "go.opentelemetry.io/otel/trace" @@ -25,14 +25,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindProducer, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go index 4bbed87bc..7fb79b939 100644 --- a/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go +++ b/internal/pkg/instrumentation/bpf/go.opentelemetry.io/otel/traceglobal/probe.go @@ -6,6 +6,7 @@ package global import ( "encoding/binary" "fmt" + "log/slog" "math" "go.opentelemetry.io/auto/internal/pkg/inject" @@ -13,7 +14,6 @@ import ( "go.opentelemetry.io/auto/internal/pkg/process" "go.opentelemetry.io/auto/internal/pkg/structfield" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "golang.org/x/sys/unix" @@ -32,14 +32,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindClient, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go index 366426dbb..bb2636b5c 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/client/probe.go @@ -5,11 +5,11 @@ package grpc import ( "fmt" + "log/slog" "strconv" "strings" "github.com/cilium/ebpf" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" @@ -30,14 +30,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindClient, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go index 9264d125d..e79852dc0 100644 --- a/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go +++ b/internal/pkg/instrumentation/bpf/google.golang.org/grpc/server/probe.go @@ -5,8 +5,8 @@ package server import ( "fmt" + "log/slog" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" @@ -28,14 +28,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindServer, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/net/http/client/probe.go b/internal/pkg/instrumentation/bpf/net/http/client/probe.go index f7eb679e7..16476b00c 100644 --- a/internal/pkg/instrumentation/bpf/net/http/client/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/client/probe.go @@ -5,12 +5,12 @@ package client import ( "fmt" + "log/slog" "net/url" "os" "strings" "github.com/cilium/ebpf" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" @@ -33,7 +33,7 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindClient, InstrumentedPkg: pkg, @@ -64,7 +64,7 @@ func New(logger logr.Logger) probe.Probe { return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.AllocationConst{}, diff --git a/internal/pkg/instrumentation/bpf/net/http/server/probe.go b/internal/pkg/instrumentation/bpf/net/http/server/probe.go index 3996aa770..6e6cc49d3 100644 --- a/internal/pkg/instrumentation/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentation/bpf/net/http/server/probe.go @@ -4,9 +4,9 @@ package server import ( + "log/slog" "strings" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -30,14 +30,14 @@ const ( ) // New returns a new [probe.Probe]. -func New(logger logr.Logger) probe.Probe { +func New(logger *slog.Logger) probe.Probe { id := probe.ID{ SpanKind: trace.SpanKindServer, InstrumentedPkg: pkg, } return &probe.Base[bpfObjects, event]{ ID: id, - Logger: logger.WithName(id.String()), + Logger: logger, Consts: []probe.Const{ probe.RegistersABIConst{}, probe.StructFieldConst{ diff --git a/internal/pkg/instrumentation/manager.go b/internal/pkg/instrumentation/manager.go index 49cdd680e..94f8c3128 100644 --- a/internal/pkg/instrumentation/manager.go +++ b/internal/pkg/instrumentation/manager.go @@ -7,11 +7,11 @@ import ( "context" "errors" "fmt" + "log/slog" "sync" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/rlimit" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/trace" @@ -46,7 +46,7 @@ const ( // Manager handles the management of [probe.Probe] instances. type Manager struct { - logger logr.Logger + logger *slog.Logger probes map[probe.ID]probe.Probe otelController *opentelemetry.Controller globalImpl bool @@ -62,8 +62,7 @@ type Manager struct { } // NewManager returns a new [Manager]. -func NewManager(logger logr.Logger, otelController *opentelemetry.Controller, globalImpl bool, loadIndicator chan struct{}, cp ConfigProvider) (*Manager, error) { - logger = logger.WithName("Manager") +func NewManager(logger *slog.Logger, otelController *opentelemetry.Controller, globalImpl bool, loadIndicator chan struct{}, cp ConfigProvider) (*Manager, error) { m := &Manager{ logger: logger, probes: make(map[probe.ID]probe.Probe), @@ -146,7 +145,7 @@ func (m *Manager) FilterUnusedProbes(target *process.TargetDetails) { } if !funcsFound { - m.logger.V(1).Info("no functions found for probe, removing", "name", name) + m.logger.Debug("no functions found for probe, removing", "name", name) delete(m.probes, name) } } @@ -240,7 +239,7 @@ func (m *Manager) ConfigLoop(ctx context.Context) { } err := m.applyConfig(c) if err != nil { - m.logger.Error(err, "Failed to apply config") + m.logger.Error("Failed to apply config", "error", err) continue } m.currentConfig = c @@ -282,7 +281,7 @@ func (m *Manager) Run(ctx context.Context, target *process.TargetDetails) error case <-ctx.Done(): m.probeMu.Lock() - m.logger.V(1).Info("Shutting down all probes") + m.logger.Debug("Shutting down all probes") err := m.cleanup(target) // Wait for all probes to stop before closing the chan they send on. @@ -321,24 +320,24 @@ func (m *Manager) load(target *process.TargetDetails) error { // Load probes for name, i := range m.probes { if isProbeEnabled(name, m.currentConfig) { - m.logger.V(0).Info("loading probe", "name", name) + m.logger.Info("loading probe", "name", name) err := i.Load(exe, target, m.currentConfig.SamplingConfig) if err != nil { - m.logger.Error(err, "error while loading probes, cleaning up", "name", name) + m.logger.Error("error while loading probes, cleaning up", "error", err, "name", name) return errors.Join(err, m.cleanup(target)) } } } - m.logger.V(1).Info("loaded probes to memory", "total_probes", len(m.probes)) + m.logger.Debug("loaded probes to memory", "total_probes", len(m.probes)) return nil } func (m *Manager) mount(target *process.TargetDetails) error { if target.AllocationDetails != nil { - m.logger.V(1).Info("Mounting bpffs", "allocations_details", target.AllocationDetails) + m.logger.Debug("Mounting bpffs", "allocations_details", target.AllocationDetails) } else { - m.logger.V(1).Info("Mounting bpffs") + m.logger.Debug("Mounting bpffs") } return bpffsMount(target) } @@ -356,12 +355,12 @@ func (m *Manager) cleanup(target *process.TargetDetails) error { err = errors.Join(err, m.otelController.Shutdown(ctx)) } - m.logger.V(1).Info("Cleaning bpffs") + m.logger.Debug("Cleaning bpffs") return errors.Join(err, bpffsCleanup(target)) } //nolint:revive // ignoring linter complaint about control flag -func availableProbes(l logr.Logger, withTraceGlobal bool) []probe.Probe { +func availableProbes(l *slog.Logger, withTraceGlobal bool) []probe.Probe { insts := []probe.Probe{ grpcClient.New(l), grpcServer.New(l), diff --git a/internal/pkg/instrumentation/manager_load_test.go b/internal/pkg/instrumentation/manager_load_test.go index 0bc59be49..192f66672 100644 --- a/internal/pkg/instrumentation/manager_load_test.go +++ b/internal/pkg/instrumentation/manager_load_test.go @@ -6,11 +6,9 @@ package instrumentation import ( - "log" - "os" + "log/slog" "testing" - "github.com/go-logr/stdr" "github.com/hashicorp/go-version" "github.com/stretchr/testify/assert" "go.opentelemetry.io/auto/internal/pkg/inject" @@ -46,10 +44,7 @@ func TestLoadProbes(t *testing.T) { } func fakeManager(t *testing.T) *Manager { - logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) - logger = logger.WithName("Instrumentation") - - m, err := NewManager(logger, nil, true, nil, NewNoopConfigProvider(nil)) + m, err := NewManager(slog.Default(), nil, true, nil, NewNoopConfigProvider(nil)) assert.NoError(t, err) assert.NotNil(t, m) diff --git a/internal/pkg/instrumentation/manager_test.go b/internal/pkg/instrumentation/manager_test.go index c6223531c..1bbb0a72e 100644 --- a/internal/pkg/instrumentation/manager_test.go +++ b/internal/pkg/instrumentation/manager_test.go @@ -7,13 +7,11 @@ package instrumentation import ( "context" - "log" - "os" + "log/slog" "testing" "time" "github.com/cilium/ebpf/link" - "github.com/go-logr/stdr" "github.com/hashicorp/go-version" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -187,10 +185,7 @@ func TestDependencyChecks(t *testing.T) { } func fakeManager(t *testing.T) *Manager { - logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) - logger = logger.WithName("Instrumentation") - - m, err := NewManager(logger, nil, true, nil, NewNoopConfigProvider(nil)) + m, err := NewManager(slog.Default(), nil, true, nil, NewNoopConfigProvider(nil)) assert.NoError(t, err) assert.NotNil(t, m) @@ -230,16 +225,13 @@ func TestRunStopping(t *testing.T) { probeStop := make(chan struct{}) p := newSlowProbe(probeStop) - logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) - logger = logger.WithName("Instrumentation") - tp := new(shutdownTracerProvider) - ctrl, err := opentelemetry.NewController(logger, tp, "") + ctrl, err := opentelemetry.NewController(slog.Default(), tp, "") require.NoError(t, err) m := &Manager{ otelController: ctrl, - logger: logger.WithName("Manager"), + logger: slog.Default(), probes: map[probe.ID]probe.Probe{{}: p}, eventCh: make(chan *probe.Event), cp: NewNoopConfigProvider(nil), @@ -359,8 +351,6 @@ func (p *dummyProvider) sendConfig(c Config) { } func TestConfigProvider(t *testing.T) { - logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) - logger = logger.WithName("Instrumentation") loadedIndicator := make(chan struct{}) netHTTPClientProbeID := probe.ID{InstrumentedPkg: "net/http", SpanKind: trace.SpanKindClient} @@ -372,7 +362,7 @@ func TestConfigProvider(t *testing.T) { falseVal := false m := &Manager{ - logger: logger.WithName("Manager"), + logger: slog.Default(), probes: map[probe.ID]probe.Probe{ netHTTPClientProbeID: &noopProbe{}, netHTTPServerProbeID: &noopProbe{}, diff --git a/internal/pkg/instrumentation/probe/probe.go b/internal/pkg/instrumentation/probe/probe.go index c4d2b6ed7..08117b2de 100644 --- a/internal/pkg/instrumentation/probe/probe.go +++ b/internal/pkg/instrumentation/probe/probe.go @@ -10,12 +10,12 @@ import ( "errors" "fmt" "io" + "log/slog" "os" "github.com/cilium/ebpf" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/perf" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "go.opentelemetry.io/auto/internal/pkg/inject" @@ -55,7 +55,7 @@ type Base[BPFObj any, BPFEvent any] struct { // ID is a unique identifier for the probe. ID ID // Logger is used to log operations and errors. - Logger logr.Logger + Logger *slog.Logger // Consts are the constants that need to be injected into the eBPF program // that is run by this Probe. @@ -149,7 +149,7 @@ func (i *Base[BPFObj, BPFEvent]) loadUprobes(exec *link.Executable, td *process. links, err := up.load(exec, td, i.collection) if err != nil { if up.Optional { - i.Logger.V(1).Info("failed to attach optional uprobe", "probe", i.ID, "symbol", up.Sym, "error", err) + i.Logger.Debug("failed to attach optional uprobe", "probe", i.ID, "symbol", up.Sym, "error", err) continue } return err @@ -202,18 +202,18 @@ func (i *Base[BPFObj, BPFEvent]) Run(dest chan<- *Event) { if errors.Is(err, perf.ErrClosed) { return } - i.Logger.Error(err, "error reading from perf reader") + i.Logger.Error("error reading from perf reader", "error", err) continue } if record.LostSamples != 0 { - i.Logger.V(1).Info("perf event ring buffer full", "dropped", record.LostSamples) + i.Logger.Debug("perf event ring buffer full", "dropped", record.LostSamples) continue } se, err := i.processRecord(record) if err != nil { - i.Logger.Error(err, "failed to process perf record") + i.Logger.Error("failed to process perf record", "error", err) } e := &Event{ Package: i.ID.InstrumentedPkg, @@ -246,7 +246,7 @@ func (i *Base[BPFObj, BPFEvent]) Close() error { err = errors.Join(err, c.Close()) } if err == nil { - i.Logger.V(1).Info("Closed", "Probe", i.ID) + i.Logger.Debug("Closed", "Probe", i.ID) } return err } diff --git a/internal/pkg/opentelemetry/controller.go b/internal/pkg/opentelemetry/controller.go index eba78c6e4..266a6f2d0 100644 --- a/internal/pkg/opentelemetry/controller.go +++ b/internal/pkg/opentelemetry/controller.go @@ -5,9 +5,9 @@ package opentelemetry import ( "context" + "log/slog" "time" - "github.com/go-logr/logr" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/auto/internal/pkg/instrumentation/probe" @@ -16,7 +16,7 @@ import ( // Controller handles OpenTelemetry telemetry generation for events. type Controller struct { - logger logr.Logger + logger *slog.Logger version string tracerProvider trace.TracerProvider tracersMap map[tracerID]trace.Tracer @@ -56,11 +56,11 @@ func (c *Controller) getTracer(pkg, tracerName, version, schema string) trace.Tr // Trace creates a trace span for event. func (c *Controller) Trace(event *probe.Event) { for _, se := range event.SpanEvents { - c.logger.V(1).Info("got event", "kind", event.Kind.String(), "pkg", event.Package, "attrs", se.Attributes, "traceID", se.SpanContext.TraceID().String(), "spanID", se.SpanContext.SpanID().String()) + c.logger.Debug("got event", "kind", event.Kind.String(), "pkg", event.Package, "attrs", se.Attributes, "traceID", se.SpanContext.TraceID().String(), "spanID", se.SpanContext.SpanID().String()) ctx := context.Background() if se.SpanContext == nil { - c.logger.V(1).Info("got event without context - dropping") + c.logger.Debug("got event without context - dropping") return } @@ -70,7 +70,7 @@ func (c *Controller) Trace(event *probe.Event) { } ctx = ContextWithEBPFEvent(ctx, *se) - c.logger.V(1).Info("getting tracer", "name", se.TracerName, "version", se.TracerVersion, "schema", se.TracerSchema) + c.logger.Debug("getting tracer", "name", se.TracerName, "version", se.TracerVersion, "schema", se.TracerSchema) _, span := c.getTracer(event.Package, se.TracerName, se.TracerVersion, se.TracerSchema). Start(ctx, se.SpanName, trace.WithAttributes(se.Attributes...), @@ -86,9 +86,7 @@ func (c *Controller) convertTime(t int64) time.Time { } // NewController returns a new initialized [Controller]. -func NewController(logger logr.Logger, tracerProvider trace.TracerProvider, ver string) (*Controller, error) { - logger = logger.WithName("Controller") - +func NewController(logger *slog.Logger, tracerProvider trace.TracerProvider, ver string) (*Controller, error) { bt, err := utils.EstimateBootTimeOffset() if err != nil { return nil, err diff --git a/internal/pkg/opentelemetry/controller_test.go b/internal/pkg/opentelemetry/controller_test.go index 3c67c22bb..95899131c 100644 --- a/internal/pkg/opentelemetry/controller_test.go +++ b/internal/pkg/opentelemetry/controller_test.go @@ -6,8 +6,7 @@ package opentelemetry import ( "context" "fmt" - "log" - "os" + "log/slog" "runtime" "strconv" "strings" @@ -15,8 +14,6 @@ import ( "testing" "time" - "github.com/go-logr/logr/testr" - "github.com/go-logr/stdr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -62,7 +59,6 @@ func instResource() *resource.Resource { func TestTrace(t *testing.T) { startTime := time.Now() endTime := startTime.Add(1 * time.Second) - logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) exporter := tracetest.NewInMemoryExporter() tp := sdktrace.NewTracerProvider( @@ -75,7 +71,7 @@ func TestTrace(t *testing.T) { assert.NoError(t, err) }() - ctrl, err := NewController(logger, tp, "test") + ctrl, err := NewController(slog.Default(), tp, "test") assert.NoError(t, err) convertedStartTime := ctrl.convertTime(startTime.Unix()) @@ -297,8 +293,6 @@ func TestTrace(t *testing.T) { } func TestGetTracer(t *testing.T) { - logger := stdr.New(log.New(os.Stderr, "", log.LstdFlags)) - exporter := tracetest.NewInMemoryExporter() tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), @@ -310,7 +304,7 @@ func TestGetTracer(t *testing.T) { assert.NoError(t, err) }() - ctrl, err := NewController(logger, tp, "test") + ctrl, err := NewController(slog.Default(), tp, "test") assert.NoError(t, err) t1 := ctrl.getTracer("foo/bar", "test", "v1", "schema") @@ -361,7 +355,7 @@ func TestShutdown(t *testing.T) { tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(batcher)) - ctrl, err := NewController(testr.New(t), tp, "test") + ctrl, err := NewController(slog.Default(), tp, "test") require.NoError(t, err) ctx := context.Background() diff --git a/internal/pkg/process/allocate.go b/internal/pkg/process/allocate.go index 0a8c0afb8..3da48aaaf 100644 --- a/internal/pkg/process/allocate.go +++ b/internal/pkg/process/allocate.go @@ -5,12 +5,11 @@ package process import ( "fmt" + "log/slog" "math" "os" "runtime" - "github.com/go-logr/logr" - "go.opentelemetry.io/auto/internal/pkg/instrumentation/utils" "go.opentelemetry.io/auto/internal/pkg/process/ptrace" ) @@ -23,9 +22,7 @@ type AllocationDetails struct { } // Allocate allocates memory for the instrumented process. -func Allocate(logger logr.Logger, pid int) (*AllocationDetails, error) { - logger = logger.WithName("Allocate") - +func Allocate(logger *slog.Logger, pid int) (*AllocationDetails, error) { // runtime.NumCPU doesn't query any kind of hardware or OS state, // but merely uses affinity APIs to count what CPUs the given go process is available to run on. // Go's implementation of runtime.NumCPU (https://github.com/golang/go/blob/48d899dcdbed4534ed942f7ec2917cf86b18af22/src/runtime/os_linux.go#L97) @@ -37,7 +34,7 @@ func Allocate(logger logr.Logger, pid int) (*AllocationDetails, error) { } mapSize := uint64(os.Getpagesize() * nCPU * 8) - logger.V(1).Info( + logger.Debug( "Requesting memory allocation", "size", mapSize, "page size", os.Getpagesize(), @@ -48,7 +45,7 @@ func Allocate(logger logr.Logger, pid int) (*AllocationDetails, error) { return nil, err } - logger.V(1).Info( + logger.Debug( "mmaped remote memory", "start_addr", fmt.Sprintf("0x%x", addr), "end_addr", fmt.Sprintf("0x%x", addr+mapSize), @@ -61,7 +58,7 @@ func Allocate(logger logr.Logger, pid int) (*AllocationDetails, error) { }, nil } -func remoteAllocate(logger logr.Logger, pid int, mapSize uint64) (uint64, error) { +func remoteAllocate(logger *slog.Logger, pid int, mapSize uint64) (uint64, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() program, err := ptrace.NewTracedProgram(pid, logger) @@ -70,17 +67,17 @@ func remoteAllocate(logger logr.Logger, pid int, mapSize uint64) (uint64, error) } defer func() { - logger.V(0).Info("Detaching from process", "pid", pid) + logger.Info("Detaching from process", "pid", pid) err := program.Detach() if err != nil { - logger.Error(err, "Failed to detach ptrace", "pid", pid) + logger.Error("Failed to detach ptrace", "error", err, "pid", pid) } }() if err := program.SetMemLockInfinity(); err != nil { - logger.Error(err, "Failed to set memlock on process") + logger.Error("Failed to set memlock on process", "error", err) } else { - logger.V(1).Info("Set memlock on process successfully") + logger.Debug("Set memlock on process successfully") } fd := -1 diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index acf7062a2..94446920a 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -80,7 +80,7 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ for _, dep := range a.BuildInfo.Deps { depVersion, err := version.NewVersion(dep.Version) if err != nil { - a.logger.Error(err, "parsing dependency version", "dependency", dep) + a.logger.Error("parsing dependency version", "error", err, "dependency", dep) continue } result.Libraries[dep.Path] = depVersion @@ -92,7 +92,7 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ return nil, err } for _, fn := range funcs { - a.logger.V(1).Info("found function", "function_name", fn) + a.logger.Debug("found function", "function_name", fn) } result.Functions = funcs @@ -134,7 +134,7 @@ func (a *Analyzer) findFunctions(elfF *elf.File, relevantFuncs map[string]interf result, err := binary.FindFunctionsUnStripped(elfF, relevantFuncs) if err != nil { if errors.Is(err, elf.ErrNoSymbols) { - a.logger.V(1).Info("No symbols found in binary, trying to find functions using .gosymtab") + a.logger.Debug("No symbols found in binary, trying to find functions using .gosymtab") return binary.FindFunctionsStripped(elfF, relevantFuncs) } return nil, err diff --git a/internal/pkg/process/discover.go b/internal/pkg/process/discover.go index fb7fee49d..348b75582 100644 --- a/internal/pkg/process/discover.go +++ b/internal/pkg/process/discover.go @@ -8,13 +8,12 @@ import ( "debug/buildinfo" "errors" "io" + "log/slog" "os" "path" "strconv" "strings" "time" - - "github.com/go-logr/logr" ) var ( @@ -29,15 +28,13 @@ var ( // Analyzer is used to find actively running processes. type Analyzer struct { - logger logr.Logger + logger *slog.Logger BuildInfo *buildinfo.BuildInfo } // NewAnalyzer returns a new [ProcessAnalyzer]. -func NewAnalyzer(logger logr.Logger) *Analyzer { - return &Analyzer{ - logger: logger.WithName("Analyzer"), - } +func NewAnalyzer(logger *slog.Logger) *Analyzer { + return &Analyzer{logger: logger} } // DiscoverProcessID searches for the target as an actively running process, @@ -59,18 +56,18 @@ func (a *Analyzer) DiscoverProcessID(ctx context.Context, target *TargetArgs) (i for { select { case <-ctx.Done(): - a.logger.V(1).Info("stopping process id discovery due to kill signal") + a.logger.Debug("stopping process id discovery due to kill signal") return 0, ErrInterrupted case <-t.C: pid, err := a.findProcessID(target, proc) if err == nil { - a.logger.V(0).Info("found process", "pid", pid) + a.logger.Info("found process", "pid", pid) return pid, nil } if err == ErrProcessNotFound { - a.logger.V(1).Info("process not found yet, trying again soon", "exe_path", target.ExePath) + a.logger.Debug("process not found yet, trying again soon", "exe_path", target.ExePath) } else { - a.logger.Error(err, "error while searching for process", "exe_path", target.ExePath) + a.logger.Error("error while searching for process", "error", err, "exe_path", target.ExePath) } // Reset the file offset for next iteration diff --git a/internal/pkg/process/ptrace/ptrace_linux.go b/internal/pkg/process/ptrace/ptrace_linux.go index 51c6ac4be..b50c52ea5 100644 --- a/internal/pkg/process/ptrace/ptrace_linux.go +++ b/internal/pkg/process/ptrace/ptrace_linux.go @@ -5,6 +5,7 @@ package ptrace import ( "fmt" + "log/slog" "os" "strconv" "strings" @@ -12,7 +13,6 @@ import ( "golang.org/x/sys/unix" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "github.com/pkg/errors" @@ -38,7 +38,7 @@ type TracedProgram struct { backupRegs *syscall.PtraceRegs backupCode []byte - logger logr.Logger + logger *slog.Logger } // Pid return the pid of traced program. @@ -59,9 +59,7 @@ func waitPid(pid int) error { } // NewTracedProgram ptrace all threads of a process. -func NewTracedProgram(pid int, logger logr.Logger) (*TracedProgram, error) { - logger = logger.WithName("TracedProgram") - +func NewTracedProgram(pid int, logger *slog.Logger) (*TracedProgram, error) { tidMap := make(map[int]bool) retryCount := make(map[int]int) @@ -105,7 +103,7 @@ func NewTracedProgram(pid int, logger logr.Logger) (*TracedProgram, error) { retryCount[tid]++ } if retryCount[tid] < threadRetryLimit { - logger.V(1).Info("retry attaching thread", "tid", tid, "retryCount", retryCount[tid], "limit", threadRetryLimit) + logger.Debug("retry attaching thread", "tid", tid, "retryCount", retryCount[tid], "limit", threadRetryLimit) continue } @@ -119,12 +117,12 @@ func NewTracedProgram(pid int, logger logr.Logger) (*TracedProgram, error) { if err != nil { e := syscall.PtraceDetach(tid) if e != nil && !strings.Contains(e.Error(), "no such process") { - logger.Error(e, "detach failed", "tid", tid) + logger.Error("detach failed", "error", e, "tid", tid) } return nil, errors.WithStack(err) } - logger.V(1).Info("attach successfully", "tid", tid) + logger.Debug("attach successfully", "tid", tid) tids[tid] = true tidMap[tid] = true } @@ -236,7 +234,7 @@ func (p *TracedProgram) Madvise(addr uint64, length uint64) error { } minVersion := version.Must(version.NewVersion("5.14")) - p.logger.V(1).Info("Detected linux kernel version", "version", ver) + p.logger.Debug("Detected linux kernel version", "version", ver) if ver.GreaterThanOrEqual(minVersion) { advice = syscall.MADV_WILLNEED | MadvisePopulateRead | MadvisePopulateWrite } @@ -248,6 +246,6 @@ func (p *TracedProgram) Madvise(addr uint64, length uint64) error { // Mlock runs mlock syscall. func (p *TracedProgram) Mlock(addr uint64, length uint64) error { ret, err := p.Syscall(syscall.SYS_MLOCK, addr, length, 0, 0, 0, 0) - p.logger.V(1).Info("mlock ret", "ret", ret) + p.logger.Debug("mlock ret", "ret", ret) return err } diff --git a/internal/pkg/process/ptrace/ptrace_other.go b/internal/pkg/process/ptrace/ptrace_other.go index ae879ad05..1a683e906 100644 --- a/internal/pkg/process/ptrace/ptrace_other.go +++ b/internal/pkg/process/ptrace/ptrace_other.go @@ -5,13 +5,13 @@ package ptrace -import "github.com/go-logr/logr" +import "log/slog" // Stubs for non-linux systems type TracedProgram struct{} -func NewTracedProgram(pid int, logger logr.Logger) (*TracedProgram, error) { +func NewTracedProgram(pid int, logger *slog.Logger) (*TracedProgram, error) { return nil, nil } diff --git a/internal/tools/go.mod b/internal/tools/go.mod index c93cb818f..14c9426cc 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -6,8 +6,6 @@ toolchain go1.22.6 require ( github.com/docker/docker v27.2.0+incompatible - github.com/go-logr/logr v1.4.2 - github.com/go-logr/stdr v1.2.2 github.com/golangci/golangci-lint v1.60.3 github.com/google/go-licenses/v2 v2.0.0-alpha.1 github.com/hashicorp/go-version v1.7.0 @@ -77,6 +75,8 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/go-git/go-git/v5 v5.12.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect diff --git a/internal/tools/inspect/app.go b/internal/tools/inspect/app.go index e8a31d78a..54b0531e3 100644 --- a/internal/tools/inspect/app.go +++ b/internal/tools/inspect/app.go @@ -10,9 +10,9 @@ import ( "errors" "fmt" "io" + "log/slog" "os" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "go.opentelemetry.io/auto/internal/pkg/structfield" @@ -25,7 +25,7 @@ type app struct { AppVer *version.Version Fields []structfield.ID - log logr.Logger + log *slog.Logger tmpDir string exec string data *dwarf.Data @@ -36,13 +36,13 @@ type app struct { // The new app is built in a temp directory. It is up to the caller to ensure // the returned app's Close method is called when it is no longer needed so // all temp directory resources are cleaned up. -func newApp(ctx context.Context, l logr.Logger, j job) (*app, error) { +func newApp(ctx context.Context, l *slog.Logger, j job) (*app, error) { a := &app{ Renderer: j.Renderer, Builder: j.Builder, AppVer: j.AppVer, Fields: j.Fields, - log: l.WithName("app"), + log: l, } var err error @@ -79,14 +79,14 @@ func newApp(ctx context.Context, l logr.Logger, j job) (*app, error) { return nil, err } - a.log.V(1).Info("built app", "binary", a.exec) + a.log.Debug("built app", "binary", a.exec) return a, nil } // GetOffset returnst the struct field offset for sf. It uses the DWARF data // of the app's built binary to find this value. func (a *app) GetOffset(id structfield.ID) (uint64, bool) { - a.log.V(1).Info("analyzing binary...", "id", id, "binary", a.exec) + a.log.Debug("analyzing binary...", "id", id, "binary", a.exec) strct := fmt.Sprintf("%s.%s", id.PkgPath, id.Struct) r := a.data.Reader() diff --git a/internal/tools/inspect/builder.go b/internal/tools/inspect/builder.go index 7a0f7dcfd..6452c4e83 100644 --- a/internal/tools/inspect/builder.go +++ b/internal/tools/inspect/builder.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "io" + "log/slog" "path/filepath" "github.com/docker/docker/api/types/container" @@ -16,7 +17,6 @@ import ( "github.com/docker/docker/api/types/mount" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" ) @@ -25,7 +25,7 @@ var minCompatVer = version.Must(version.NewVersion("1.17.0")) // builder builds a Go application into a binary using Docker. type builder struct { - log logr.Logger + log *slog.Logger cli *client.Client goVer *version.Version @@ -38,7 +38,7 @@ type builder struct { // // If goVer is nil, the latest version of the Go docker container will be used // to build applications. -func newBuilder(l logr.Logger, cli *client.Client, goVer *version.Version) *builder { +func newBuilder(l *slog.Logger, cli *client.Client, goVer *version.Version) *builder { img := "golang:latest" if goVer != nil { // Use goVer.String here so 1.12 means 1.12.0. If Original is used, it @@ -47,7 +47,7 @@ func newBuilder(l logr.Logger, cli *client.Client, goVer *version.Version) *buil img = fmt.Sprintf("golang:%s", goVer.String()) } return &builder{ - log: l.WithName("builder"), + log: l, cli: cli, goVer: goVer, GoImage: img, @@ -56,7 +56,7 @@ func newBuilder(l logr.Logger, cli *client.Client, goVer *version.Version) *buil // Build builds the appV version of a Go application located in dir. func (b *builder) Build(ctx context.Context, dir string, appV *version.Version, modName string) (string, error) { - b.log.V(2).Info("building application...", "version", appV, "dir", dir, "image", b.GoImage) + b.log.Debug("building application...", "version", appV, "dir", dir, "image", b.GoImage) app := fmt.Sprintf("app%s", appV.Original()) goGetCmd := fmt.Sprintf("go get %s@%s", modName, appV.Original()) @@ -77,12 +77,12 @@ func (b *builder) Build(ctx context.Context, dir string, appV *version.Version, return "", err } - b.log.V(1).Info("built application", "version", appV, "dir", dir, "image", b.GoImage) + b.log.Debug("built application", "version", appV, "dir", dir, "image", b.GoImage) return filepath.Join(dir, app), nil } func (b *builder) runCmd(ctx context.Context, cmd []string, dir string) error { - b.log.V(2).Info("running command...", "cmd", cmd, "dir", dir, "image", b.GoImage) + b.log.Debug("running command...", "cmd", cmd, "dir", dir, "image", b.GoImage) err := b.pullImage(ctx) if err != nil { @@ -108,7 +108,7 @@ func (b *builder) pullImage(ctx context.Context) error { return err } if len(summaries) > 0 { - b.log.V(2).Info("using local image", "image", b.GoImage) + b.log.Debug("using local image", "image", b.GoImage) return nil } @@ -120,7 +120,7 @@ func (b *builder) pullImage(ctx context.Context) error { out := new(bytes.Buffer) _, err = io.Copy(out, rc) - b.log.V(1).Info("pulling image", "image", b.GoImage, "output", out.String()) + b.log.Debug("pulling image", "image", b.GoImage, "output", out.String()) return err } diff --git a/internal/tools/inspect/cache.go b/internal/tools/inspect/cache.go index 24af68b84..5a91b279e 100644 --- a/internal/tools/inspect/cache.go +++ b/internal/tools/inspect/cache.go @@ -5,9 +5,9 @@ package inspect import ( "encoding/json" + "log/slog" "os" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "go.opentelemetry.io/auto/internal/pkg/structfield" @@ -15,13 +15,13 @@ import ( // Cache is a cache of struct field offsets. type Cache struct { - log logr.Logger + log *slog.Logger data *structfield.Index } // NewCache loads struct field offsets from offsetFile and returns them as a // new Cache. -func NewCache(l logr.Logger, offsetFile string) (*Cache, error) { +func NewCache(l *slog.Logger, offsetFile string) (*Cache, error) { c := newCache(l) f, err := os.Open(offsetFile) @@ -35,8 +35,8 @@ func NewCache(l logr.Logger, offsetFile string) (*Cache, error) { return c, err } -func newCache(l logr.Logger) *Cache { - return &Cache{log: l.WithName("cache")} +func newCache(l *slog.Logger) *Cache { + return &Cache{log: l} } // GetOffset returns the cached offset key and true for the id at the specified @@ -54,6 +54,6 @@ func (c *Cache) GetOffset(ver *version.Version, id structfield.ID) (structfield. } else { msg += "miss" } - c.log.V(1).Info(msg, "version", ver, "id", id) + c.log.Debug(msg, "version", ver, "id", id) return off, ok } diff --git a/internal/tools/inspect/cmd/offsetgen/main.go b/internal/tools/inspect/cmd/offsetgen/main.go index 09f26f6d0..228733b33 100644 --- a/internal/tools/inspect/cmd/offsetgen/main.go +++ b/internal/tools/inspect/cmd/offsetgen/main.go @@ -10,14 +10,11 @@ import ( "encoding/json" "flag" "fmt" - "log" + "log/slog" "os" "os/signal" "runtime" - "github.com/go-logr/logr" - "github.com/go-logr/stdr" - "go.opentelemetry.io/auto/internal/pkg/structfield" "go.opentelemetry.io/auto/internal/tools/inspect" ) @@ -38,7 +35,7 @@ var ( // verbosity is the log verbosity level flag value. verbosity int - logger logr.Logger + logger *slog.Logger ) func init() { @@ -49,8 +46,7 @@ func init() { flag.Parse() - stdr.SetVerbosity(verbosity) - logger = stdr.New(log.New(os.Stderr, "", log.LstdFlags)) + logger = slog.Default() } func manifests() ([]inspect.Manifest, error) { @@ -199,7 +195,7 @@ func main() { func run() error { m, err := manifests() if err != nil { - logger.Error(err, "failed to load manifests") + logger.Error("failed to load manifests", "error", err) return err } @@ -207,14 +203,14 @@ func run() error { if cacheFile != "" { cache, err = inspect.NewCache(logger, cacheFile) if err != nil { - logger.Error(err, "failed to load cache", "path", cacheFile) + logger.Error("failed to load cache", "error", err, "path", cacheFile) // Use an empty cache. } } i, err := inspect.New(logger, cache, m...) if err != nil { - logger.Error(err, "failed to setup inspector") + logger.Error("failed to setup inspector", "error", err) return err } i.NWorkers = numCPU @@ -225,7 +221,7 @@ func run() error { to, err := i.Do(ctx) if err != nil { - logger.Error(err, "failed get offsets") + logger.Error("failed get offsets", "error", err) return err } @@ -237,7 +233,7 @@ func run() error { logger.Info("writing offsets", "dest", outputFile) f, err := os.Create(outputFile) if err != nil { - logger.Error(err, "failed to open output file", "dest", outputFile) + logger.Error("failed to open output file", "error", err, "dest", outputFile) return err } defer f.Close() @@ -245,7 +241,7 @@ func run() error { enc := json.NewEncoder(f) enc.SetIndent("", " ") if err := enc.Encode(to); err != nil { - logger.Error(err, "failed to write offsets", "dest", outputFile) + logger.Error("failed to write offsets", "error", err, "dest", outputFile) return err } return nil diff --git a/internal/tools/inspect/inspector.go b/internal/tools/inspect/inspector.go index 177814743..1a87f88e4 100644 --- a/internal/tools/inspect/inspector.go +++ b/internal/tools/inspect/inspector.go @@ -6,9 +6,9 @@ package inspect import ( "context" "errors" + "log/slog" "github.com/docker/docker/client" - "github.com/go-logr/logr" "github.com/hashicorp/go-version" "golang.org/x/sync/errgroup" @@ -22,7 +22,7 @@ type Inspector struct { NWorkers int Cache *Cache - log logr.Logger + log *slog.Logger client *client.Client jobs []job @@ -34,12 +34,10 @@ type Inspector struct { // If cache is non-nil, offsets will first be looked up there. Otherwise, the // offsets will be found by building the applicatiions in the manifests and // inspecting the produced binaries. -func New(l logr.Logger, cache *Cache, manifests ...Manifest) (*Inspector, error) { - logger := l.WithName("inspector") - +func New(logger *slog.Logger, cache *Cache, manifests ...Manifest) (*Inspector, error) { if cache == nil { logger.Info("using empty cache") - cache = newCache(l) + cache = newCache(logger) } cli, err := client.NewClientWithOpts( @@ -72,7 +70,7 @@ func (i *Inspector) AddManifest(manifest Manifest) error { return err } - i.log.V(2).Info("adding manifest", "manifest", manifest) + i.log.Debug("adding manifest", "manifest", manifest) goVer := manifest.Application.GoVerions if goVer == nil { @@ -218,7 +216,7 @@ func (i *Inspector) do(ctx context.Context, j job) (out []result, err error) { app, err := newApp(ctx, i.log, j) buildErr := &errBuild{} if errors.As(err, &buildErr) { - i.log.V(1).Info( + i.log.Debug( "failed to build app, skipping", "version", j.AppVer, "src", j.Renderer.src, diff --git a/internal/tools/inspect/render.go b/internal/tools/inspect/render.go index c64c09aba..8280a9758 100644 --- a/internal/tools/inspect/render.go +++ b/internal/tools/inspect/render.go @@ -6,12 +6,11 @@ package inspect import ( "embed" "io/fs" + "log/slog" "os" "path/filepath" "strings" "text/template" - - "github.com/go-logr/logr" ) //go:embed templates/golang.org/x/net/*.tmpl @@ -24,7 +23,7 @@ var DefaultFS embed.FS // Renderer renders templates from an fs.FS. type Renderer struct { - log logr.Logger + log *slog.Logger fs fs.FS src string @@ -34,11 +33,11 @@ type Renderer struct { // in f at the provided src. // // If f is nil, DefaultFS will be used instead. -func NewRenderer(l logr.Logger, src string, f fs.FS) Renderer { +func NewRenderer(l *slog.Logger, src string, f fs.FS) Renderer { if f == nil { f = DefaultFS } - return Renderer{log: l.WithName("renderer"), fs: f, src: src} + return Renderer{log: l, fs: f, src: src} } // Render renders the Renderer's src in dest using data. @@ -46,14 +45,14 @@ func NewRenderer(l logr.Logger, src string, f fs.FS) Renderer { // All src will be rendered in the same file-tree with the same names (except // for any ".tmpl" suffixes) as found in the Renderer's fs.FS. func (r Renderer) Render(dest string, data interface{}) error { - r.log.V(2).Info("rendering...", "src", r.src, "dest", dest, "data", data) + r.log.Debug("rendering...", "src", r.src, "dest", dest, "data", data) tmpls, err := template.ParseFS(r.fs, r.src) if err != nil { return err } for _, tmpl := range tmpls.Templates() { - r.log.V(3).Info("rendering template...", "template", tmpl.Name) + r.log.Debug("rendering template...", "template", tmpl.Name) target := filepath.Join(dest, strings.TrimSuffix(tmpl.Name(), ".tmpl")) wr, err := os.Create(target) if err != nil { @@ -64,9 +63,9 @@ func (r Renderer) Render(dest string, data interface{}) error { if err != nil { return err } - r.log.V(2).Info("rendered template", "template", tmpl.Name()) + r.log.Debug("rendered template", "template", tmpl.Name()) } - r.log.V(1).Info("rendered", "src", r.src, "dest", dest, "data", data) + r.log.Debug("rendered", "src", r.src, "dest", dest, "data", data) return nil } diff --git a/level.go b/level.go deleted file mode 100644 index 9565d8dc9..000000000 --- a/level.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package auto - -import ( - "bytes" - "errors" - "fmt" -) - -// LogLevel defines the log level which instrumentation uses. -type LogLevel string - -const ( - // logLevelUndefined is an unset log level, it should not be used. - logLevelUndefined LogLevel = "" - // LogLevelDebug sets the logging level to log all messages. - LogLevelDebug LogLevel = "debug" - // LogLevelInfo sets the logging level to log only informational, warning, and error messages. - LogLevelInfo LogLevel = "info" - // LogLevelWarn sets the logging level to log only warning and error messages. - LogLevelWarn LogLevel = "warn" - // LogLevelError sets the logging level to log only error messages. - LogLevelError LogLevel = "error" -) - -var errInvalidLogLevel = errors.New("invalid LogLevel") - -// String returns the string encoding of the LogLevel l. -func (l LogLevel) String() string { - switch l { - case LogLevelDebug, LogLevelInfo, LogLevelWarn, LogLevelError, logLevelUndefined: - return string(l) - default: - return fmt.Sprintf("Level(%s)", string(l)) - } -} - -// UnmarshalText applies the LogLevel type when inputted text is valid. -func (l *LogLevel) UnmarshalText(text []byte) error { - *l = LogLevel(bytes.ToLower(text)) - - return l.validate() -} - -func (l *LogLevel) validate() error { - if l == nil { - return errors.New("nil LogLevel") - } - - switch *l { - case LogLevelDebug, LogLevelInfo, LogLevelWarn, LogLevelError: - // Valid. - default: - return fmt.Errorf("%w: %s", errInvalidLogLevel, l.String()) - } - return nil -} - -// ParseLogLevel return a new LogLevel parsed from text. A non-nil error is returned if text is not a valid LogLevel. -func ParseLogLevel(text string) (LogLevel, error) { - var level LogLevel - - err := level.UnmarshalText([]byte(text)) - - return level, err -} diff --git a/level_test.go b/level_test.go deleted file mode 100644 index a87ca9892..000000000 --- a/level_test.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package auto - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestLevelString(t *testing.T) { - testCases := []struct { - name string - level LogLevel - str string - }{ - { - name: "LogLevelUndefined", - level: logLevelUndefined, - str: "", - }, - { - name: "LogLevelDebug", - level: LogLevelDebug, - str: "debug", - }, - { - name: "LogLevelInfo", - level: LogLevelInfo, - str: "info", - }, - { - name: "LogLevelWarn", - level: LogLevelWarn, - str: "warn", - }, - { - name: "LogLevelError", - level: LogLevelError, - str: "error", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - assert.Equal(t, tc.str, tc.level.String(), "string does not match") - }) - } -} - -func TestValidate(t *testing.T) { - l := LogLevel("notexist") - assert.ErrorIs(t, l.validate(), errInvalidLogLevel) -} - -func TestParseLogLevel(t *testing.T) { - testCases := []struct { - name string - str string - level LogLevel - }{ - { - name: "ParseLogLevelDebug", - str: "debug", - level: LogLevelDebug, - }, - { - name: "ParseLogLevelInfo", - str: "info", - level: LogLevelInfo, - }, - { - name: "ParseLogLevelWarn", - str: "warn", - level: LogLevelWarn, - }, - { - name: "ParseLogLevelError", - str: "error", - level: LogLevelError, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - l, _ := ParseLogLevel(tc.str) - - assert.Equal(t, tc.level, l, "LogLevel does not match") - }) - } - - t.Run("ParseNotExist", func(t *testing.T) { - _, err := ParseLogLevel("notexist") - - assert.ErrorIs(t, err, errInvalidLogLevel) - }) -}