Support getting CAPTURE_BODY and TRANSACTION_MAX_SPANS options from central config#577
Support getting CAPTURE_BODY and TRANSACTION_MAX_SPANS options from central config#577SergeyKleyman merged 16 commits intoelastic:masterfrom SergeyKleyman:Central_config_part_2
Conversation
…ral_config_part_2
Co-Authored-By: Brandon Morelli <bmorelli25@gmail.com>
Co-Authored-By: Brandon Morelli <bmorelli25@gmail.com>
gregkalapos
left a comment
There was a problem hiding this comment.
I think overall this is fine - sorry that it took so long for me to go through this.
If I may add some suggestions:
- If possible please add some comments in the code - that really helps others to understand it (I added below some specific places where it'd help). When you write it, it's totally obvious, I know - but 1-2 lines of comments here and there can make a huge difference for the reader.
- I think we still have lots of unrelated things in this PR - for now it's fine, I'd not change those, but in the future, especially with these bigger PRs, could we please just focus on what the PR title says? That'd make reviewing easier.
| namespace Elastic.Apm.AspNetCore.Extensions | ||
| { | ||
| public static class TransactionExtensions | ||
| internal static class TransactionExtensions |
There was a problem hiding this comment.
Hmm.. this is technically a breaking change. Probably no one uses it, because this should not be public and I 100% agree with that. I already almost made the same change in one of my previous PRs.
Still I think it'd be best to leave it public and once we release 2.0 make it internal - and go through the code base and fix if there are other similar problems (I think there are).
Unfortunately this was a mistake, but I think it'd be better to fix this on a major release bump.
There was a problem hiding this comment.
I agree with your assessment:
Probably no one uses it
So is it worth spending any more time on it?
There was a problem hiding this comment.
So is it worth spending any more time on it?
Yes, because it's just about changing internal back to public and we have 1 less breaking change. That can be done very quickly.
There was a problem hiding this comment.
Unfortunately it's not as simple as changing internal back to public because the signature of CollectRequestInfo changed.
There was a problem hiding this comment.
Oh, yeah I see. As said here, I'd left it as it is. I know, the IConfigurationReader went away, but technically we could still pass that as a parameter.
Anyway, ok, let's make it internal and hope no one uses it. But could we try to avoid these things in the future please?
| ParentId = parentId; | ||
| Transaction = new TransactionData(transaction.IsSampled, transaction.Type); | ||
|
|
||
| if (transaction.IsSampled) Context = transaction.Context; |
There was a problem hiding this comment.
I see you move capturing the context from QueueError to the Error .ctor. Is that related to the new configs coming from central config? I think it's not and I'd leave out such changes from these PRs.
I think we discussed on slack that transaction's context should be separated from the error's context. So instead of sharing it, we should capture those differently, in case one of those changes.
Probably similar to other agents (or at least Python) we should also capture Error.Context always - also in case the transaction is not sampled.
But I feel none of these are related to this PR, so I'd prefer everything related to this outside of the PR - unless I overlooked something and it's directly related to fetching the setting values from central config.
| public static void CollectRequestInfo(this ITransaction transaction, HttpContext httpContext, IConfigurationReader configurationReader, | ||
| IApmLogger logger | ||
| ) | ||
| internal static void CollectRequestBody(this Transaction transaction, bool isForError, HttpRequest request, IApmLogger logger) |
There was a problem hiding this comment.
I think the only thing related to adding CAPTURE_BODY to central config is that the IConfigurationReader is changed to transaction.ConfigSnapshot, right? Would it be possible that we do other changes (like making this method to capture the body both for errors and not errors, restructuring the code, etc.) in separate PRs in the future? It would make reviews easier - the smaller the PR is the easier it is to review.
|
|
||
| if (nameInConfig == adaptedServiceName) | ||
| _logger?.Warning()?.Log("Service name provided in configuration is {ServiceName}", nameInConfig); | ||
| _logger?.Debug()?.Log("Service name provided in configuration is {ServiceName}", nameInConfig); |
There was a problem hiding this comment.
This is no big deal, but this is I think again unrelated to the title of the PR. I usually switch to master, do this change, create a PR with a new branch and merge these separately - with git this really takes no time. That helps keeping these big PRs smaller.
| } | ||
|
|
||
| protected List<string> ParseCaptureBodyContentTypes(ConfigurationKeyValue kv, string captureBody) | ||
| protected List<string> ParseCaptureBodyContentTypes(ConfigurationKeyValue kv) |
There was a problem hiding this comment.
Sooo..what happens here is that since CAPTURE_BODY is now live changeable, we can't take that into consideration when we read CaptureBodyContentTypes, right?
There was a problem hiding this comment.
That is correct.
|
|
||
| [Theory] | ||
| [MemberData(nameof(OptionsChangedAfterStartTestVariants))] | ||
| public async Task Options_changed_after_start(int startCfgVariantIndex, OptionsTestVariant startCfgVariant) |
There was a problem hiding this comment.
It'd be really nice to add some comments to this one. To be honest, I already started going through this PR before EAH and this was the point where I gave up - some comments would really help here.
| } | ||
|
|
||
| private static bool IsCaptureRequestBodyEnabled(Transaction transaction, bool isForError) => | ||
| transaction.ConfigSnapshot.CaptureBody.Equals(ConfigConsts.SupportedValues.CaptureBodyAll) |
There was a problem hiding this comment.
At least to me IConfigurationReaderExtentions with ShouldExtractRequestBodyOnError and ShouldExtractRequestBodyOnTransactions was easier to follow than this method. - no action needed on this, just saying.
| public Context Context => _context.Value; | ||
|
|
||
| [JsonIgnore] | ||
| internal IConfigSnapshot ConfigSnapshot { get; } |
There was a problem hiding this comment.
So, if I understand correctly, the plan is that this is the ConfigSnapshot instance that we pass to every other component like Span and also this instance is used by things like TransactionExtensions, right? If I'm right, then this seems to be a fairly important property and I'd comment it. If I'm wrong, then I'd still comment it, because after looking at the code long enough I got the wrong impression.
| { | ||
| var contentType = new ContentType(httpContext.Request.ContentType); | ||
| // Is request body already captured? | ||
| if (transaction.IsContextCreated |
There was a problem hiding this comment.
Why does transaction.IsContextCreated matter here? 🤔 Is it because transaction.Context.Request would create one? If so, is there any case when only the Body is filled? I don't think so... so if we are here, I think we already have a context anyway, or not?
There was a problem hiding this comment.
I didn't want to assume too much about the context in which this method is called - the purpose was to avoid creating empty Context. I've added a comment to the code.
There was a problem hiding this comment.
Ok, sounds good to me.
| var exception = kv.Value.GetType().GetTypeInfo().GetDeclaredProperty("exception").GetValue(kv.Value) as Exception; | ||
|
|
||
| var transaction = _agent.Tracer.CurrentTransaction; | ||
| var transaction = (Transaction)_agent.Tracer.CurrentTransaction; |
There was a problem hiding this comment.
Hmm.. this cast is a little bit unfortunate - with this it MUST be a Transaction, otherwise it will throw an exception - so e.g. we can't just replace to NoOpTransaction later if needed.
I guess the root cause of the challenge here is that we don't dependency inject the configuration anymore, instead it comes through the Transaction. I'm not sure this is good - could we maybe find another way to flow the ConfigSnapshot?
There was a problem hiding this comment.
It's not like it's the only place where we assume that ITransaction is actually Transaction - for example
If/when we need to have other implementations of ITransaction we will revisit it. For example we can introduce TransactionBase and move ConfigSnapshot there.
There was a problem hiding this comment.
I'd consider a pattern matching based on types very different from a hard cast.
But I think we are good here. In #608 I moved this part out from here, so probably we can also get rid of the cast once we merge that.
Context: In #608 I realized that capturing request body here is not a very good thing, because this is a sync method and reading the body synchronously can cause thread starvation. So I'd say let's leave it as is, and in #608 this will evolve.
gregkalapos
left a comment
There was a problem hiding this comment.
Discussed on slack.
I hoped to move some of the unrelated changes out from here, or at least some reaction to those here.
Overall no blocker on this PR, but if possible please try to keep these smaller in the future, otherwise it's very hard to review.
Reviewing a couple of hundred lines can be done in a couple of minutes, but having a 1000+ lines PR with 31 files changing, with lots of moving parts takes significantly longer. Adding some comments and making it as small as possible helps the reviewer a lot.
Closes #534