Skip to content

Cloud metadata#1599

Merged
eyalkoren merged 30 commits intoelastic:masterfrom
eyalkoren:cloud-metadata
Jan 26, 2021
Merged

Cloud metadata#1599
eyalkoren merged 30 commits intoelastic:masterfrom
eyalkoren:cloud-metadata

Conversation

@eyalkoren
Copy link
Contributor

@eyalkoren eyalkoren commented Jan 6, 2021

What does this PR do?

Closes #1264
Extending the work started at #1453

Checklist

  • Spec is implemented
  • Updating CHANGELOG.asciidoc
  • Unit tests for raw metadata deserialization logic
  • Unit tests for metadata serialization logic
  • Unit tests for the new async metadata creation mechanism with all CLOUD_PROVIDER options
  • Added an API method or config option? Document in which version this will be introduced
  • I have made corresponding changes to the documentation
  • manual tests on each cloud with all CLOUD_PROVIDER options
  • manual tests on each cloud with invalid URL or improper input parsing - for future changes in cloud APIs
  • manual test with older APM server
@ghost
Copy link

ghost commented Jan 6, 2021

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview

Expand to view the summary

Build stats

  • Build Cause: Started by user eyalkoren

    • Start Time: 2021-01-26T14:26:53.523+0000
  • Duration: 44 min 30 sec

  • Commit: f6115f3

Test stats 🧪

Test Results
Failed 0
Passed 1697
Skipped 12
Total 1709

💚 Flaky test report

Tests succeeded.

Expand to view the summary

Test stats 🧪

Test Results
Failed 0
Passed 1697
Skipped 12
Total 1709

@codecov-io
Copy link

codecov-io commented Jan 6, 2021

Codecov Report

Merging #1599 (f6115f3) into master (5e6287a) will increase coverage by 0.52%.
The diff coverage is 81.61%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #1599      +/-   ##
============================================
+ Coverage     58.77%   59.30%   +0.52%     
- Complexity       92     3462    +3370     
============================================
  Files           399      403       +4     
  Lines         17864    18239     +375     
  Branches       2475     2512      +37     
============================================
+ Hits          10500    10817     +317     
- Misses         6641     6663      +22     
- Partials        723      759      +36     
Impacted Files Coverage Δ Complexity Δ
.../apm/agent/report/serialize/PayloadSerializer.java 0.00% <0.00%> (ø) 0.00 <0.00> (?)
...a/co/elastic/apm/agent/log/shipper/FileTailer.java 0.00% <0.00%> (ø) 0.00 <0.00> (ø)
...astic/apm/agent/log/shipper/LogShipperFactory.java 0.00% <0.00%> (ø) 0.00 <0.00> (ø)
...co/elastic/apm/agent/log/shipper/TailableFile.java 71.06% <ø> (ø) 47.00 <0.00> (+47.00)
.../elastic/apm/agent/impl/CloudMetadataProvider.java 64.17% <64.17%> (ø) 21.00 <21.00> (?)
...va/co/elastic/apm/agent/impl/ElasticApmTracer.java 66.25% <66.66%> (+0.21%) 81.00 <0.00> (+81.00)
...nt/configuration/ApmServerConfigurationSource.java 76.08% <75.00%> (-1.70%) 22.00 <1.00> (+22.00) ⬇️
.../co/elastic/apm/agent/util/UrlConnectionUtils.java 75.00% <75.00%> (ø) 1.00 <1.00> (?)
.../main/java/co/elastic/apm/agent/impl/MetaData.java 90.47% <87.50%> (-4.53%) 10.00 <2.00> (+10.00) ⬇️
.../java/co/elastic/apm/agent/util/ExecutorUtils.java 71.05% <87.50%> (+10.67%) 8.00 <3.00> (+8.00)
... and 15 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5e6287a...f6115f3. Read the comment docs.

