Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace lager.Logger with log/slog.Logger #267

Closed
elgohr opened this issue Aug 17, 2023 · 4 comments · Fixed by #292
Closed

Replace lager.Logger with log/slog.Logger #267

elgohr opened this issue Aug 17, 2023 · 4 comments · Fixed by #292

Comments

@elgohr
Copy link

elgohr commented Aug 17, 2023

Is your feature request related to a problem? Please describe.

At the moment the brokerapi requires an import of lager.Logger as another third party dependency.
As the lager.Logger interface contains LogFormat in Sink, it can't be implemented without the dependency to lager.Logger.
I would like to avoid the dependency to another third party dependency.

Describe the solution you'd like

Replace lager.Logger with an own interface or use log/slog.Logger as a solution from the standard library.

Describe alternatives you've considered

No response

Additional context

No response

@cf-gitbot
Copy link
Member

We have created an issue in Pivotal Tracker to manage this:

https://www.pivotaltracker.com/story/show/185850722

The labels on this github issue will be updated when the story is started.

@blgm
Copy link
Member

blgm commented Aug 23, 2023

I think this is the right strategic direction.

The earliest I would want to do this is when Go 1.20 goes out of support, as until that point users would expect brokerapi to work with supported Go versions.

I recently created a PR against lager to add compatibility between lager and log/slog. If it gets merged, it would allow you to write apps that use log/slog and "convert" your slog.Logger into a lager.Sink, something like:

func foo(slogLogger *slog.Logger) {
  lagerLogger := lager.NewLogger("my-lager-logger")
  lagerLogger.RegisterSink(lager.NewSlogSink(slogLogger))
  brokerapi.New(Broker{}, lagerLogger, Creds{})
  ...

It doesn't get rid of the dependency on lager, but it would allow you to use log/slog elsewhere and limit the leakage of lager into the rest of your code. The idea is that you can take a step in the right direction, and at some later stage lager could be removed from brokerapi (though I can't promise this will happen as it would be a big breaking change). What do you think?

@elgohr
Copy link
Author

elgohr commented Aug 23, 2023

Regarding the timeline I would agree.

Regarding the logger and in context of SBOMs I would see it as a problem if every dependency would add their favorite logging framework (version) to the game. Today I could write a wrapper on my own - but I can’t remove the dependency.
I would prefer to use an interface.

@blgm
Copy link
Member

blgm commented Jan 29, 2024

Hi @elgohr , with Go 1.22 likely to be released soon, I've created PR #292 which replaces lager with slog. I think it's inline with what you were suggesting. I'd be very interested in any feedback or suggestions that you have.

@blgm blgm closed this as completed in #292 Apr 2, 2024
blgm added a commit that referenced this issue Apr 2, 2024
## Breaking Changes
This package now accepts a `*slog.Logger` from the Go standard library, rather than a [Lager logger](https://github.com/cloudfoundry/lager). This allows the use of alternative loggers.

- This package no longer requires you to import `code.cloudfoundry.org/lager/v3`.
- The constructors `New()`, `NewWithCustomAuth()`, `NewWithOptions()`, and also `AttachRoutes()` all take a `*slog.Logger`
- `apiresponses.FailureResponse` errors with a `ValidatedStatusCode()` method also take a `*slog.Logger` rather than a Lager logger
- The middleware `middlewares.APIVersionMiddleware` has had the `LoggerFactory` field removed, and a new field `Logger` added with type `*slog.Logger`.

If you want to continue to use Lager, you can just convert it to a `*slog.Logger`, for which you will need Lager [v3.0.3](https://github.com/cloudfoundry/lager/releases/tag/v3.0.3) for example:
```go
logger := lager.NewLogger("a-lager-logger")
router := brokerapi.New(serviceBroker, slog.New(lager.NewHandler(logger)), credentials)
```

## Reasons
Historically brokerapi has required use of the [`lager`](https://github.com/cloudfoundry/lager) logger. In Go 1.21, structured logging was introduced into the Go standard library via the [`log/slog`](https://pkg.go.dev/log/slog) package, and `slog` [compatability was added](cloudfoundry/lager@4bf4955) to `lager`.

`brokerapi` has been modified to require a `slog` logger to be passed rather than a `lager` logger. This allows users a choice of logger. Users who still want to use lager can easily do that using the lager/slog compatability.

And users who want to use `slog` or an `slog`-compatible logger can do that instead.

A key advantage is that `lager` is no longer a dependency of this package, which simplifies package management for apps that use brokerapi and other libraries which use `lager`.

Resolves #267
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants