-
Notifications
You must be signed in to change notification settings - Fork 304
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
HPCC-32465 Add ESP support for trace level #19246
HPCC-32465 Add ESP support for trace level #19246
Conversation
Jira Issue: https://hpccsystems.atlassian.net//browse/HPCC-32465 Jirabot Action Result: |
@ghalliday you'll notice I've defined my own version of loadTraceFlags for the ESP. I opened https://hpccsystems.atlassian.net/browse/HPCC-32477 to potentially change the jlib implementation. This PR implements the change that Jira suggests. Also, #19007 is a draft that is stacked on top of this, if you want to see a bigger example of this change in use. |
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.
@timothyklemm The change makes sense, but better would be to enhance the existing loadTraceFlags with a consistent super-set of the functionality. A few other comments on the code as it stands.
void copyTraceFlags(IPropertyTree *legacyEsp, IPropertyTree *appEsp) | ||
{ | ||
IPropertyTree *traceFlags = appEsp->queryPropTree(propTraceFlags); | ||
if (traceFlags) |
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.
minor: Possibly simpler as
if (traceFlags)
legacyEsp->setPropTree(propTraceFlags, LINK(match));
(This copyTree function should be moved to jptree.hpp...)
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.
WIll do.
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 simplification of this method is straightforward. Adding a function to jptree ks less so. This function, making assumptions about source and target nodes, is too specialized to belong in jlib. My first thought for generalizing it involves target node, source node, and source path, with the copied node always added as a child of the target. This might not be general enough, if someone might want to specify a target path as well.
If a generalized copy function should be part of this PR, what would your expectation be for its interface/behavior?
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 is an existing copyTree function that is clone in workunit.cpp and espp.cpp. It would make sense for this to be migrated into jptree, and for this function to make use of it. Not for this PR though.
esp/platform/espp.cpp
Outdated
{ | ||
VStringBuffer attrName("@%s", option.name); | ||
const char* value = nullptr; | ||
if (!(value = ptree->queryProp(attrName))) |
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.
style: We generally avoid assignments inside if statements - they are hard to read.
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.
Will change.
esp/platform/espp.cpp
Outdated
else // Boolean trace options | ||
{ | ||
bool flag = false; | ||
deserializer(value, flag); |
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.
minor: Code elsewhere would use strToBool(value). Does the deserializer provide other benefits?
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 already had the deserializer for integral trace levels. Just reused it for consistency in the method. Moving logic out to jlib might make the deserializer unpalatable in both cases since its definition is in an ESP header.
esp/platform/espp.cpp
Outdated
{ | ||
unsigned level = unsigned(dft & TraceFlags::LevelMask); | ||
dft &= ~TraceFlags::LevelMask; | ||
if (streq(value, "traceStandard")) |
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.
tracelevel=standard
would be more intuitive than
tracelevel=traceStandard
also, case insensitive comparison would be more user friendly.
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.
Agree.
esp/platform/esptrace.h
Outdated
// ESP process names for use with options mapping | ||
constexpr const char* eclwatchApplication = "eclwatch"; | ||
constexpr const char* eclservicesApplication = "eclservices"; | ||
constexpr const char* eclqueriesApplication = "eclqueires"; |
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.
Unused, and has a typo in the string.
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 suppose the definitions are premature. I defined them so mapTraceOptions will eventually be able to use different option lists for distinct ESPs. Not sure how many new options will be defined for most platform ESPs, but I have a lot in mind for esdl and esdl-sandbox (when/if we return focus to DESDL) that might also extend into loggingservice.
Are you asking for removal until needed, or is fixing the type sufficient?
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 don't mind, probably cleaner to remove.
The danger with adding constants or other items that are not actually used, is that when they come to be used they are not checked, because they are assumed to be correct because they are already checked in, but equally there is a danger that items that are not used aren't checked as carefully when they are merged.
esp/platform/esptrace.h
Outdated
constexpr const char* loggingserviceApplication = "loggingservice"; | ||
|
||
// Trace options for ESP | ||
constexpr TraceFlags traceLevel = TraceFlags::LevelMask; |
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 looks is confusing. Why have a constant called traceLevel which is actually a bit mask? It is likely to lead to confusion if there was code which said
if (traceLevel == ....)
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.
Given my use of TRACEOPT, which is its own issue, I needed a flag named traceLevel
to build the option. I assigned the mask instead of an individual level hoping it would be clear that the property wasn't tied to that single value. Avoiding TRACEOPT makes this unnecessary.
esp/platform/esptrace.h
Outdated
// Trace option list fragment for options used by most ESPs | ||
#define ESP_OPTIONS_FRAGMENT \ | ||
PLATFORM_OPTIONS_FRAGMENT \ | ||
TRACEOPT(traceLevel), |
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 think what you actually want to do is no use TRACEOPT, but use
{ "traceLevel", traceNone },
if you want to support traceLevel.
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.
Will change.
esp/platform/espp.cpp
Outdated
} | ||
if (streq(value, "default")) // allow a configuration to explicitly request a default value | ||
continue; | ||
if (streq(option.name, propTraceLevel)) // non-Boolean traceLevel |
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 logic makes sense, but would probably make more sense added to loadTraceFlags.
I would add add an extra enumeration traceDetail[Level?] = 0xffffffff, and check that value with this processing:
if (option.value == traceDetail)...
(I am suggesting traceDetail rather than traceLevel to avoid clashes with the existing traceLevel option which has different ranges of values?)
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.
Agree on loadTraceFlags. With multiple comments here, suggest we fix this here, then it will be easy to lift and shift into jlib.
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 don't understand your intent for traceDetail. Would it replace the string comparison on the name, or would it be in addition to that?
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.
It would replace the comparison on the name.
esp/platform/espp.cpp
Outdated
else if (streq(value, "traceMax")) | ||
dft |= traceMax; | ||
else if (deserializer(value, level) == Deserialization_SUCCESS) | ||
dft |= TraceFlags(level) & TraceFlags::LevelMask; |
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.
minor: range checking on level - this could be used to set any of the other flags as well. I suspect that should be blocked.
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 don't think it will set any other flags given the application of the level mask, but it does contradict the README which states that all other values are equivalent to traceNone. Will add a range check, and remove the following else block that also contradicts the README by treating all other values as "default".
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.
You are correct, I missed the level mask.
@timothyklemm I only read your comment about the related PR afterwards. I agree, and suggest you make the changes in the lib function. |
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.
@ghalliday I'm clear on most of your feedback, but I do have a couple questions.
esp/platform/esptrace.h
Outdated
constexpr const char* loggingserviceApplication = "loggingservice"; | ||
|
||
// Trace options for ESP | ||
constexpr TraceFlags traceLevel = TraceFlags::LevelMask; |
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.
Given my use of TRACEOPT, which is its own issue, I needed a flag named traceLevel
to build the option. I assigned the mask instead of an individual level hoping it would be clear that the property wasn't tied to that single value. Avoiding TRACEOPT makes this unnecessary.
esp/platform/espp.cpp
Outdated
else // Boolean trace options | ||
{ | ||
bool flag = false; | ||
deserializer(value, flag); |
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 already had the deserializer for integral trace levels. Just reused it for consistency in the method. Moving logic out to jlib might make the deserializer unpalatable in both cases since its definition is in an ESP header.
esp/platform/espp.cpp
Outdated
else if (streq(value, "traceMax")) | ||
dft |= traceMax; | ||
else if (deserializer(value, level) == Deserialization_SUCCESS) | ||
dft |= TraceFlags(level) & TraceFlags::LevelMask; |
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 don't think it will set any other flags given the application of the level mask, but it does contradict the README which states that all other values are equivalent to traceNone. Will add a range check, and remove the following else block that also contradicts the README by treating all other values as "default".
esp/platform/espp.cpp
Outdated
{ | ||
unsigned level = unsigned(dft & TraceFlags::LevelMask); | ||
dft &= ~TraceFlags::LevelMask; | ||
if (streq(value, "traceStandard")) |
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.
Agree.
esp/platform/espp.cpp
Outdated
} | ||
if (streq(value, "default")) // allow a configuration to explicitly request a default value | ||
continue; | ||
if (streq(option.name, propTraceLevel)) // non-Boolean traceLevel |
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.
Agree on loadTraceFlags. With multiple comments here, suggest we fix this here, then it will be easy to lift and shift into jlib.
esp/platform/espp.cpp
Outdated
} | ||
if (streq(value, "default")) // allow a configuration to explicitly request a default value | ||
continue; | ||
if (streq(option.name, propTraceLevel)) // non-Boolean traceLevel |
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 don't understand your intent for traceDetail. Would it replace the string comparison on the name, or would it be in addition to that?
esp/platform/espp.cpp
Outdated
{ | ||
VStringBuffer attrName("@%s", option.name); | ||
const char* value = nullptr; | ||
if (!(value = ptree->queryProp(attrName))) |
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.
Will change.
esp/platform/esptrace.h
Outdated
// Trace option list fragment for options used by most ESPs | ||
#define ESP_OPTIONS_FRAGMENT \ | ||
PLATFORM_OPTIONS_FRAGMENT \ | ||
TRACEOPT(traceLevel), |
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.
Will change.
esp/platform/esptrace.h
Outdated
// ESP process names for use with options mapping | ||
constexpr const char* eclwatchApplication = "eclwatch"; | ||
constexpr const char* eclservicesApplication = "eclservices"; | ||
constexpr const char* eclqueriesApplication = "eclqueires"; |
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 suppose the definitions are premature. I defined them so mapTraceOptions will eventually be able to use different option lists for distinct ESPs. Not sure how many new options will be defined for most platform ESPs, but I have a lot in mind for esdl and esdl-sandbox (when/if we return focus to DESDL) that might also extend into loggingservice.
Are you asking for removal until needed, or is fixing the type sufficient?
void copyTraceFlags(IPropertyTree *legacyEsp, IPropertyTree *appEsp) | ||
{ | ||
IPropertyTree *traceFlags = appEsp->queryPropTree(propTraceFlags); | ||
if (traceFlags) |
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.
WIll do.
227fd45
to
8a615da
Compare
@ghalliday I've updated based on your earlier comments. Not sure what to make of the failing test... both GitHub and VS Code handle the internal link that the test claims to be invalid as expected. |
@AttilaVamos please can you look at the broken link report. It is from a relative path. Is this a problem with the hyper-link checking? |
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.
Looks good. I think it is worth replacing/updating the loadTraceFlags function with this enhanced version.
void copyTraceFlags(IPropertyTree *legacyEsp, IPropertyTree *appEsp) | ||
{ | ||
IPropertyTree *traceFlags = appEsp->queryPropTree(propTraceFlags); | ||
if (traceFlags) |
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 is an existing copyTree function that is clone in workunit.cpp and espp.cpp. It would make sense for this to be migrated into jptree, and for this function to make use of it. Not for this PR though.
esp/platform/espp.cpp
Outdated
char* endptr = nullptr; | ||
unsigned tmp = strtoul(value, &endptr, 10); | ||
if (endptr && !*endptr && TraceFlags(tmp) <= TraceFlags::LevelMask) | ||
dft |= TraceFlags(tmp) & TraceFlags::LevelMask; |
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.
trivial: no need for the mask any more, now the assign is protected.
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.
Looks good. Please squash and I will merge.
67ec81a
to
7e44732
Compare
@ghalliday it's squashed. |
@timothyklemm is the first commit required? Please can you separate that out into a separate PR - I would have some related comments that are unrelated to the tracing flags. |
Oops. There already is a separate PR for the first commit. The two commits are unrelated but combine to form the base for the latest version of the security manager decorator. I forgot to unstack them. |
7e44732
to
caa4517
Compare
@ghalliday now decoupled from the unrelated commit. |
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.
@timothyklemm one issue spotted on final review.
esp/platform/application_config.cpp
Outdated
{ | ||
IPropertyTree *traceFlags = appEsp->queryPropTree(propTraceFlags); | ||
if (traceFlags) | ||
legacyEsp->setPropTree(propTraceFlags, traceFlags); |
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 missing a LINK(). I think it is likely to cause a crash when esp terminates.
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.
Agreed.
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.
@ghalliday made and squashed the one line change.
- Define an ESP process configuration node that supports specification of global TraceFlags values for each ESP. - Reserve traceDetail to request a specific trace level (0: none, 1: standard, 2: detailed, 3: max). This replaces acting on the last observed occurrence of either traceNone, traceStandard, traceDetailed, and traceMax. - Override default flag settings when not configured and a debug build. Signed-off-by: Tim Klemm <tim.klemm@lexisnexisrisk.com>
caa4517
to
2ad17a1
Compare
Jira Issue: https://hpccsystems.atlassian.net//browse/HPCC-32465 Jirabot Action Result: |
Jira Issue: https://hpccsystems.atlassian.net//browse/HPCC-32465 Jirabot Action Result: |
Close and reopened to force all tests to be rerun (to check failures really are false positives) |
Jirabot Action Result: |
Type of change:
Checklist:
Smoketest:
Testing: