-
Notifications
You must be signed in to change notification settings - Fork 8
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
feat: log opentelemetry logs and errors using a provided zap logger #239
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #239 +/- ##
==========================================
- Coverage 60.40% 58.84% -1.56%
==========================================
Files 55 72 +17
Lines 1836 2396 +560
==========================================
+ Hits 1109 1410 +301
- Misses 659 905 +246
- Partials 68 81 +13 ☔ View full report in Codecov by Sentry. |
looking into static analysis failures |
@@ -0,0 +1,22 @@ | |||
package errorhandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you check if this works for our custom batchspanprocessor or if it can be adapted the new zap logger? https://github.com/hypertrace/goagent/tree/main/instrumentation/opentelemetry/batchspanprocessor . We add some custom code in our batchspanprocessor like catching panics and metrics for spans received, sent and dropped. Since we cannot use the logger in the internal package in the otel go repo, we adapt it and even initialize a new stdout logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didnt know we had a logger here. We can do it, zap has a global api. We can either wrap it in go-logr or use zap itself in the custom bsp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -245,6 +248,19 @@ func Init(cfg *config.AgentConfig) func() { | |||
// and returns a shutdown function to flush data immediately on a termination signal. | |||
func InitWithSpanProcessorWrapper(cfg *config.AgentConfig, wrapper SpanProcessorWrapper, | |||
versionInfoAttrs []attribute.KeyValue) func() { | |||
logger, err := zap.NewProduction() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there existing log config we can use to set some config in the zap logger we create?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We dont have any existing log config in the hypertrace proto. The traceable goagent initializes logger with this config: https://github.com/Traceableai/goagent-src/blob/main/init.go#L29. Maybe we can move that logic here? Or can just use the new zap compatible api there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a techdebt ticket to move the hypertrace goagent login into traceable goagent and archive hypertrace goagent. So we should probably wait until we do that and in hypertrace we can go with some zap logger support. But it should be overridable by the traceable goagent one for now. I did not know that we already had a zap logger in traceable goagent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh okay, then I think we should be good. We can pass that zap logger here with the new api
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My ask here is that we should be able to use the logger created in the agent(i.e. mirroring-agent/ebpf) so that we can control where do the logs go(file/stdout/stderr), loglevels, rotation from one place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. As of now ebpf calls this api: https://github.com/Traceableai/ebpf/blob/main/pkg/export/exporter.go#L41
This calls the InitWithSpanProcessorWrapper
here https://github.com/Traceableai/goagent-src/blob/main/init.go#L37. Now we'll update the goagent-src to also expose an api for taking in a zap logger, and will call InitWithSpanProcessorWrapperAndZap
instead of InitWithSpanProcessorWrapper
, then we can update the respective clients (ebpf/mirroring-agent/ext_cap)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. If the same zap logger or zapcore object can be used throughout, that would be ideal.
@varkey98 Trying to understand how would batchSpanProcessor get the zap.Logger instance which is created for ext_cap/mirroring-agent/ebpf? |
It'll be like the goagent client calls |
One caveat is that if any of our agents set a zap global logger, that will be overwritten during goagent initialization. I dont think any of our agents do this, but we should remember this in the future |
// since global variables init happens on package imports, | ||
// the zap global logger might not be set by then | ||
// hence doing a lazy initialization | ||
func getLogger() logr.Logger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we instead pass logger here
goagent/instrumentation/opentelemetry/init.go
Line 309 in 94709da
sp := modbsp.CreateBatchSpanProcessor( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works with whatever logger we pass as of now. I've checked with file logger on TPA. Because we set the global logger here: https://github.com/hypertrace/goagent/blob/main/instrumentation/opentelemetry/init.go#L288. Only case this wont work is when someone sets another global zap logger from another go routine. But I dont think we do that anywhere. I didnt want to set it in the bsp struct because that'll modify the function interface compared to otel and thought we didnt want to do that. @tim-mwangi ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
traceable goagent has it's own global logger implemented with zap, I thought that when we port this to that repo, we can change the bsp to our global logger instead of zap global logger and this as makeshift mechanism for the time being
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for the logger being adapted is that it is an internal package and so cannot be used in our customized batchspanprocessor. So it the env. https://github.com/open-telemetry/opentelemetry-go/blob/64416533d5cc340a8cc53d98084604758283af09/sdk/trace/batch_span_processor.go#L13
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/sdk/internal/env"
So we can pass it but be careful to maintain the custom changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be okay for now. I did not see that replaceLogger call earlier.
} | ||
|
||
// Warn prints messages about warnings in the API or SDK. | ||
// Not an error but is likely more important than an informational event. | ||
func Warn(msg string, keysAndValues ...interface{}) { | ||
logger.V(1).Info(msg, keysAndValues...) | ||
getLogger().V(1).Info(msg, keysAndValues...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, do we need separate verbosity levels here? How does that gets configured?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this, kept the existing behavior. cc: @tim-mwangi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is based on the adaptation from https://github.com/open-telemetry/opentelemetry-go/blob/main/internal/global/internal_logging.go. I believe they are the levels in the logr package. If we are somehow hooking zap under the logr package, I think they should be compatible?
Description
As of now, the opentelemetry logs and errors are printed to stdout. Adding logic to use a passed zap logger for logging these. Opentelemetry go uses go-logr API for internal logging and go-logr has a zap wrapper implementation which is used for passing the provided zap logger to the opentelemetry library.
Testing
Please describe the tests that you ran to verify your changes. Please summarize what did you test and what needs to be tested e.g. deployed and tested helm chart locally.
Checklist: