Skip to content

fix: Truncate large table samples in Teams alerts to prevent payload size issues#2104

Closed
RamiNoodle733 wants to merge 1 commit intoelementary-data:masterfrom
RamiNoodle733:fix/teams-payload-size-2044
Closed

fix: Truncate large table samples in Teams alerts to prevent payload size issues#2104
RamiNoodle733 wants to merge 1 commit intoelementary-data:masterfrom
RamiNoodle733:fix/teams-payload-size-2044

Conversation

@RamiNoodle733
Copy link

@RamiNoodle733 RamiNoodle733 commented Feb 6, 2026

Description

This PR fixes issue #2044 where Teams alerts fail when the payload is too large (typically when there are >25 rows with multiple columns in test result samples).

Changes

  • Added new maximum_rows_in_alert_samples_table config parameter (default: 25)
  • Added table truncation logic in _get_result_blocks() that:
    • Limits table rows to the configured maximum
    • Adds a message indicating how many rows were omitted
  • Added CLI option --maximum-rows-in-alert-samples-table (-mr) to customize the limit
  • Updated Config class to handle the new parameter
  • Updated DataMonitoringAlerts to pass the config to AlertMessageBuilder

How it works

When test result samples exceed the row limit:

  1. The table is truncated to the first N rows (default 25)
  2. A message is added below the table: "... and X more rows (truncated to prevent payload size issues)"
  3. The alert is sent successfully without hitting Teams' payload limits

Testing

Added tests for:

  • Large tables (>25 rows) being truncated
  • Small tables (<25 rows) not being affected
  • Edge case of exactly 25 rows (no truncation message)
  • Config and MessageBuilderConfig integration

Fixes #2044

Summary by CodeRabbit

New Features

  • Added ability to limit the number of rows displayed in alert sample tables to prevent excessively large payloads. Configurable via new CLI option with a default limit of 25 rows. When the limit is exceeded, tables are truncated with a note indicating additional row count.

…size issues (#2044)

When sending alerts to Microsoft Teams with large test result samples
(>25 rows with multiple columns), the payload exceeds Teams' limits
and gets rejected. This fix adds:

- New maximum_rows_in_alert_samples_table config parameter (default: 25)
- Table truncation logic that limits rows and adds a message about omitted rows
- CLI option --maximum-rows-in-alert-samples-table (-mr) to customize the limit

Fixes #2044
@github-actions
Copy link
Contributor

github-actions bot commented Feb 6, 2026

👋 @RamiNoodle733
Thank you for raising your pull request.
Please make sure to add tests and document all user-facing changes.
You can do this by editing the docs files in this pull request.

@coderabbitai
Copy link

coderabbitai bot commented Feb 6, 2026

📝 Walkthrough

Walkthrough

This change introduces a new configuration parameter maximum_rows_in_alert_samples_table (default 25) to limit the number of rows displayed in alert sample tables. The parameter is propagated through the configuration system, CLI, and alerting pipeline, with truncation logic applied in the message builder to prevent oversized payloads.

Changes

Cohort / File(s) Summary
Configuration Parameter Addition
elementary/config/config.py, elementary/monitor/data_monitoring/alerts/data_monitoring_alerts.py
Adds new optional maximum_rows_in_alert_samples_table parameter to Config class with default value of 25, then passes it to AlertMessageBuilder configuration.
CLI Integration
elementary/monitor/cli.py
Introduces new CLI option --maximum-rows-in-alert-samples-table (-mr) and threads it through the monitor command to pass into Config construction and DataMonitoringAlerts initialization.
Alert Message Truncation Logic
elementary/monitor/alerts/alert_messages/builder.py
Adds maximum_rows_in_alert_samples_table field to MessageBuilderConfig and implements conditional row truncation in _get_result_blocks: when table rows exceed the limit, truncates to the maximum and appends an italicized note indicating omitted rows.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A limit on rows, oh what a delight!
No more giant payloads that give Teams a fright
Just twenty-five samples, then snip goes the thread
With a note: "more rows here!" the alert gently said
Payload size tamed, by this config-y breed! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses core requirements from #2044 by truncating large table samples with a configurable threshold and providing user feedback, but lacks warning logging and comprehensive error handling for Teams webhook failures. Implement warning/notice logging when truncation occurs and add graceful handling with meaningful error logs for Teams webhook failures as specified in #2044 requirements.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding truncation for large table samples in Teams alerts to prevent payload size issues.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing table truncation for alert samples and configuring the maximum row limit across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@elementary/monitor/alerts/alert_messages/builder.py`:
- Around line 398-417: Guard against non-positive
maximum_rows_in_alert_samples_table by normalizing it before truncation: compute
a safe_max = max(1, self.config.maximum_rows_in_alert_samples_table) (or treat
<=0 as "no truncation" by using safe_max = None and skipping truncation), then
use safe_max when slicing result_sample and when computing omitted_rows_count =
max(0, len(result_sample) - safe_max); update the truncation branch that uses
result_sample[:self.config.maximum_rows_in_alert_samples_table],
omitted_rows_count, TableBlock.from_dicts, LinesBlock and ItalicTextLineBlock to
reference safe_max so you never produce an empty table or negative
omitted_rows_count for 0/negative config values.
🧹 Nitpick comments (1)
elementary/monitor/alerts/alert_messages/builder.py (1)

398-413: No observability when truncation occurs.

The PR objectives call for logging a warning when truncation happens. Currently, no log message is emitted. Consider adding a logger.info or logger.warning call when rows are truncated, so operators can identify which alerts were modified. This would require importing a logger into this module if one isn't already available.

Comment on lines +398 to +417
# Truncate table if too many rows to prevent Teams payload size issues
if len(result_sample) > self.config.maximum_rows_in_alert_samples_table:
truncated_sample = result_sample[:self.config.maximum_rows_in_alert_samples_table]
omitted_rows_count = len(result_sample) - self.config.maximum_rows_in_alert_samples_table
result_blocks.append(
TableBlock.from_dicts(truncated_sample),
)
result_blocks.append(
LinesBlock(
lines=[
ItalicTextLineBlock(
text=f"... and {omitted_rows_count} more rows (truncated to prevent payload size issues)"
),
]
)
)
else:
result_blocks.append(
TableBlock.from_dicts(result_sample),
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider guarding against non-positive maximum_rows_in_alert_samples_table values.

The truncation logic works correctly for positive values. However, if a user passes 0 or a negative value via CLI (e.g., --maximum-rows-in-alert-samples-table 0), the behavior degrades:

  • 0: result_sample[:0] → empty table, with a message saying "and N more rows" for all rows.
  • Negative: result_sample[-k:] silently drops rows from the start instead of limiting from the end, and omitted_rows_count becomes negative, producing a nonsensical message like "... and -5 more rows".

A simple guard (either in the config or here) would prevent this.

Proposed fix (in config or CLI layer)

Option A — Validate at the config level in config.py:

         self.maximum_rows_in_alert_samples_table = self._first_not_none(
             maximum_rows_in_alert_samples_table,
             config.get("maximum_rows_in_alert_samples_table"),
             25,
         )
+        if self.maximum_rows_in_alert_samples_table is not None and self.maximum_rows_in_alert_samples_table < 1:
+            raise InvalidArgumentsError(
+                "maximum_rows_in_alert_samples_table must be a positive integer."
+            )

Option B — Add a min constraint in the CLI option:

 `@click.option`(
     "--maximum-rows-in-alert-samples-table",
     "-mr",
     type=int,
     default=25,
+    callback=lambda ctx, param, value: value if value >= 1 else ctx.fail("must be >= 1"),
     help="Maximum number of rows to display in a table in alert samples.",
 )
🤖 Prompt for AI Agents
In `@elementary/monitor/alerts/alert_messages/builder.py` around lines 398 - 417,
Guard against non-positive maximum_rows_in_alert_samples_table by normalizing it
before truncation: compute a safe_max = max(1,
self.config.maximum_rows_in_alert_samples_table) (or treat <=0 as "no
truncation" by using safe_max = None and skipping truncation), then use safe_max
when slicing result_sample and when computing omitted_rows_count = max(0,
len(result_sample) - safe_max); update the truncation branch that uses
result_sample[:self.config.maximum_rows_in_alert_samples_table],
omitted_rows_count, TableBlock.from_dicts, LinesBlock and ItalicTextLineBlock to
reference safe_max so you never produce an empty table or negative
omitted_rows_count for 0/negative config values.

@RamiNoodle733 RamiNoodle733 closed this by deleting the head repository Feb 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] prevent too big payload in edr monitor that will be rejected by Teams

1 participant