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

slog context support #237

Merged
merged 2 commits into from
Dec 1, 2023
Merged

slog context support #237

merged 2 commits into from
Dec 1, 2023

Conversation

pohly
Copy link
Contributor

@pohly pohly commented Nov 26, 2023

Conversion is done on demand. A program which uses either slog or logr for
logging remains as efficient as before. What is less efficient is storing a
logger of one type and then retrieving it as the other.

Ideally, reusable packages should avoid using a slog.Logger and prefer
logr.Logger instead when retrieving a logger from a context. There is a
significant amount of packages which already work that way (Kubernetes and
related packages), while storing and retrieving a slog.Logger is new and not
done anywhere yet. Emulating existing behavior ensures better performance.

To enable on demand conversion, the slogr implementation must be moved
into the main package.

Related-to: #234

context_slog.go Outdated Show resolved Hide resolved
Copy link
Contributor

@thockin thockin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't horrible, to me, but it seems like one day slog will decide to add context support and then we'll have to do it all again.

context_noslog.go Show resolved Hide resolved
slogr.go Show resolved Hide resolved
slogr.go Outdated
//
// The logr verbosity level is mapped to slog levels such that V(0) becomes
// slog.LevelInfo and V(4) becomes slog.LevelDebug.
func NewLogr(handler slog.Handler) Logger {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we have logr.New(logr.LogSink) and logr.NewLogr(slog.Handler) ? Eww.

NewFromSlogHandler() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't thought much about the names. I agree that it makes sense to reconsider, now that they are being used with logr as package selector instead of slogr.

I'm fine with NewFromSlogHandler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed in a separate commit, to have an explanation for the reason in the commit history.

I also restored slogr/slogr_test.go because that has an example and it's worth testing the code there. It doesn't do much, but better safe than sorry...

context_slog.go Show resolved Hide resolved
@pohly
Copy link
Contributor Author

pohly commented Nov 27, 2023

This isn't horrible, to me, but it seems like one day slog will decide to add context support

Very unlikely. @jba again confirmed it, saying "They [context support methods] were very controversial.I don't see that changing." -- golang/go#56345 (comment)

@thockin
Copy link
Contributor

thockin commented Nov 27, 2023

I suspect that Context methods will be reconsidered as people adopt slog and find that to be egregiously absent. It was contentious among vocal early-adopters. It won't be contentious among the larger population (I think).

@pohly
Copy link
Contributor Author

pohly commented Nov 28, 2023

I've pushed an update:

  • first commit updated to restore slogr/slogr_test.go
  • new commits for renaming and documentation

README.md Outdated
@@ -145,11 +146,12 @@ There are implementations for the following logging libraries:
## slog interoperability

Interoperability goes both ways, using the `logr.Logger` API with a `slog.Handler`
and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` and
`NewSlogHandler` API calls to convert between a `logr.Logger` and a `slog.Handler`.
and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` (= `logr.NewFromSlogHandler`) and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this effectively replaces slogr, then we should just document the logr APIs here, not slogr.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure whether we'd want to deprecate slogr - it just got added 🥵

But we can also do that, no strong opinion from me about it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love having two equivaent ways of saying the same thng which are both "suported". Deprecated doesn't mean gone, just "look here instead". IMO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

slogr/slogr.go Show resolved Hide resolved
slogr/slogr.go Outdated
@@ -36,14 +36,11 @@ import (
//
// The logr verbosity level is mapped to slog levels such that V(0) becomes
// slog.LevelInfo and V(4) becomes slog.LevelDebug.
//
// NewLogr is identical to [logr.NewFromSlogHandler]. Either of these can
// be used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be Deprecated: Use logr.NewFromSlogHandler instead ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also kill off all the duplicate docs that way - users just go read the logr version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The duplicated docs are indeed annoying. I'm leaning towards simply deprecating slogr now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

slogr/slogr.go Outdated
@@ -64,16 +61,11 @@ func NewLogr(handler slog.Handler) logr.Logger {
// slog.New(NewSlogHandler(logger)).Warning(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger)).Info(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger.V(4))).Info(...) -> logger.GetSink().Info(level=4, ...)
//
// NewSlogHandler is identical to [logr.NewSlogHandler]. Either of these can
// be used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same above re: Deprecated and var

slogr_test.go Show resolved Hide resolved
slogr_test.go Outdated
// level=DEBUG msg="with values, verbosity and name" x=1 y=2 str=abc logger=foo/bar
}

func ExampleNewSlogLogger() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be ExampleNewSlogHandler ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, fixed.

slogr_test.go Outdated
}

func ExampleNew() {
logger := logr.NewFromSlogHandler(slog.NewTextHandler(os.Stdout, debugWithoutTime))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we name the var logrLogger ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

slogr_test.go Outdated
Verbosity: 10,
})

