-
Notifications
You must be signed in to change notification settings - Fork 546
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
ioredis: add requireParent config option #344
Comments
I think we could also disable instrumentation when |
You mean remove the creation of |
@blumamir Yeah i think it makes more sense than adding |
I would call it With regards to removing |
I agree. At least the default behavior and config option names should be unified across all instrumentation libraries. If we choose to go on the |
I like the name
Not sure I understood. Where do you suggest to inject this Noop implementation in the instrumentation libraries? |
I was just referring to |
There is no more NoRecordingSpan. It was removed and there is only Noop now. Additionally, spec says not to create them directly. use NOOP_TRACER.startSpan instead |
We are talking about the same, whatever it will be NoRecordingSpan, NOOP_TRACER or any other Noop object I would rather use this Noop than create extra complexity with if statements everywhere. |
Maybe I am missing something, but the private _startHttpSpan(name: string, options: SpanOptions) {
/*
* If a parent is required but not present, we use a `NoopSpan` to still
* propagate context without recording it.
*/
const requireParent =
options.kind === SpanKind.CLIENT
? this._getConfig().requireParentforOutgoingSpans
: this._getConfig().requireParentforIncomingSpans;
let span: Span;
const currentSpan = getSpan(context.active());
if (requireParent === true && currentSpan === undefined) {
// TODO: Refactor this when a solution is found in
// https://github.com/open-telemetry/opentelemetry-specification/issues/530
span = NOOP_TRACER.startSpan(name, options);
} else if (requireParent === true && currentSpan?.context().isRemote) {
span = currentSpan;
} else {
span = this.tracer.startSpan(name, options);
}
this._spanNotEnded.add(span);
return span;
} Did you mean you suggest moving the logic into the |
Some code to just explain the difference what I was talking about Current state
vs Suggested state
In second example (suggested) you assign appropriate function once only. Then next time function |
@obecny , we need to also check if current span is undefined: private startSpan(){
if (this.config.requireParentSpan && getSpan(context.active()) === undefined) {
return this._original();
} else {
this._instrument();
return this._original();
}
} and we have to check it on each call to In that case, the second example becomes: private onInit(){
if (this.config.requireParentSpan) {
this._instrument = function () {
if(getSpan(context.active()) !== undefined) {
// call the regular instrument as usual.
} else {
// noop
}
};
} else {
this._instrument = function () {
// instrument etc.
};
}
}
private startSpan(){
this._instrument();
return this._original();
} or something similar, right? |
yes but you got the idea right. |
Yes. This still requires adding if statements inside each plugin thought, but it's only one if per plugin. |
sounds like a potential spec improvement |
we would have to specify this in spec. Each plugin behaves differently some adds parent and few other spans, some adds only attributes to existing span. I'm not sure if this will be an easy task to define all possible edge cases. I would add this for now only for plugins that it makes sense and maybe create some shareable helper function for it - can be inside instrumentation perhaps ? |
I meant adding |
You are right, there are too many edge cases. |
imho good idea, we just need to make sure to make it work in the backward compatible way so that we can add this safely and it will not change the behaviour of any plugin by default unless user specify this param explicitly. Lets wait for few more votes for yes or no to see what others think. |
easy to make it backwards compatible if you have |
My motivation is actually to disabled this behavior in ioredis instrumentation which is ON by default. In my opinion, we should align it to be OFF by default unless user specifically turns it ON, but that would be a behavior change for few plugins \ instrumentations. Anyway, I can send a PR for the change in core and contrib repos when we converge to a decision. |
I'm not that sure about this. I would assume the |
I have to say that I'm not completely sure why it is useful. |
It purely depends what you expect from your tracing solution to monitor. My main point is that there is no simple right/wrong here. Trying to sync all plugins and defining the "correct" default is most likely hard. |
I agree about that. |
Having in mind all different edge cases I think that This would be an optional parameter with 0 (null/undefined) as default This way current plugins don't need to be upgraded changed or forced to change their current behaviour. And we can make necessary changes slowly. |
I want to summarize the two options that were suggested and discussed: NoopSpanAdd With this approach, I imagine the plugin code to look something like: span = this.tracer.startSpan(name, { requireParent: this._config.requireParentSpan }); Very clean and easy. No InstrumentationThe other option, as suggested by @vmarchaud, is to check in each plugin code for the config and the active span, and disable instrumentation altogether. if(this._config.requireParentSpan && getSpan(context.active()) === undefined) {
return original.apply(this, arguments);
} This is more verbose and error-prone than the previous options.
I would like to fix this issue, as currently |
I prefer the no instrumentation approach. The downstream plugin issue is a real one and it should also be slightly more performant. To me it is also much more obvious what is happening |
I think also that no instrumentation is the better choice. Has someone investigated how other languages handle this? It seems this issue has moved from requireParent for ioredis to a more generic discussion. Besides the requireParent filter there are also instrumentations which have other filters, e.g. http has a url filter.
|
Thanks @Flarna for bringing it up. non configurable requireParent == It probably makes sense to look at 3 categories for libraries as well:
Each of which might have different considerations as to setting the default behavior (for example, use While there might be some undocumented reasons for setting it one way or another in specific cases, I think the project and the users can benefit from creating a unified and consistent behavior, or at least allowing user to tune this option in instrumentation configuration. instrumentation-http
instrumentation-grpc
instrumentation\plugin-ioredis
instrumentation\plugin-mongodb
instrumentation\plugin-dns
instrumentation\plugin-graphql
plugin-express
plugin-hapi
plugin-koa
plugin-mysql
plugin-pg
plugin-redis
|
ioredis instrumentation library is not creating a trace if the redis operation has no parent.
While this behaviour makes sense for some users, it might not be the desired behaviour for other, as for example redis commands might be sent from timers and then they will not be instrumented. I want to add a new config option
requireParent
similar to the one in instrumentation-http.Currently, HTTP instrumentation library is by default not requiring parent span, and ioredis does.
I would like to make them behave the same way, so by default all operations are instrumented, and user can choose not to instrument orphaned redis commands by setting the
requireParent
option totrue
.Since this is a breaking change for the library, I would like to discuss it first and hear your thought about it.
The text was updated successfully, but these errors were encountered: