Skip to content

Use Sampler to determine whether to fill stack trace #2111

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

Merged
merged 12 commits into from
Sep 25, 2019

Conversation

trustin
Copy link
Member

@trustin trustin commented Sep 25, 2019

Motivation:

Flags.verboseExceptions() gives a user only two choices - enabling
stacktrace for all exceptions or not. We could let a user take
trade-offs by allowing him or her to specify a Sampler specification.

Modifications:

  • Accept a Sampler specification string as a value of the
    com.linecorp.armeria.verboseExceptions system property.
    • Use the default specification of rate-limited=10, which allows 10
      traces per second per exception type.
    • Note that true and false are translated into always and
      never.
  • Add ExceptionSampler
  • Replace Flags.verboseExceptions() with verboseExceptionSampler()
    and verboseExceptionSamplerSpec()
  • The exceptions which never had stack traces can now have stack trace.
  • Add a benchmark

Result:

  • A user will get the stack trace for some exceptions out of the box,
    which is a better experience.
    • Previously, a user had to set true to the flag manually.
  • A user can trade-off between the cost of filling in stack trace and
    the debuggability in a fine-grained manner.

Benchmark result:

Benchmark                                              Mode  Cnt          Score          Error  Units
ExceptionSamplerBenchmark.baseline_singleton          thrpt    5  115913078.321 ±  2470676.668  ops/s
ExceptionSamplerBenchmark.baseline_withStackTrace     thrpt    5     435184.216 ±    68777.567  ops/s
ExceptionSamplerBenchmark.baseline_withoutStackTrace  thrpt    5   51507410.813 ±  4643400.389  ops/s
ExceptionSamplerBenchmark.sampler_always              thrpt    5     460633.461 ±    23792.691  ops/s
ExceptionSamplerBenchmark.sampler_never               thrpt    5   65191830.351 ± 10603815.026  ops/s
ExceptionSamplerBenchmark.sampler_random_1            thrpt    5   22901381.973 ±   992182.987  ops/s
ExceptionSamplerBenchmark.sampler_random_10           thrpt    5    4131608.570 ±    62347.977  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_1       thrpt    5   16322277.831 ±   591082.048  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_10      thrpt    5   15205268.392 ±   339038.406  ops/s

Motivation:

`Flags.verboseExceptions()` gives a user only two choices - enabling
stacktrace for all exceptions or not. We could let a user take
trade-offs by allowing him or her to specify a `Sampler` specification.

Modifications:

- Accept a `Sampler` specification string as a value of the
  `com.linecorp.armeria.verboseExceptions` system property.
  - Use the default specification of `rate-limited=1`, which allows one
    trace per second per exception type.
  - Note that `true` and `false` are translated into `always` and
    `never`.
- Add `ExceptionSampler`
- Replace Flags.verboseExceptions()` with `verboseExceptionSampler()`
  and `verboseExceptionSamplerSpec()`
- Add a benchmark

Result:

- A user will get the stack trace for some exceptions out of the box,
  which is a better experience.
  - Previously, a user had to set `true` to the flag manually.
- A user can trade-off between the cost of filling in stack trace and
  the debuggability in a fine-grained manner.

Benchmark result:

```
Benchmark                                              Mode  Cnt          Score          Error  Units
ExceptionSamplerBenchmark.baseline_singleton          thrpt    5  113645503.499 ±  4733673.802  ops/s
ExceptionSamplerBenchmark.baseline_withStackTrace     thrpt    5     415370.775 ±   117032.077  ops/s
ExceptionSamplerBenchmark.baseline_withoutStackTrace  thrpt    5   50683298.670 ±  8876147.874  ops/s
ExceptionSamplerBenchmark.sampler_always              thrpt    5     423056.060 ±    81934.927  ops/s
ExceptionSamplerBenchmark.sampler_never               thrpt    5   67165540.355 ± 13892391.328  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited         thrpt    5   15781563.939 ±  1037630.515  ops/s
```
@trustin trustin added this to the 0.93.0 milestone Sep 25, 2019
@trustin
Copy link
Member Author

trustin commented Sep 25, 2019

@adriancole You might find this interesting.

@minwoox
Copy link
Contributor

minwoox commented Sep 25, 2019

What is the rate that you used in the benchmark test?
Ah I found that it's 1 for second. Thanks!

private final String spec;

ExceptionSampler(String spec) {
samplerFactory = unused -> Sampler.of(spec);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any chance that a user wants to set different specs for different exceptions?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure. Perhaps we can consider that when someone asks for it? 😉

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a comment about this idea to Flags

}

@Override
public boolean isSampled(Class<? extends Throwable> exceptionType) {
Copy link
Contributor

Choose a reason for hiding this comment

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

so the rationale for the type parameter is solving the overhead problem caused by allocating an exception, correct?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, kind of. If we accepted a Throwable, we will see a chicken and egg problem. 😄

Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

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

Nice work! 👍

@trustin
Copy link
Member Author

trustin commented Sep 25, 2019

sampler_rateLimited_10 was tainted by wrong input. Here's the correct one:

Benchmark                                              Mode  Cnt          Score          Error  Units
ExceptionSamplerBenchmark.baseline_singleton          thrpt    5  115913078.321 ±  2470676.668  ops/s
ExceptionSamplerBenchmark.baseline_withStackTrace     thrpt    5     435184.216 ±    68777.567  ops/s
ExceptionSamplerBenchmark.baseline_withoutStackTrace  thrpt    5   51507410.813 ±  4643400.389  ops/s
ExceptionSamplerBenchmark.sampler_always              thrpt    5     460633.461 ±    23792.691  ops/s
ExceptionSamplerBenchmark.sampler_never               thrpt    5   65191830.351 ± 10603815.026  ops/s
ExceptionSamplerBenchmark.sampler_random_1            thrpt    5   22901381.973 ±   992182.987  ops/s
ExceptionSamplerBenchmark.sampler_random_10           thrpt    5    4131608.570 ±    62347.977  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_1       thrpt    5   16322277.831 ±   591082.048  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_10      thrpt    5   15205268.392 ±   339038.406  ops/s

Copy link
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

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

👍

@codecov
Copy link

codecov bot commented Sep 25, 2019

Codecov Report

Merging #2111 into master will decrease coverage by 0.08%.
The diff coverage is 41.66%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #2111      +/-   ##
============================================
- Coverage     73.78%   73.69%   -0.09%     
+ Complexity     9491     9488       -3     
============================================
  Files           833      834       +1     
  Lines         36545    36585      +40     
  Branches       4525     4527       +2     
============================================
- Hits          26964    26963       -1     
- Misses         7253     7292      +39     
- Partials       2328     2330       +2
Impacted Files Coverage Δ Complexity Δ
...a/common/grpc/protocol/ArmeriaStatusException.java 100% <ø> (ø) 3 <0> (ø) ⬇️
...a/com/linecorp/armeria/common/util/Exceptions.java 39.47% <ø> (+0.34%) 25 <0> (ø) ⬇️
.../com/linecorp/armeria/common/TimeoutException.java 33.33% <ø> (+13.33%) 2 <0> (+1) ⬆️
...orp/armeria/common/ProtocolViolationException.java 33.33% <0%> (ø) 2 <1> (ø) ⬇️
...om/linecorp/armeria/server/saml/SamlException.java 0% <0%> (ø) 0 <0> (ø) ⬇️
...inecorp/armeria/client/RefusedStreamException.java 0% <0%> (ø) 0 <0> (ø) ⬇️
...m/linecorp/armeria/server/HttpStatusException.java 57.89% <0%> (ø) 6 <0> (ø) ⬇️
.../com/linecorp/armeria/common/ExceptionSampler.java 0% <0%> (ø) 0 <0> (?)
...rp/armeria/client/UnprocessedRequestException.java 62.5% <0%> (ø) 3 <1> (ø) ⬇️
...linecorp/armeria/server/HttpResponseException.java 75% <0%> (ø) 6 <1> (ø) ⬇️
... and 32 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 0e8f016...aabbf96. Read the comment docs.

@@ -23,7 +23,7 @@
*/
public class ArmeriaStatusException extends RuntimeException {

public static final long serialVersionUID = -8370257107063108923L;
private static final long serialVersionUID = -8370257107063108923L;
Copy link
Contributor

Choose a reason for hiding this comment

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

😱

@minwoox
Copy link
Contributor

minwoox commented Sep 25, 2019

still LGTM 👍

@@ -95,16 +95,19 @@

switch (spec) {
case "true":
case "always":
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@trustin trustin merged commit 63b9e42 into line:master Sep 25, 2019
@trustin trustin deleted the exception_sampling branch September 25, 2019 10:56
eugene70 pushed a commit to eugene70/armeria that referenced this pull request Oct 16, 2019
Motivation:

`Flags.verboseExceptions()` gives a user only two choices - enabling
stacktrace for all exceptions or not. We could let a user take
trade-offs by allowing him or her to specify a `Sampler` specification.

Modifications:

- Accept a `Sampler` specification string as a value of the
  `com.linecorp.armeria.verboseExceptions` system property.
  - Use the default specification of `rate-limited=10`, which allows 10
    traces per second per exception type.
  - Note that `true` and `false` are translated into `always` and
    `never`.
- Add `ExceptionSampler`
- Replace `Flags.verboseExceptions()` with `verboseExceptionSampler()`
  and `verboseExceptionSamplerSpec()`
- The exceptions which never had stack traces can now have stack trace.
- Add a benchmark

Result:

- A user will get the stack trace for some exceptions out of the box,
  which is a better experience.
  - Previously, a user had to set `true` to the flag manually.
- A user can trade-off between the cost of filling in stack trace and
  the debuggability in a fine-grained manner.

Benchmark result:

```
Benchmark                                              Mode  Cnt          Score          Error  Units
ExceptionSamplerBenchmark.baseline_singleton          thrpt    5  115913078.321 ±  2470676.668  ops/s
ExceptionSamplerBenchmark.baseline_withStackTrace     thrpt    5     435184.216 ±    68777.567  ops/s
ExceptionSamplerBenchmark.baseline_withoutStackTrace  thrpt    5   51507410.813 ±  4643400.389  ops/s
ExceptionSamplerBenchmark.sampler_always              thrpt    5     460633.461 ±    23792.691  ops/s
ExceptionSamplerBenchmark.sampler_never               thrpt    5   65191830.351 ± 10603815.026  ops/s
ExceptionSamplerBenchmark.sampler_random_1            thrpt    5   22901381.973 ±   992182.987  ops/s
ExceptionSamplerBenchmark.sampler_random_10           thrpt    5    4131608.570 ±    62347.977  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_1       thrpt    5   16322277.831 ±   591082.048  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_10      thrpt    5   15205268.392 ±   339038.406  ops/s
```
fmguerreiro pushed a commit to fmguerreiro/armeria that referenced this pull request Sep 19, 2020
Motivation:

`Flags.verboseExceptions()` gives a user only two choices - enabling
stacktrace for all exceptions or not. We could let a user take
trade-offs by allowing him or her to specify a `Sampler` specification.

Modifications:

- Accept a `Sampler` specification string as a value of the
  `com.linecorp.armeria.verboseExceptions` system property.
  - Use the default specification of `rate-limited=10`, which allows 10
    traces per second per exception type.
  - Note that `true` and `false` are translated into `always` and
    `never`.
- Add `ExceptionSampler`
- Replace `Flags.verboseExceptions()` with `verboseExceptionSampler()`
  and `verboseExceptionSamplerSpec()`
- The exceptions which never had stack traces can now have stack trace.
- Add a benchmark

Result:

- A user will get the stack trace for some exceptions out of the box,
  which is a better experience.
  - Previously, a user had to set `true` to the flag manually.
- A user can trade-off between the cost of filling in stack trace and
  the debuggability in a fine-grained manner.

Benchmark result:

```
Benchmark                                              Mode  Cnt          Score          Error  Units
ExceptionSamplerBenchmark.baseline_singleton          thrpt    5  115913078.321 ±  2470676.668  ops/s
ExceptionSamplerBenchmark.baseline_withStackTrace     thrpt    5     435184.216 ±    68777.567  ops/s
ExceptionSamplerBenchmark.baseline_withoutStackTrace  thrpt    5   51507410.813 ±  4643400.389  ops/s
ExceptionSamplerBenchmark.sampler_always              thrpt    5     460633.461 ±    23792.691  ops/s
ExceptionSamplerBenchmark.sampler_never               thrpt    5   65191830.351 ± 10603815.026  ops/s
ExceptionSamplerBenchmark.sampler_random_1            thrpt    5   22901381.973 ±   992182.987  ops/s
ExceptionSamplerBenchmark.sampler_random_10           thrpt    5    4131608.570 ±    62347.977  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_1       thrpt    5   16322277.831 ±   591082.048  ops/s
ExceptionSamplerBenchmark.sampler_rateLimited_10      thrpt    5   15205268.392 ±   339038.406  ops/s
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants