Skip to content

Commit ec049fe

Browse files
committed
Merge branch '6.x'
2 parents 3b16d8c + db7b84d commit ec049fe

File tree

7 files changed

+126
-10
lines changed

7 files changed

+126
-10
lines changed

CHANGELOG.asciidoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ endif::[]
3434
[[release-notes-6.x]]
3535
=== Python Agent version 6.x
3636
37+
[[release-notes-6.7.2]]
38+
=== 6.7.2 - 2021-12-07
39+
40+
[float]
41+
===== Bug fixes
42+
* fix AttributeError in sync instrumentation of httpx {pull}1423[#1423]
43+
* add setting to disable span compression, default to disabled {pull}1429[#1429]
44+
3745
[[release-notes-6.7.1]]
3846
=== 6.7.1 - 2021-11-29
3947

docs/configuration.asciidoc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,24 @@ To disable stack trace collection for spans completely, set the value to `0`.
691691
Except for the special values `-1` and `0`,
692692
this setting has to be provided in *<<config-format-duration, duration format>>*.
693693

694+
[float]
695+
[[config-span-compression-enabled]]
696+
==== `span_compression_enabled`
697+
698+
<<dynamic-configuration, image:./images/dynamic-config.svg[] >>
699+
700+
[options="header"]
701+
|============
702+
| Environment | Django/Flask | Default
703+
| `ELASTIC_APM_SPAN_COMPRESSION_ENABLED` | `SPAN_COMPRESSION_ENABLED` | `False`
704+
|============
705+
706+
Enable/disable span compression.
707+
708+
If enabled, the agent will compress very short, repeated spans into a single span,
709+
which is beneficial for storage and processing requirements.
710+
Some information is lost in this process, e.g. exact durations of each compressed span.
711+
694712
[float]
695713
[[config-span-compression-exact-match-max_duration]]
696714
==== `span_compression_exact_match_max_duration`

elasticapm/conf/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,14 +580,15 @@ class Config(_ConfigBase):
580580
],
581581
type=int,
582582
)
583+
span_compression_enabled = _BoolConfigValue("SPAN_COMPRESSION_ENABLED", default=False)
583584
span_compression_exact_match_max_duration = _ConfigValue(
584-
"span_compression_exact_match_max_duration",
585+
"SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION",
585586
default=50,
586587
validators=[duration_validator],
587588
type=int,
588589
)
589590
span_compression_same_kind_max_duration = _ConfigValue(
590-
"span_compression_exact_match_max_duration",
591+
"SPAN_COMPRESSION_SAME_KIND_MAX_DURATION",
591592
default=5,
592593
validators=[duration_validator],
593594
type=int,

elasticapm/traces.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,12 @@ def is_exact_match(self, other_span: SpanType) -> bool:
593593
return bool(self.name == other_span.name and self.is_same_kind(other_span))
594594

595595
def is_compression_eligible(self) -> bool:
596-
return self.leaf and not self.dist_tracing_propagated and self.outcome in (None, constants.OUTCOME.SUCCESS)
596+
"""
597+
Determine if this span is eligible for compression.
598+
"""
599+
if self.tracer.config.span_compression_enabled:
600+
return self.leaf and not self.dist_tracing_propagated and self.outcome in (None, constants.OUTCOME.SUCCESS)
601+
return False
597602

598603
@property
599604
def discardable(self) -> bool:

elasticapm/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

31-
__version__ = (6, 7, 1)
31+
__version__ = (6, 7, 2)
3232
VERSION = ".".join(map(str, __version__))

tests/client/span_compression_tests.py

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@
3535

3636
@pytest.mark.parametrize(
3737
"elasticapm_client",
38-
[{"span_compression_same_kind_max_duration": "5ms", "span_compression_exact_match_max_duration": "5ms"}],
38+
[
39+
{
40+
"span_compression_enabled": True,
41+
"span_compression_same_kind_max_duration": "5ms",
42+
"span_compression_exact_match_max_duration": "5ms",
43+
}
44+
],
3945
indirect=True,
4046
)
4147
def test_exact_match(elasticapm_client):
@@ -73,7 +79,13 @@ def test_exact_match(elasticapm_client):
7379

7480
@pytest.mark.parametrize(
7581
"elasticapm_client",
76-
[{"span_compression_same_kind_max_duration": "5ms", "span_compression_exact_match_max_duration": "5ms"}],
82+
[
83+
{
84+
"span_compression_enabled": True,
85+
"span_compression_same_kind_max_duration": "5ms",
86+
"span_compression_exact_match_max_duration": "5ms",
87+
}
88+
],
7789
indirect=True,
7890
)
7991
def test_same_kind(elasticapm_client):
@@ -114,7 +126,13 @@ def test_same_kind(elasticapm_client):
114126

115127
@pytest.mark.parametrize(
116128
"elasticapm_client",
117-
[{"span_compression_same_kind_max_duration": "5ms", "span_compression_exact_match_max_duration": "5ms"}],
129+
[
130+
{
131+
"span_compression_enabled": True,
132+
"span_compression_same_kind_max_duration": "5ms",
133+
"span_compression_exact_match_max_duration": "5ms",
134+
}
135+
],
118136
indirect=True,
119137
)
120138
def test_exact_match_after_same_kind(elasticapm_client):
@@ -162,7 +180,13 @@ def test_exact_match_after_same_kind(elasticapm_client):
162180

163181
@pytest.mark.parametrize(
164182
"elasticapm_client",
165-
[{"span_compression_same_kind_max_duration": "5ms", "span_compression_exact_match_max_duration": "5ms"}],
183+
[
184+
{
185+
"span_compression_enabled": True,
186+
"span_compression_same_kind_max_duration": "5ms",
187+
"span_compression_exact_match_max_duration": "5ms",
188+
}
189+
],
166190
indirect=True,
167191
)
168192
def test_nested_spans(elasticapm_client):
@@ -199,7 +223,13 @@ def test_nested_spans(elasticapm_client):
199223

200224
@pytest.mark.parametrize(
201225
"elasticapm_client",
202-
[{"span_compression_same_kind_max_duration": "5ms", "span_compression_exact_match_max_duration": "5ms"}],
226+
[
227+
{
228+
"span_compression_enabled": True,
229+
"span_compression_same_kind_max_duration": "5ms",
230+
"span_compression_exact_match_max_duration": "5ms",
231+
}
232+
],
203233
indirect=True,
204234
)
205235
def test_buffer_is_reported_if_next_child_ineligible(elasticapm_client):
@@ -224,7 +254,13 @@ def test_buffer_is_reported_if_next_child_ineligible(elasticapm_client):
224254

225255
@pytest.mark.parametrize(
226256
"elasticapm_client",
227-
[{"span_compression_same_kind_max_duration": "5ms", "span_compression_exact_match_max_duration": "5ms"}],
257+
[
258+
{
259+
"span_compression_enabled": True,
260+
"span_compression_same_kind_max_duration": "5ms",
261+
"span_compression_exact_match_max_duration": "5ms",
262+
}
263+
],
228264
indirect=True,
229265
)
230266
def test_compressed_spans_not_counted(elasticapm_client):
@@ -254,3 +290,43 @@ def test_compressed_spans_not_counted(elasticapm_client):
254290
spans = elasticapm_client.events[SPAN]
255291
assert len(spans) == transaction["span_count"]["started"] == 1
256292
assert transaction["span_count"]["dropped"] == 0
293+
294+
295+
@pytest.mark.parametrize(
296+
"elasticapm_client",
297+
[
298+
{
299+
"span_compression_enabled": False,
300+
"span_compression_same_kind_max_duration": "5ms",
301+
"span_compression_exact_match_max_duration": "5ms",
302+
}
303+
],
304+
indirect=True,
305+
)
306+
def test_span_compression_disabled(elasticapm_client):
307+
transaction = elasticapm_client.begin_transaction("test")
308+
with elasticapm.capture_span(
309+
"test",
310+
span_type="a",
311+
span_subtype="b",
312+
span_action="c",
313+
leaf=True,
314+
duration=2,
315+
extra={"destination": {"service": {"resource": "x"}}},
316+
) as span1:
317+
assert not span1.is_compression_eligible()
318+
with elasticapm.capture_span(
319+
"test",
320+
span_type="a",
321+
span_subtype="b",
322+
span_action="c",
323+
leaf=True,
324+
duration=3,
325+
extra={"destination": {"service": {"resource": "x"}}},
326+
) as span2:
327+
assert not span2.is_compression_eligible()
328+
elasticapm_client.end_transaction("test")
329+
spans = elasticapm_client.events[SPAN]
330+
assert len(spans) == 2
331+
span = spans[0]
332+
assert "composite" not in span

tests/config/tests.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,3 +440,11 @@ def test_versioned_config_attribute_access(elasticapm_client):
440440
elasticapm_client.config.update("2", capture_body=True)
441441
val = elasticapm_client.config.start_stop_order
442442
assert isinstance(val, int)
443+
444+
445+
def test_config_all_upper_case():
446+
c = Config.__class__.__dict__.items()
447+
for field, config_value in Config.__dict__.items():
448+
if not isinstance(config_value, _ConfigValue):
449+
continue
450+
assert config_value.env_key == config_value.env_key.upper()

0 commit comments

Comments
 (0)