mirror of https://github.com/grafana/grafana.git
TraceView: Refine UI visual hierarchy inside details section (#108929)
Actionlint / Lint GitHub Actions files (push) Waiting to run
Details
Backend Code Checks / Validate Backend Configs (push) Waiting to run
Details
Backend Unit Tests / Detect whether code changed (push) Waiting to run
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / All backend unit tests complete (push) Blocked by required conditions
Details
CodeQL checks / Analyze (actions) (push) Waiting to run
Details
CodeQL checks / Analyze (go) (push) Waiting to run
Details
CodeQL checks / Analyze (javascript) (push) Waiting to run
Details
Lint Frontend / Detect whether code changed (push) Waiting to run
Details
Lint Frontend / Lint (push) Blocked by required conditions
Details
Lint Frontend / Typecheck (push) Blocked by required conditions
Details
Lint Frontend / Betterer (push) Blocked by required conditions
Details
golangci-lint / lint-go (push) Waiting to run
Details
Crowdin Upload Action / upload-sources-to-crowdin (push) Waiting to run
Details
Verify i18n / verify-i18n (push) Waiting to run
Details
End-to-end tests / Detect whether code changed (push) Waiting to run
Details
End-to-end tests / Build & Package Grafana (push) Blocked by required conditions
Details
End-to-end tests / Build E2E test runner (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/dashboards-suite, dashboards-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/panels-suite, panels-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/smoke-tests-suite, smoke-tests-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/various-suite, various-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/dashboards-suite, dashboards-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/various-suite, various-suite) (push) Blocked by required conditions
Details
End-to-end tests / Verify Storybook (Playwright) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (1, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (2, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (3, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (4, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (5, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (6, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (7, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (8, 8) (push) Blocked by required conditions
Details
End-to-end tests / All Playwright tests complete (push) Blocked by required conditions
Details
End-to-end tests / A11y test (push) Blocked by required conditions
Details
End-to-end tests / All E2E tests complete (push) Blocked by required conditions
Details
Frontend tests / Detect whether code changed (push) Waiting to run
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (1) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (2) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (3) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (4) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (5) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (6) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (7) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (8) (push) Blocked by required conditions
Details
Frontend tests / Decoupled plugin tests (push) Blocked by required conditions
Details
Frontend tests / Packages unit tests (push) Blocked by required conditions
Details
Frontend tests / All frontend unit tests complete (push) Blocked by required conditions
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / All backend integration tests complete (push) Blocked by required conditions
Details
Reject GitHub secrets / reject-gh-secrets (push) Waiting to run
Details
Build Release Packages / setup (push) Waiting to run
Details
Build Release Packages / Dispatch grafana-enterprise build (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:darwin/amd64, darwin-amd64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:darwin/arm64, darwin-arm64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/amd64,deb:grafana:linux/amd64,rpm:grafana:linux/amd64,docker:grafana:linux/amd64,docker:grafana:linux/amd64:ubuntu,npm:grafana,storybook, linux-amd64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm/v6,deb:grafana:linux/arm/v6, linux-armv6, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm/v7,deb:grafana:linux/arm/v7,docker:grafana:linux/arm/v7,docker:grafana:linux/arm/v7:ubuntu, linux-armv7, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm64,deb:grafana:linux/arm64,rpm:grafana:linux/arm64,docker:grafana:linux/arm64,docker:grafana:linux/arm64:ubuntu, linux-arm64, false) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/s390x,deb:grafana:linux/s390x,rpm:grafana:linux/s390x,docker:grafana:linux/s390x,docker:grafana:linux/s390x:ubuntu, linux-s390x, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:windows/amd64,zip:grafana:windows/amd64,msi:grafana:windows/amd64, windows-amd64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:windows/arm64,zip:grafana:windows/arm64, windows-arm64, true) (push) Blocked by required conditions
Details
Build Release Packages / Upload artifacts (push) Blocked by required conditions
Details
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Waiting to run
Details
Shellcheck / Shellcheck scripts (push) Waiting to run
Details
Run Storybook a11y tests / Detect whether code changed (push) Waiting to run
Details
Run Storybook a11y tests / Run Storybook a11y tests (push) Blocked by required conditions
Details
Swagger generated code / Verify committed API specs match (push) Waiting to run
Details
Dispatch sync to mirror / dispatch-job (push) Waiting to run
Details
trigger-dashboard-search-e2e / trigger-search-e2e (push) Waiting to run
Details
Trivy Scan / trivy-scan (push) Waiting to run
Details
Actionlint / Lint GitHub Actions files (push) Waiting to run
Details
Backend Code Checks / Validate Backend Configs (push) Waiting to run
Details
Backend Unit Tests / Detect whether code changed (push) Waiting to run
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions
Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions
Details
Backend Unit Tests / All backend unit tests complete (push) Blocked by required conditions
Details
CodeQL checks / Analyze (actions) (push) Waiting to run
Details
CodeQL checks / Analyze (go) (push) Waiting to run
Details
CodeQL checks / Analyze (javascript) (push) Waiting to run
Details
Lint Frontend / Detect whether code changed (push) Waiting to run
Details
Lint Frontend / Lint (push) Blocked by required conditions
Details
Lint Frontend / Typecheck (push) Blocked by required conditions
Details
Lint Frontend / Betterer (push) Blocked by required conditions
Details
golangci-lint / lint-go (push) Waiting to run
Details
Crowdin Upload Action / upload-sources-to-crowdin (push) Waiting to run
Details
Verify i18n / verify-i18n (push) Waiting to run
Details
End-to-end tests / Detect whether code changed (push) Waiting to run
Details
End-to-end tests / Build & Package Grafana (push) Blocked by required conditions
Details
End-to-end tests / Build E2E test runner (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/dashboards-suite, dashboards-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/panels-suite, panels-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/smoke-tests-suite, smoke-tests-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/various-suite, various-suite (old arch)) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/dashboards-suite, dashboards-suite) (push) Blocked by required conditions
Details
End-to-end tests / ${{ matrix.suite }} (e2e/various-suite, various-suite) (push) Blocked by required conditions
Details
End-to-end tests / Verify Storybook (Playwright) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (1, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (2, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (3, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (4, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (5, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (6, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (7, 8) (push) Blocked by required conditions
Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (8, 8) (push) Blocked by required conditions
Details
End-to-end tests / All Playwright tests complete (push) Blocked by required conditions
Details
End-to-end tests / A11y test (push) Blocked by required conditions
Details
End-to-end tests / All E2E tests complete (push) Blocked by required conditions
Details
Frontend tests / Detect whether code changed (push) Waiting to run
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (1) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (2) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (3) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (4) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (5) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (6) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (7) (push) Blocked by required conditions
Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (8) (push) Blocked by required conditions
Details
Frontend tests / Decoupled plugin tests (push) Blocked by required conditions
Details
Frontend tests / Packages unit tests (push) Blocked by required conditions
Details
Frontend tests / All frontend unit tests complete (push) Blocked by required conditions
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Sqlite (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / MySQL (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (1/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (2/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (3/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (4/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (5/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (6/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (7/8) (push) Waiting to run
Details
Integration Tests / Postgres (${{ matrix.shard }}) (8/8) (push) Waiting to run
Details
Integration Tests / All backend integration tests complete (push) Blocked by required conditions
Details
Reject GitHub secrets / reject-gh-secrets (push) Waiting to run
Details
Build Release Packages / setup (push) Waiting to run
Details
Build Release Packages / Dispatch grafana-enterprise build (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:darwin/amd64, darwin-amd64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:darwin/arm64, darwin-arm64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/amd64,deb:grafana:linux/amd64,rpm:grafana:linux/amd64,docker:grafana:linux/amd64,docker:grafana:linux/amd64:ubuntu,npm:grafana,storybook, linux-amd64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm/v6,deb:grafana:linux/arm/v6, linux-armv6, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm/v7,deb:grafana:linux/arm/v7,docker:grafana:linux/arm/v7,docker:grafana:linux/arm/v7:ubuntu, linux-armv7, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm64,deb:grafana:linux/arm64,rpm:grafana:linux/arm64,docker:grafana:linux/arm64,docker:grafana:linux/arm64:ubuntu, linux-arm64, false) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/s390x,deb:grafana:linux/s390x,rpm:grafana:linux/s390x,docker:grafana:linux/s390x,docker:grafana:linux/s390x:ubuntu, linux-s390x, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:windows/amd64,zip:grafana:windows/amd64,msi:grafana:windows/amd64, windows-amd64, true) (push) Blocked by required conditions
Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:windows/arm64,zip:grafana:windows/arm64, windows-arm64, true) (push) Blocked by required conditions
Details
Build Release Packages / Upload artifacts (push) Blocked by required conditions
Details
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Waiting to run
Details
Shellcheck / Shellcheck scripts (push) Waiting to run
Details
Run Storybook a11y tests / Detect whether code changed (push) Waiting to run
Details
Run Storybook a11y tests / Run Storybook a11y tests (push) Blocked by required conditions
Details
Swagger generated code / Verify committed API specs match (push) Waiting to run
Details
Dispatch sync to mirror / dispatch-job (push) Waiting to run
Details
trigger-dashboard-search-e2e / trigger-search-e2e (push) Waiting to run
Details
Trivy Scan / trivy-scan (push) Waiting to run
Details
* TraceView: Span details content redesign * Unify displaying various sections in span details * Revert i18n key change * Update tests
This commit is contained in:
parent
f3cb8aa903
commit
7d8c2fbb82
|
@ -96,7 +96,7 @@ describe('AccordianKeyValues test', () => {
|
||||||
it('renders the summary instead of the table when it is not expanded', () => {
|
it('renders the summary instead of the table when it is not expanded', () => {
|
||||||
setupAccordian({ isOpen: false } as AccordianKeyValuesProps);
|
setupAccordian({ isOpen: false } as AccordianKeyValuesProps);
|
||||||
|
|
||||||
expect(screen.getByRole('switch', { name: 'test accordian: span.kind client omg mos-def' })).toBeInTheDocument();
|
expect(screen.getByRole('switch', { name: 'test accordian span.kind client omg mos-def' })).toBeInTheDocument();
|
||||||
expect(screen.queryByRole('table')).not.toBeInTheDocument();
|
expect(screen.queryByRole('table')).not.toBeInTheDocument();
|
||||||
expect(screen.queryAllByRole('cell')).toHaveLength(0);
|
expect(screen.queryAllByRole('cell')).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ import cx from 'classnames';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2, TraceKeyValuePair } from '@grafana/data';
|
import { GrafanaTheme2, TraceKeyValuePair } from '@grafana/data';
|
||||||
import { Icon, useStyles2 } from '@grafana/ui';
|
import { Counter, Icon, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { autoColor } from '../../Theme';
|
import { autoColor } from '../../Theme';
|
||||||
import TNil from '../../types/TNil';
|
import TNil from '../../types/TNil';
|
||||||
|
@ -43,6 +43,10 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
||||||
background: autoColor(theme, '#e8e8e8'),
|
background: autoColor(theme, '#e8e8e8'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
headerLabel: css({
|
||||||
|
width: '120px',
|
||||||
|
display: 'inline-block',
|
||||||
|
}),
|
||||||
headerEmpty: css({
|
headerEmpty: css({
|
||||||
label: 'headerEmpty',
|
label: 'headerEmpty',
|
||||||
background: 'none',
|
background: 'none',
|
||||||
|
@ -87,6 +91,9 @@ export type AccordianKeyValuesProps = {
|
||||||
logName?: string;
|
logName?: string;
|
||||||
highContrast?: boolean;
|
highContrast?: boolean;
|
||||||
interactive?: boolean;
|
interactive?: boolean;
|
||||||
|
onlyValues?: boolean;
|
||||||
|
showSummary?: boolean;
|
||||||
|
showCountBadge?: boolean;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
label: string | React.ReactNode;
|
label: string | React.ReactNode;
|
||||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => KeyValuesTableLink[]) | TNil;
|
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => KeyValuesTableLink[]) | TNil;
|
||||||
|
@ -127,6 +134,9 @@ export default function AccordianKeyValues({
|
||||||
isOpen,
|
isOpen,
|
||||||
label,
|
label,
|
||||||
linksGetter,
|
linksGetter,
|
||||||
|
onlyValues = false,
|
||||||
|
showSummary = true,
|
||||||
|
showCountBadge = false,
|
||||||
onToggle = null,
|
onToggle = null,
|
||||||
}: AccordianKeyValuesProps) {
|
}: AccordianKeyValuesProps) {
|
||||||
const isEmpty = (!Array.isArray(data) || !data.length) && !logName;
|
const isEmpty = (!Array.isArray(data) || !data.length) && !logName;
|
||||||
|
@ -148,7 +158,7 @@ export default function AccordianKeyValues({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const showDataSummaryFields = data.length > 0 && !isOpen;
|
const showDataSummaryFields = showSummary && data.length > 0 && !isOpen;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx(className, styles.container)}>
|
<div className={cx(className, styles.container)}>
|
||||||
|
@ -161,9 +171,9 @@ export default function AccordianKeyValues({
|
||||||
data-testid="AccordianKeyValues--header"
|
data-testid="AccordianKeyValues--header"
|
||||||
>
|
>
|
||||||
{arrow}
|
{arrow}
|
||||||
<strong data-test={markers.LABEL}>
|
<strong data-test={markers.LABEL} className={styles.headerLabel}>
|
||||||
{label}
|
{label}
|
||||||
{showDataSummaryFields && ':'}
|
{showCountBadge ? <Counter value={data.length} variant="secondary" /> : null}
|
||||||
</strong>
|
</strong>
|
||||||
{showDataSummaryFields && (
|
{showDataSummaryFields && (
|
||||||
<span className={css({ marginLeft: '0.7em' })}>
|
<span className={css({ marginLeft: '0.7em' })}>
|
||||||
|
@ -171,7 +181,7 @@ export default function AccordianKeyValues({
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isOpen && <KeyValuesTable data={tableFields} linksGetter={linksGetter} />}
|
{isOpen && <KeyValuesTable data={tableFields} linksGetter={linksGetter} onlyValues={onlyValues} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,10 +103,10 @@ describe('AccordianLogs tests', () => {
|
||||||
setup({ isOpen: true, openedItems: new Set() } as AccordianLogsProps);
|
setup({ isOpen: true, openedItems: new Set() } as AccordianLogsProps);
|
||||||
expect(
|
expect(
|
||||||
screen.getByRole('switch', {
|
screen.getByRole('switch', {
|
||||||
name: '15μs (foo event name) : message oh the next log message more stuff',
|
name: '15μs (foo event name) message oh the next log message more stuff',
|
||||||
})
|
})
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
expect(screen.getByRole('switch', { name: '5μs: message oh the log message something else' })).toBeInTheDocument();
|
expect(screen.getByRole('switch', { name: '5μs message oh the log message something else' })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders event name and duration when events list is open', () => {
|
it('renders event name and duration when events list is open', () => {
|
||||||
|
|
|
@ -32,14 +32,12 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||||
AccordianLogs: css({
|
AccordianLogs: css({
|
||||||
label: 'AccordianLogs',
|
label: 'AccordianLogs',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
marginBottom: '0.25rem',
|
|
||||||
}),
|
}),
|
||||||
AccordianLogsHeader: css({
|
AccordianLogsHeader: css({
|
||||||
label: 'AccordianLogsHeader',
|
label: 'AccordianLogsHeader',
|
||||||
color: 'inherit',
|
color: 'inherit',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: '0.25rem 0.1em',
|
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: autoColor(theme, '#e8e8e8'),
|
background: autoColor(theme, '#e8e8e8'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,7 +75,7 @@ describe('AccordianReferences tests', () => {
|
||||||
it('renders the correct number of references', () => {
|
it('renders the correct number of references', () => {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
expect(screen.getByRole('switch', { name: 'References (3)' })).toBeInTheDocument();
|
expect(screen.getByRole('switch', { name: 'References 3' })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('content doesnt show when not expanded', () => {
|
it('content doesnt show when not expanded', () => {
|
||||||
|
@ -88,7 +88,7 @@ describe('AccordianReferences tests', () => {
|
||||||
it('renders the content when it is expanded', () => {
|
it('renders the content when it is expanded', () => {
|
||||||
setup({ isOpen: true } as AccordianReferencesProps);
|
setup({ isOpen: true } as AccordianReferencesProps);
|
||||||
|
|
||||||
expect(screen.getByRole('switch', { name: 'References (3)' })).toBeInTheDocument();
|
expect(screen.getByRole('switch', { name: 'References 3' })).toBeInTheDocument();
|
||||||
expect(screen.getAllByRole('link', { name: /^service\d\sop\d/ })).toHaveLength(2);
|
expect(screen.getAllByRole('link', { name: /^service\d\sop\d/ })).toHaveLength(2);
|
||||||
expect(screen.getByRole('link', { name: /^View\sLinked/ })).toBeInTheDocument();
|
expect(screen.getByRole('link', { name: /^View\sLinked/ })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ import * as React from 'react';
|
||||||
|
|
||||||
import { Field, GrafanaTheme2, LinkModel } from '@grafana/data';
|
import { Field, GrafanaTheme2, LinkModel } from '@grafana/data';
|
||||||
import { Trans, t } from '@grafana/i18n';
|
import { Trans, t } from '@grafana/i18n';
|
||||||
import { Icon, useStyles2 } from '@grafana/ui';
|
import { Counter, Icon, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { autoColor } from '../../Theme';
|
import { autoColor } from '../../Theme';
|
||||||
import { TraceSpanReference } from '../../types/trace';
|
import { TraceSpanReference } from '../../types/trace';
|
||||||
|
@ -36,16 +36,14 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
}),
|
}),
|
||||||
AccordianReferences: css({
|
AccordianReferences: css({
|
||||||
label: 'AccordianReferences',
|
label: 'AccordianReferences',
|
||||||
border: `1px solid ${autoColor(theme, '#d8d8d8')}`,
|
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
marginBottom: '0.25rem',
|
marginBottom: '0.25rem',
|
||||||
}),
|
}),
|
||||||
AccordianReferencesHeader: css({
|
AccordianReferencesHeader: css({
|
||||||
label: 'AccordianReferencesHeader',
|
label: 'AccordianReferencesHeader',
|
||||||
background: autoColor(theme, '#e4e4e4'),
|
|
||||||
color: 'inherit',
|
color: 'inherit',
|
||||||
display: 'block',
|
display: 'block',
|
||||||
padding: '0.25rem 0.5rem',
|
padding: '0.25rem 0',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: autoColor(theme, '#dadada'),
|
background: autoColor(theme, '#dadada'),
|
||||||
},
|
},
|
||||||
|
@ -223,7 +221,7 @@ const AccordianReferences = ({
|
||||||
<Trans i18nKey="explore.accordian-references.references">References</Trans>
|
<Trans i18nKey="explore.accordian-references.references">References</Trans>
|
||||||
</span>
|
</span>
|
||||||
</strong>{' '}
|
</strong>{' '}
|
||||||
({data.length})
|
<Counter value={data.length} />
|
||||||
</HeaderComponent>
|
</HeaderComponent>
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<References
|
<References
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
// Copyright (c) 2019 Uber Technologies, Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import { render, screen, within } from '@testing-library/react';
|
|
||||||
|
|
||||||
import AccordianText from './AccordianText';
|
|
||||||
|
|
||||||
const warnings = ['Duplicated tag', 'Duplicated spanId'];
|
|
||||||
|
|
||||||
describe('<AccordianText>', () => {
|
|
||||||
const props = {
|
|
||||||
compact: false,
|
|
||||||
data: warnings,
|
|
||||||
highContrast: false,
|
|
||||||
isOpen: false,
|
|
||||||
label: 'le-label',
|
|
||||||
onToggle: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
it('renders without exploding', () => {
|
|
||||||
render(<AccordianText {...props} />);
|
|
||||||
expect(() => render(<AccordianText {...props} />)).not.toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders the label', () => {
|
|
||||||
render(<AccordianText {...props} />);
|
|
||||||
const { getByText } = within(screen.getByTestId('AccordianText--header'));
|
|
||||||
expect(getByText(props.label)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders the content when it is expanded', () => {
|
|
||||||
props.isOpen = true;
|
|
||||||
render(<AccordianText {...props} />);
|
|
||||||
warnings.forEach((warning) => {
|
|
||||||
expect(screen.getByText(warning)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,97 +0,0 @@
|
||||||
// Copyright (c) 2019 Uber Technologies, Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
import { css } from '@emotion/css';
|
|
||||||
import cx from 'classnames';
|
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
|
||||||
import { Icon, useStyles2 } from '@grafana/ui';
|
|
||||||
|
|
||||||
import { autoColor } from '../../Theme';
|
|
||||||
import TNil from '../../types/TNil';
|
|
||||||
|
|
||||||
import { getStyles as getAccordianKeyValuesStyles } from './AccordianKeyValues';
|
|
||||||
import TextList from './TextList';
|
|
||||||
|
|
||||||
import { alignIcon } from '.';
|
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => ({
|
|
||||||
header: css({
|
|
||||||
cursor: 'pointer',
|
|
||||||
overflow: 'hidden',
|
|
||||||
padding: '0.25em 0.1em',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
'&:hover': {
|
|
||||||
background: autoColor(theme, '#e8e8e8'),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
type AccordianTextProps = {
|
|
||||||
className?: string | TNil;
|
|
||||||
headerClassName?: string | TNil;
|
|
||||||
data: string[];
|
|
||||||
highContrast?: boolean;
|
|
||||||
interactive?: boolean;
|
|
||||||
isOpen: boolean;
|
|
||||||
label: React.ReactNode | string;
|
|
||||||
onToggle?: null | (() => void);
|
|
||||||
TextComponent?: React.ElementType<{ data: string[] }>;
|
|
||||||
};
|
|
||||||
|
|
||||||
function DefaultTextComponent({ data }: { data: string[] }) {
|
|
||||||
return <TextList data={data} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function AccordianText({
|
|
||||||
className = null,
|
|
||||||
data,
|
|
||||||
headerClassName,
|
|
||||||
highContrast = false,
|
|
||||||
interactive = true,
|
|
||||||
isOpen,
|
|
||||||
label,
|
|
||||||
onToggle = null,
|
|
||||||
TextComponent = DefaultTextComponent,
|
|
||||||
}: AccordianTextProps) {
|
|
||||||
const isEmpty = !Array.isArray(data) || !data.length;
|
|
||||||
const accordianKeyValuesStyles = useStyles2(getAccordianKeyValuesStyles);
|
|
||||||
const iconCls = cx(alignIcon, { [accordianKeyValuesStyles.emptyIcon]: isEmpty });
|
|
||||||
let arrow: React.ReactNode | null = null;
|
|
||||||
let headerProps: {} | null = null;
|
|
||||||
if (interactive) {
|
|
||||||
arrow = isOpen ? (
|
|
||||||
<Icon name={'angle-down'} className={iconCls} />
|
|
||||||
) : (
|
|
||||||
<Icon name={'angle-right'} className={iconCls} />
|
|
||||||
);
|
|
||||||
headerProps = {
|
|
||||||
'aria-checked': isOpen,
|
|
||||||
onClick: isEmpty ? null : onToggle,
|
|
||||||
role: 'switch',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const styles = useStyles2(getStyles);
|
|
||||||
return (
|
|
||||||
<div className={className || ''}>
|
|
||||||
<div className={cx(styles.header, headerClassName)} {...headerProps} data-testid="AccordianText--header">
|
|
||||||
{arrow}
|
|
||||||
<strong>{label}</strong> ({data.length})
|
|
||||||
</div>
|
|
||||||
{isOpen && <TextComponent data={data} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -47,7 +47,7 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
||||||
row: css({
|
row: css({
|
||||||
label: 'row',
|
label: 'row',
|
||||||
'& > td': {
|
'& > td': {
|
||||||
padding: '0.5rem 0.5rem',
|
padding: '0 0.5rem',
|
||||||
height: '30px',
|
height: '30px',
|
||||||
},
|
},
|
||||||
'&:nth-child(2n) > td': {
|
'&:nth-child(2n) > td': {
|
||||||
|
@ -68,7 +68,6 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
||||||
color: autoColor(theme, '#888'),
|
color: autoColor(theme, '#888'),
|
||||||
whiteSpace: 'pre',
|
whiteSpace: 'pre',
|
||||||
width: '125px',
|
width: '125px',
|
||||||
verticalAlign: 'top',
|
|
||||||
}),
|
}),
|
||||||
copyColumn: css({
|
copyColumn: css({
|
||||||
label: 'copyColumn',
|
label: 'copyColumn',
|
||||||
|
@ -118,19 +117,32 @@ export const LinkValue = ({ link, children }: PropsWithChildren<LinkValueProps>)
|
||||||
export type KeyValuesTableProps = {
|
export type KeyValuesTableProps = {
|
||||||
data: TraceKeyValuePair[];
|
data: TraceKeyValuePair[];
|
||||||
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => KeyValuesTableLink[]) | TNil;
|
linksGetter?: ((pairs: TraceKeyValuePair[], index: number) => KeyValuesTableLink[]) | TNil;
|
||||||
|
onlyValues?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function KeyValuesTable(props: KeyValuesTableProps) {
|
export default function KeyValuesTable(props: KeyValuesTableProps) {
|
||||||
const { data, linksGetter } = props;
|
const { data, linksGetter, onlyValues } = props;
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
return (
|
return (
|
||||||
<div className={cx(styles.KeyValueTable)} data-testid="KeyValueTable">
|
<div className={cx(styles.KeyValueTable)} data-testid="KeyValueTable">
|
||||||
<table className={styles.table}>
|
<table className={styles.table}>
|
||||||
<tbody className={styles.body}>
|
<tbody className={styles.body}>
|
||||||
{data.map((row, i) => {
|
{data.map((row, i) => {
|
||||||
const markup = {
|
let markup = { __html: '' };
|
||||||
|
if (row.type === 'code') {
|
||||||
|
markup = {
|
||||||
|
__html: `<pre style="border: none; background: none">${row.value}</pre>`,
|
||||||
|
};
|
||||||
|
} else if (row.type === 'text') {
|
||||||
|
markup = {
|
||||||
|
__html: `<span style="white-space: pre-wrap;">${row.value}</span>`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
markup = {
|
||||||
__html: jsonMarkup(parseIfComplexJson(row.value)),
|
__html: jsonMarkup(parseIfComplexJson(row.value)),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const jsonTable = <div className={styles.jsonTable} dangerouslySetInnerHTML={markup} />;
|
const jsonTable = <div className={styles.jsonTable} dangerouslySetInnerHTML={markup} />;
|
||||||
const links = linksGetter?.(data, i);
|
const links = linksGetter?.(data, i);
|
||||||
let valueMarkup;
|
let valueMarkup;
|
||||||
|
@ -147,15 +159,17 @@ export default function KeyValuesTable(props: KeyValuesTableProps) {
|
||||||
return (
|
return (
|
||||||
// `i` is necessary in the key because row.key can repeat
|
// `i` is necessary in the key because row.key can repeat
|
||||||
<tr className={styles.row} key={`${row.key}-${i}`}>
|
<tr className={styles.row} key={`${row.key}-${i}`}>
|
||||||
|
{!onlyValues && (
|
||||||
<td className={styles.keyColumn} data-testid="KeyValueTable--keyColumn">
|
<td className={styles.keyColumn} data-testid="KeyValueTable--keyColumn">
|
||||||
{row.key}
|
{row.key}
|
||||||
</td>
|
</td>
|
||||||
|
)}
|
||||||
<td>{valueMarkup}</td>
|
<td>{valueMarkup}</td>
|
||||||
<td className={styles.copyColumn}>
|
<td className={styles.copyColumn}>
|
||||||
<CopyIcon
|
<CopyIcon
|
||||||
className={copyIconClassName}
|
className={copyIconClassName}
|
||||||
copyText={JSON.stringify(row, null, 2)}
|
copyText={row.type === 'code' || row.type === 'text' ? row.value : JSON.stringify(row, null, 2)}
|
||||||
tooltipTitle="Copy JSON"
|
tooltipTitle="Copy"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
|
|
||||||
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
const getStyles = () => ({
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
TextList: css({
|
TextList: css({
|
||||||
maxHeight: '450px',
|
maxHeight: '450px',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
|
@ -32,7 +33,7 @@ const getStyles = () => ({
|
||||||
padding: '0.25rem 0.5rem',
|
padding: '0.25rem 0.5rem',
|
||||||
verticalAlign: 'top',
|
verticalAlign: 'top',
|
||||||
'&:nth-child(2n)': {
|
'&:nth-child(2n)': {
|
||||||
background: '#f5f5f5',
|
background: theme.colors.background.secondary,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,11 +29,11 @@ import {
|
||||||
PluginExtensionPoints,
|
PluginExtensionPoints,
|
||||||
IconName,
|
IconName,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { Trans, t } from '@grafana/i18n';
|
import { t } from '@grafana/i18n';
|
||||||
import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend';
|
import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend';
|
||||||
import { usePluginLinks } from '@grafana/runtime';
|
import { usePluginLinks } from '@grafana/runtime';
|
||||||
import { TimeZone } from '@grafana/schema';
|
import { TimeZone } from '@grafana/schema';
|
||||||
import { TextArea, useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { pyroscopeProfileIdTagKey } from '../../../createSpanLink';
|
import { pyroscopeProfileIdTagKey } from '../../../createSpanLink';
|
||||||
import { autoColor } from '../../Theme';
|
import { autoColor } from '../../Theme';
|
||||||
|
@ -46,7 +46,6 @@ import { formatDuration } from '../utils';
|
||||||
import AccordianKeyValues from './AccordianKeyValues';
|
import AccordianKeyValues from './AccordianKeyValues';
|
||||||
import AccordianLogs from './AccordianLogs';
|
import AccordianLogs from './AccordianLogs';
|
||||||
import AccordianReferences from './AccordianReferences';
|
import AccordianReferences from './AccordianReferences';
|
||||||
import AccordianText from './AccordianText';
|
|
||||||
import DetailState from './DetailState';
|
import DetailState from './DetailState';
|
||||||
import { ShareSpanButton } from './ShareSpanButton';
|
import { ShareSpanButton } from './ShareSpanButton';
|
||||||
import { getSpanDetailLinkButtons } from './SpanDetailLinkButtons';
|
import { getSpanDetailLinkButtons } from './SpanDetailLinkButtons';
|
||||||
|
@ -99,6 +98,9 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||||
gap: '0 1rem',
|
gap: '0 1rem',
|
||||||
marginBottom: '0.25rem',
|
marginBottom: '0.25rem',
|
||||||
}),
|
}),
|
||||||
|
content: css({
|
||||||
|
fontSize: theme.typography.bodySmall.fontSize,
|
||||||
|
}),
|
||||||
listWrapper: css({
|
listWrapper: css({
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
@ -340,7 +342,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||||
<ShareSpanButton focusSpanLink={focusSpanLink} />
|
<ShareSpanButton focusSpanLink={focusSpanLink} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.linkList}>{linksComponent}</div>
|
<div className={styles.linkList}>{linksComponent}</div>
|
||||||
<div>
|
<div className={styles.content}>
|
||||||
<div>
|
<div>
|
||||||
<AccordianKeyValues
|
<AccordianKeyValues
|
||||||
data={tags}
|
data={tags}
|
||||||
|
@ -368,48 +370,39 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||||
timestamp={traceStartTime}
|
timestamp={traceStartTime}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{warnings && warnings.length > 0 && (
|
{warnings && warnings.length > 0 && (
|
||||||
<AccordianText
|
<AccordianKeyValues
|
||||||
className={styles.AccordianWarnings}
|
data={warnings.map((warning) => ({
|
||||||
headerClassName={styles.AccordianWarningsHeader}
|
key: '',
|
||||||
label={
|
value: warning,
|
||||||
<span className={styles.AccordianWarningsLabel}>
|
type: 'text',
|
||||||
<Trans i18nKey="explore.span-detail.warnings">Warnings</Trans>
|
}))}
|
||||||
</span>
|
showSummary={false}
|
||||||
}
|
showCountBadge={true}
|
||||||
data={warnings}
|
|
||||||
isOpen={isWarningsOpen}
|
isOpen={isWarningsOpen}
|
||||||
|
onlyValues={true}
|
||||||
onToggle={() => warningsToggle(spanID)}
|
onToggle={() => warningsToggle(spanID)}
|
||||||
|
label={t('explore.span-detail.warnings', 'Warnings')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{stackTraces?.length ? (
|
{stackTraces?.length ? (
|
||||||
<AccordianText
|
<AccordianKeyValues
|
||||||
label={t('explore.span-detail.label-stack-trace', 'Stack trace')}
|
data={stackTraces.map((stackTrace) => ({
|
||||||
data={stackTraces}
|
key: '',
|
||||||
|
value: stackTrace,
|
||||||
|
type: 'code',
|
||||||
|
}))}
|
||||||
|
onlyValues={true}
|
||||||
|
showSummary={false}
|
||||||
|
showCountBadge={true}
|
||||||
isOpen={isStackTracesOpen}
|
isOpen={isStackTracesOpen}
|
||||||
TextComponent={(textComponentProps) => {
|
|
||||||
let text;
|
|
||||||
if (textComponentProps.data?.length > 1) {
|
|
||||||
text = textComponentProps.data
|
|
||||||
.map((stackTrace, index) => `StackTrace ${index + 1}:\n${stackTrace}`)
|
|
||||||
.join('\n');
|
|
||||||
} else {
|
|
||||||
text = textComponentProps.data?.[0];
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<TextArea
|
|
||||||
className={styles.Textarea}
|
|
||||||
style={{ cursor: 'unset' }}
|
|
||||||
readOnly
|
|
||||||
cols={10}
|
|
||||||
rows={10}
|
|
||||||
value={text}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
onToggle={() => stackTracesToggle(spanID)}
|
onToggle={() => stackTracesToggle(spanID)}
|
||||||
|
label={t('explore.span-detail.label-stack-trace', 'Stack trace')}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{references && references.length > 0 && (references.length > 1 || references[0].refType !== 'CHILD_OF') && (
|
{references && references.length > 0 && (references.length > 1 || references[0].refType !== 'CHILD_OF') && (
|
||||||
<AccordianReferences
|
<AccordianReferences
|
||||||
data={references}
|
data={references}
|
||||||
|
|
|
@ -40,7 +40,6 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => ({
|
||||||
|
|
||||||
'& .json-markup': {
|
'& .json-markup': {
|
||||||
lineHeight: '17px',
|
lineHeight: '17px',
|
||||||
fontSize: '13px',
|
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
whiteSpace: 'pre-wrap',
|
whiteSpace: 'pre-wrap',
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,7 +24,6 @@ const getStyles = () => ({
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
color: 'inherit',
|
color: 'inherit',
|
||||||
height: '100%',
|
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
'&:focus': {
|
'&:focus': {
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.25)',
|
backgroundColor: 'rgba(255, 255, 255, 0.25)',
|
||||||
|
|
|
@ -290,6 +290,8 @@ export class TestDataDataSource extends DataSourceWithBackend<TestDataDataQuery>
|
||||||
{ name: 'tags' },
|
{ name: 'tags' },
|
||||||
{ name: 'kind' },
|
{ name: 'kind' },
|
||||||
{ name: 'statusCode' },
|
{ name: 'statusCode' },
|
||||||
|
{ name: 'warnings' },
|
||||||
|
{ name: 'stackTraces' },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const numberOfSpans = options.targets[0].spanCount || 10;
|
const numberOfSpans = options.targets[0].spanCount || 10;
|
||||||
|
@ -327,6 +329,52 @@ export class TestDataDataSource extends DataSourceWithBackend<TestDataDataQuery>
|
||||||
: [],
|
: [],
|
||||||
kind: i === 0 ? 'client' : kinds[Math.floor(Math.random() * kinds.length)],
|
kind: i === 0 ? 'client' : kinds[Math.floor(Math.random() * kinds.length)],
|
||||||
statusCode: statusCodes[Math.floor(Math.random() * statusCodes.length)],
|
statusCode: statusCodes[Math.floor(Math.random() * statusCodes.length)],
|
||||||
|
references:
|
||||||
|
i === 0
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
refType: 'EXTERNAL',
|
||||||
|
spanID: spanIdPrefix + 10001,
|
||||||
|
traceID: spanIdPrefix + '10000',
|
||||||
|
tags: [
|
||||||
|
{ key: 'external.service', value: `Service${i}` },
|
||||||
|
{ key: 'resource.pod', value: `Pod${i}` },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
warnings:
|
||||||
|
i % 2 === 0
|
||||||
|
? [
|
||||||
|
'[2025-07-30T14:12:09Z] [payment-service] Delayed response from external payment gateway (Stripe). Request ID: 8f3a7c2b-ff13-4e3c-b610-18a92c8b199d. Latency: 3421ms. Threshold: 2500ms.',
|
||||||
|
'[2025-07-30T14:14:42Z] [notification-service] Email delivery failed for user_id=93244 (Email: user@example.com). SMTP server responded with status 421: "Service not available, closing transmission channel".',
|
||||||
|
'[2025-07-30T14:18:55Z] [user-profile-service] Deprecated API version used in request: /v1/profile/update. Recommend migrating to /v2/profile/update. Client ID: svc-auth-34.',
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
stackTraces:
|
||||||
|
i % 4 === 0
|
||||||
|
? [
|
||||||
|
'Traceback (most recent call last):\n' +
|
||||||
|
' File "/app/services/payment.py", line 112, in process_transaction\n' +
|
||||||
|
' response = gateway.charge(card_info, amount)\n' +
|
||||||
|
' File "/app/lib/gateway/stripe_client.py", line 76, in charge\n' +
|
||||||
|
' return self._send_request(payload)\n' +
|
||||||
|
' File "/app/lib/gateway/stripe_client.py", line 45, in _send_request\n' +
|
||||||
|
' raise GatewayTimeoutError("Stripe request timed out after 3000ms")\n' +
|
||||||
|
'gateway.exceptions.GatewayTimeoutError: Stripe request timed out after 3000ms\n',
|
||||||
|
|
||||||
|
'Traceback (most recent call last):\n' +
|
||||||
|
' File "/usr/src/app/main.py", line 27, in <module>\n' +
|
||||||
|
' run_app()\n' +
|
||||||
|
' File "/usr/src/app/core/server.py", line 88, in run_app\n' +
|
||||||
|
' initialize_services()\n' +
|
||||||
|
' File "/usr/src/app/core/init.py", line 52, in initialize_services\n' +
|
||||||
|
' db.connect()\n' +
|
||||||
|
' File "/usr/src/app/db/connection.py", line 31, in connect\n' +
|
||||||
|
' raise DatabaseConnectionError("Failed to connect to database: timeout after 5s")\n' +
|
||||||
|
'db.exceptions.DatabaseConnectionError: Failed to connect to database: timeout after 5s\n',
|
||||||
|
]
|
||||||
|
: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue