Skip to content
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

span (experimental): Compress short exit spans #1134

Merged
merged 24 commits into from
Oct 13, 2021
Merged

span (experimental): Compress short exit spans #1134

merged 24 commits into from
Oct 13, 2021

Conversation

marclop
Copy link
Contributor

@marclop marclop commented Oct 5, 2021

Description

Implements the span compression algorithm described in elastic/apm#432.
The implementation pretty close to what the spec describes, with a few
modifications due to the differences in the Go agent implementation. The
span compression is experimental and is disabled by default with the
default thresholds for the different compression strategies set:

  • ELASTIC_APM_SPAN_COMPRESSION_ENABLED=false
  • ELASTIC_APM_SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION=50ms
  • ELASTIC_APM_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION=5ms

The implementation uses a new field (cache *Span) in TransactionData
and SpanData which is used to cache compressed or compression eligible
spans in that field. An additional composite field has also been added
to the SpanData and TransactionData.

The algorithm states that any exit span that is lower or equal duration
than the set ELASTIC_APM_SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION or
ELASTIC_APM_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION with a destination
service set is compressable into a composite span using the appropriate
strategy. Compressable spans need to be "exit" and siblings which have
not
propagated their context downstream. Sibling spans are spans that
share the same parent span (or transaction).

Spans can be compressed with same_kind or exact_match as a strategy,
and their sum is the aggregated duration of of all
When a compressed span has been compressed into a composite using the
same_kind strategy, its name is mutated to Calls to <span.Type>.

Spans will be compressed into a composite only when the siblings are
consecutive and any compression attempt that doesn't meet that,
will cause the cache to be evicted.

Additionally, two helper functions have been added under the apmtest:
package: WriteTraceTable and WriteTraceWaterfall, which help with
understanding why a test is failing if they are and debugging those.

TODO

  • Changelog
  • Docs

Related issues

Closes #972

Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
@marclop marclop added enhancement New feature or request v7.16.0 labels Oct 5, 2021
@marclop marclop self-assigned this Oct 5, 2021
Signed-off-by: Marc Lopez Rubio <[email protected]>
@apmmachine
Copy link
Contributor

apmmachine commented Oct 5, 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 preview

Expand to view the summary

Build stats

  • Start Time: 2021-10-13T09:52:14.480+0000

  • Duration: 35 min 5 sec

  • Commit: c9d42c2

Test stats 🧪

Test Results
Failed 0
Passed 11425
Skipped 268
Total 11693

🤖 GitHub comments

To re-run your PR in the CI, just comment with:

  • /test : Re-trigger the build.

  • run benchmark tests : Run the benchmark test.

Copy link
Member

@axw axw left a comment

Choose a reason for hiding this comment

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

The approach looks good. I haven't looked at all of the finer details, just left a few initial comments. I'm not entirely convinced by the locking, but again I haven't pored over all the details.

span.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span.go Outdated Show resolved Hide resolved
span.go Outdated Show resolved Hide resolved
Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
Removes the `spanBuffer`, adding a new field to `Transaction` and `Span`
instead and handling the caching directly on that field. `evictCache` is
used to flush the `TransactionData.cache` and `SpanData.cache`

Also simplifies a few functions and uses a `strings.Builder` with the
total capacity set beforehand to update the `span.Name` since that seems
to be the fastest and most efficient way to concatenate the two strings,
the allocation is unavoidable.

Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
@marclop
Copy link
Contributor Author

marclop commented Oct 7, 2021

I'll tidy the tests up a little bit before setting the PR for review, but I believe that the implementation should be complete. I'll update the PR description with the current implementation's details as well.

Signed-off-by: Marc Lopez Rubio <[email protected]>
@marclop marclop marked this pull request as ready for review October 11, 2021 02:37
@marclop marclop requested a review from a team October 11, 2021 02:40
transaction.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
Avoid `s.enqueue` from `s.attemptCompress` function and instead, return
the evicted span from the cache and use the `span.End()` function. A new
bool field has been introduced (in `Span.fromCache`), set to `true` when
the a span has been evicted from the cache. The purpose of this flag is
to avoid reporting the span timers since they've already been reported
on each `span.End`, and to prevent the `span.End()` from going into an
infinite loop, trying to compress a span that has already been evicted.

Also, updates the mutex operations to make all operations concurrently
safe.

Signed-off-by: Marc Lopez Rubio <[email protected]>
@marclop
Copy link
Contributor Author

marclop commented Oct 12, 2021

@axw I should have addressed all your concerns in b86661f. Thank you for the help.

config_test.go Outdated Show resolved Hide resolved
config_test.go Outdated Show resolved Hide resolved
docs/configuration.asciidoc Outdated Show resolved Hide resolved
span.go Outdated Show resolved Hide resolved
span.go Outdated Show resolved Hide resolved
span.go Show resolved Hide resolved
span.go Outdated Show resolved Hide resolved
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Show resolved Hide resolved
span_compressed.go Show resolved Hide resolved
Adds a new `s.compressOrEvictCache`, and simplifies `s.attemptCompress`.
The new method compresses or evicts the span into / from the cache.

Also modifies the `s.evict()` to set the cached span compression options
to `false` so the span doesn't go through the compression flow again and
causes infinite loop.

Last, it splits the compression and enqueuing portion of `s.End()` into
a new `s.end()` method which is called only for spans that have been
evicted from the cache.

Signed-off-by: Marc Lopez Rubio <[email protected]>
Signed-off-by: Marc Lopez Rubio <[email protected]>
span_compressed.go Outdated Show resolved Hide resolved
span_compressed.go Show resolved Hide resolved
Signed-off-by: Marc Lopez Rubio <[email protected]>
Copy link
Member

@axw axw left a comment

Choose a reason for hiding this comment

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

LGTM. Nice work!

@marclop marclop merged commit 27abca2 into elastic:master Oct 13, 2021
@marclop marclop deleted the f/add-span-compression-feature branch October 13, 2021 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[META 432] Implement compressed spans algorithm
3 participants