feat(weekly-report): Add Total Spans header to weekly report#119787
Draft
amy-chen23 wants to merge 6 commits into
Draft
feat(weekly-report): Add Total Spans header to weekly report#119787amy-chen23 wants to merge 6 commits into
amy-chen23 wants to merge 6 commits into
Conversation
Span names containing backslashes could produce malformed search filters because only double-quote escaping was applied. Escape backslashes first, matching the pattern used by _escape_search_query_value in the EAP search module. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Add a Total Spans section showing the aggregate span count with a View All Spans link. The count is filtered by user project access and gated behind the weekly-report-spans-chart feature flag. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Comment on lines
+741
to
+787
| for row in result.get("data", []): | ||
| span_name = row.get("span.name", "") | ||
| if not span_name: | ||
| continue | ||
| count = row.get("count()", 0) | ||
| ctx.top_spans.append( | ||
| { | ||
| "name": span_name, | ||
| "p95": row.get("p95(span.duration)", 0), | ||
| "sum": row.get("sum(span.duration)", 0), | ||
| "count": count, | ||
| } | ||
| ) | ||
| top_span_names.append(span_name) | ||
| total_count += count | ||
| ctx.total_spans_count = total_count | ||
|
|
||
| if not top_span_names: | ||
| return | ||
|
|
||
| with start_span( | ||
| op="weekly_reports.top_spans_projects", name="weekly_reports.top_spans_projects" | ||
| ): | ||
| span_name_filter = " OR ".join( | ||
| 'span.name:"{}"'.format(name.replace("\\", "\\\\").replace('"', '\\"')) | ||
| for name in top_span_names[:TOP_SPANS_QUERY_LIMIT] | ||
| ) | ||
| project_result = Spans.run_table_query( | ||
| params=snuba_params, | ||
| query_string=f"is_transaction:1 ({span_name_filter})", | ||
| selected_columns=["span.name", "project.id", "count()"], | ||
| orderby=["-count()"], | ||
| offset=0, | ||
| limit=TOP_SPANS_QUERY_LIMIT * 10, | ||
| referrer=referrer, | ||
| config=config, | ||
| sampling_mode=None, | ||
| ) | ||
|
|
||
| for row in project_result.get("data", []): | ||
| span_name = row.get("span.name", "") | ||
| project_id = row.get("project.id") | ||
| if span_name and project_id: | ||
| ctx.top_spans_projects.setdefault(span_name, set()).add(int(project_id)) | ||
|
|
||
|
|
||
| def organization_top_spans_timeseries( |
Contributor
There was a problem hiding this comment.
Weekly report Total Spans includes org-wide count for spans the user only partially owns
Total Spans is computed from org-wide count() per top span and only gates on whether the span name appears in any of the recipient's accessible projects, so span volume from projects the user cannot access is included whenever a span name is shared. Store and sum per-project counts restricted to the user's project set instead of the org-level aggregate.
Evidence
organization_top_spans()inutils.pyqueries all org projects (ctx.projects_context_map) and stores each row's org-widecount()onctx.top_spans[i]["count"].- The second query only records which project IDs a span name appears in (
ctx.top_spans_projects[name]set); the per-project counts are discarded. render_template_context()inweekly_reports.pycomputessum(span["count"] ... if ctx.top_spans_projects.get(span["name"]) & user_project_ids), so any intersection with a single owned project adds the full org-wide count.- Impact is limited: the disclosed data is an aggregate span-count number for span names the user can already see, gated by the
organizations:weekly-report-spans-chartflag andenhanced_privacy.
Also found at 1 additional location
src/sentry/tasks/summaries/weekly_reports.py:858-863
Identified by Warden security-review · DLM-K72
Add an HTML table below the Total Spans header showing span description, project(s), p95 duration, and total duration for the top 5 spans. Includes a format_duration_ms template filter for human-readable duration formatting. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sum(span.duration)withcount()to get total span countorganizations:weekly-report-spans-chartfeature flagDetails
Data layer (
utils.py):organization_top_spans()now queriescount()alongsidesum(span.duration)andp95(span.duration)total_spans_countfield onOrganizationReportContextsums counts across all queried spansTemplate (
body.html):small_countfilter for abbreviated display (e.g. "4.3m")/explore/spans/Debug preview:
/debug/mail/reports/body/Test plan
test_organization_top_spans_populates_contexttest_organization_top_spans_skips_without_transactionstest_organization_top_spans_timeseries_populates_contexttest_organization_top_spans_timeseries_skips_without_top_spanstest_enhanced_privacy_skips_top_spanstest_top_spans_feature_flag_gates_querytest_top_spans_projects_filters_by_user_access/debug/mail/reports/body/