The new packageHandler allows global slog.Loggers to be created
with attributes and groups that are not expanded until runtime.
This allows the data to be formatted with a custom slog.Handler
which is set via slog.SetDefault instead of the default logger
provided by log/slog.
Closes#40629
Builds on https://github.com/gravitational/teleport/pull/39974 to
prefer writing a single string instead of a json object to logs. This
more closely follows the behavior of the text formatter which
will output strings. The primary motivation is to ensure that no
secrets or unwanted items of a struct make it into json logs because
it is converting an object differently than the text handler.
There are two other options to avoid this, but both rely on doing
the right thing when adding an attribute, which may be overlooked or
forgotten and ultimately not noticed because only text ouput was
tested with.
1) Call .String() directly on the attribute, but this goes against
the performance guidance in the slog docs.
2) Wrap the attribute in a logutils.StringerAttr which follows the
recomendations in the slog docs:
> If you want to avoid eagerly paying the cost of the String call
> without causing the handler to potentially inspect the structure
> of the value, wrap the value in a fmt.Stringer implementation
> that hides its Marshal methods.
The default slog json handler attempts to format attributes with
json.Marshal instead of a string representation, which resulted in
errors being output as json objects instead of just the message.
```
"error":{"error":{"message":"Unable to communicate with the Teleport Auth Service"}}
```
In order to restore json output to contain only the error message
instead of the entire object special handling is done in our slog
handler wrapper that replaces the error object with the message.
* Make slog attributes output the same content regardless of format
There were a few instances of fmt.Stringers being passed to slog
as attributes to delay their evaluation as per the performance
considerations of slog: https://pkg.go.dev/log/slog#hdr-Performance_considerations.
However, this resulted in the json handler emitting different
content since they check to see if attributes are json.Marshalers
and not fmt.Stringers. To rectify the situation, a new slog.LogValuer
implementation was added that wraps a fmt.Stringer so that attributes
can be lazily constructed while producing the same output no matter
the log output format.
* fix: wrap identity and correct typo
* Bump github.com/gravitational/trace from 1.3.1 to 1.4.0
## Changelog
- Bump google.golang.org/grpc from 1.43.0 to 1.53.0 by @dependabot in #94
- Bump golang.org/x/net from 0.8.0 to 0.17.0 by @dependabot in #100
- Bump google.golang.org/grpc from 1.53.0 to 1.56.3 by @dependabot in #101
- Bump golang.org/x/crypto from 0.14.0 to 0.17.0 by @dependabot in #105
## Breaking Changes
- Remove logrus dependency by @rosstimothy in #107
- Remove references to UDP logrus hook from README by @rosstimothy in #108
Full Changelog: https://github.com/gravitational/trace/compare/v1.3.1...v1.4.0
* remove final references to removed trace functionality
* fix: formatter error handling
* Remove logging from circuit breaker
The logging is never output, and if it was would be very verbose.
Instead of dropping the level down to trace the logger is removed
entirely.
* Add constants from trace library
The logging functionality in trace is being removed in an upcoming
release. To prepare the logging component keys are copied from trace
into teleport.
* Convert trace.ComponentFields to teleport.ComponentFields
* Replace trace.Component with teleport.ComponentKey
* Replace trace logging constants
* Update slog handlers to support configured extra_fields
In addition to configuring output format users can configure the
fields which are included in log messages. Prior to this our slog
handlers didn't support this feature and always output the default
fields. Now, both the slog and logrus output is identical no matter
the extra_fields configuration as verified by TestExtraFields. It
was also found that due to the way the logurs json formatter was
configuring itself in CheckAndSetDefaults the timestamp was always
included in the final output even if it was not included in the
configured extra_fields.
* fix: update component comment
Prefer the stdlib version of the experimental package.
Includes a depguard update to prevent future regressions,
as well as an e-ref update to appease depguard.
Generated with:
$ gofmt -w -r '"golang.org/x/exp/slices" -> "slices"' . && \
make fix-imports
Tests were failing if too much time had passed between the output
of each logger being generated. The InDelta assertion was supposed
to prevent this, but because it used nanoseconds the delta of 10
was always exceeded and resulted in errors like below.
```
Max difference between 1701993842000000000 and 1701993843000000000 allowed is 10, but difference was -1e+09
```
To avoid this the assertion is now using Unix instead of UnixNano
so that we allow up to 10 seconds of drift in the timestamps.
CI is slow enough that the messages output from logrus and slog do
not occur at the same exact time. To account for the difference
the timestamp is parsed and validated to be close enough in time.
In all places that a logrus logger is being initialized an equivalent
slog logger is now being intialized as well. The TeleportProcess
was also updated to have a slog.Logger which is created with the
same fields that its logrus equivalent has. This does not convert
any logging to actually use slog yet, but does pave the way for
conversions to start.
Since the formatter does not directly write the output it creates
and instead returns it to later be written we cannot reuse the
buffer in a pool without potential races. This reverts the behavior
of the formatter to create a new buffer instead of pulling one
from a pool of buffers during formatting.
Implements two new slog.Handlers that attempt to output text in the
same format as existing logrus.TextFormatter implementations. The
most notable differences are that the order of fields in the json
output does NOT match the logrus order and the additional items
in text output are NOT sorted alphabetically like they are in logrus.
Tests added validate the output roughly matches between the two
loggers given the differences noted above. A benchmark test is also
included to demonstrate the improvements slog offers over logrus.