logger := slog.New(logr.NewSlogHandler(funcrLogger))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we name the var slogLogger ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

context_slog.go Outdated
}
}

// FromContext returns a slog.Logger from ctx or nil if no such Logger is found.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment doesn't match code wrt the name

context_slog.go Outdated
}

// FromContext returns a slog.Logger from ctx or nil if no such Logger is found.
func SlogLoggerFromContext(ctx context.Context) *slog.Logger {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can I argue for FromContextAsSlogLogger so the FromContext and NewContext prefixes survive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, make sense.

@thockin
Copy link
Contributor

thockin commented Nov 29, 2023

ICYMI - there was no new push :)

@pohly
Copy link
Contributor Author

pohly commented Nov 29, 2023

ICYMI - there was no new push :)

I wanted to revise the documentation part first regarding deprecation, but I am not going to get to that this evening anymore, so I pushed what I have just now. The next update will be tomorrow.

@pohly pohly force-pushed the slog-context-in-logr branch 2 times, most recently from 9ac9983 to ca4a15b Compare November 30, 2023 09:04
@pohly
Copy link
Contributor Author

pohly commented Nov 30, 2023

I've updated the documentation and removed the slogr/slogr_test.go: https://github.com/go-logr/logr/compare/9ac998326cdc223355affa6baeab839316117be4..ca4a15b75ca78b8f2db2de3e41b660c810ef5b9e

provides additional support code for this approach. It also contains wrappers
for the context functions in logr, so developers who prefer to not use the logr
APIs directly can use those instead and the resulting code will still be
interoperable with logr.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@veqryn: does this look okay to you?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Thank you.

Copy link
Contributor

@thockin thockin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
This is necessary to give the context handling functions access to the slogr
functionality. Functions get renamed to match names in the main package
where needed.

The slogr package is now deprecated, but continues to be supported as part of
the logr v1 API by keeping all exported items as wrappers or aliases for the
main package.
Conversion is done on demand. A program which uses either slog or logr for
logging remains as efficient as before. What is less efficient is storing a
logger of one type and then retrieving it as the other.

Ideally, reusable packages should avoid using a slog.Logger and prefer
logr.Logger instead when retrieving a logger from a context. There is a
significant amount of packages which already work that way (Kubernetes and
related packages), while storing and retrieving a logr.Logger is new and not
done anywhere yet. Emulating existing behavior ensures better performance.
@pohly
Copy link
Contributor Author

pohly commented Nov 30, 2023

New update pushed. I also found a left-over NewLogr and comments about "is identical" in the main package and removed them. I moved the slogr/example into examples/slog and updated it to use the main package's API.

=> https://github.com/go-logr/logr/compare/ca4a15b75ca78b8f2db2de3e41b660c810ef5b9e..f1edf4f6aed3da9f4599674ea66e013fd37a5446

@thockin
Copy link
Contributor

thockin commented Nov 30, 2023

LGTM - hold for @veqryn to take a look?

Copy link

@veqryn veqryn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 LGTM
After the next release, I will update slog-context to use this, and pull you all into the PR to take a look. :)

@thockin thockin merged commit 6151b2f into go-logr:master Dec 1, 2023
14 checks passed
@veqryn
Copy link

veqryn commented Dec 2, 2023

@pohly @thockin Could I get your eyes on this pr please: veqryn/slog-context#1

}
return handler
// Deprecated: use [logr.ToSlogHandler] instead.
func ToSlogHandler(logger logr.Logger) slog.Handler {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argh!

I messed up some global search/replace and renamed NewSlogHandler to ToSlogHandler although here we have to keep the old name.

Found when updating logr in klog. Will prepare a fix.

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

Successfully merging this pull request may close these issues.

None yet

3 participants