@eyalkoren eyalkoren requested a review from SylvainJuge January 6, 2021 15:28
@eyalkoren eyalkoren marked this pull request as ready for review January 18, 2021 14:20
return null;
}
try {
payloadSerializer.blockUntilReady();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not saying this doesn't work but did you consider providing a Future<MetaData> in the constructor and blocking on Future#get here and call DslJsonSerializer#serializeMetadata(MetaData metaData)? That way, we could keep state management out of the DslJsonSerializer.

Copy link
Contributor Author

@eyalkoren eyalkoren Jan 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, this is how I started, but there were several reasons I changed that: the first is that nobody really needs the metadata object, it is spread around just so it can be handed to serialization. Spreading a Future made even less sense.
In addition, I wanted to create a central serialization for it, meaning that MetaData (or something else) needs to serialize and hold the serialized data. This would mean that MetaData (or something else) now either create and use a PayloadSerializer, or I extract the metadata serialization from the rest, but that proved to be too painful and risky for this PR. Both options looked bad when I tried them, worse then doing it internally within the serializer.
Lastly, blocking during serialization itself doesn't seem right, for example- you better only start the HTTP request when ready to write to it. So I thought it would be better if the serialization interface provides a good indication for that, instead of relying on Future#get (this is not the only usage of it) that each serializer user needs to figure out.

Bottom line - there are many options to do that and I played with several ending with this. Given the multiple dependencies we had on MetaData and the time I wanted to spend on this, this seems as the least ugly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining the background

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] maybe add a small comment why we do that here in the "least ugly" way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind, but I think it is weird to explain why something was chosen over something else you wouldn't necessarily consider as a default option. Imagine you only see this code now for the first time- MetaData can be easily an internal serialization thing not known to the outer world (it is not package private only not to broaden the refactoring of this PR even more). In such case, this is the interface of the serializer- it needs time to fully initialize, no matter why, so users of it should be aware. I made efforts to emphasize this in the API as much as possible, including javadoc and an Exception which is part of the API.

Copy link
Member

@SylvainJuge SylvainJuge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! we can definitely see that having an asynchronous fetching of metadata is not without complications.

return null;
}
try {
payloadSerializer.blockUntilReady();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] maybe add a small comment why we do that here in the "least ugly" way


void writeBytes(byte[] bytes, int len);

class UninitializedException extends Exception {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make this a sub-class of IllegalStateException and not checked exception as it would be thrown only when there is a bug (we didn't waited enough or there was an error), it's not a recoverable error like an IOException .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main purpose of this type is to make anyone calling methods that throws it aware of the requirement for initialization, and the javadoc explains that. I prefer you notice this in compilation and for that it needs to be a checked Exception.

it's not a recoverable

Not sure why - it may affect only the first send/serialization and not the subsequent ones.


@Override
public boolean onLineAvailable(TailableFile tailableFile, byte[] line, int offset, int length, boolean eol) throws IOException {
public boolean onLineAvailable(TailableFile tailableFile, byte[] line, int offset, int length, boolean eol) throws Exception {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] why change to the broad Exception here ? If it's a way to make uses of this API to having to handle potential exceptions, that would be worth to add the the method Javadoc to be explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it felt inappropriate to add UninitializedException (serializer-specific) to the FileChangeListener interface...
Would you prefer that? Or something else?

executor.shutdown();
}

long futureTimeout = queryTimeoutMs + 200;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] why do we add a fixed extra timeout for the future, how do we know that 200ms is fine ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we add a fixed extra timeout for the future

We want to limit this blocking somehow, but if I use the same timeout used for the HTTP query, that would be too tight, it needs to be longer.

how do we know that 200ms is fine ?

We don't know, we live on the edge 😛

@eyalkoren eyalkoren merged commit b9e6d92 into elastic:master Jan 26, 2021
@eyalkoren eyalkoren deleted the cloud-metadata branch January 26, 2021 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

5 participants