Skip to content

Conversation

@joshuali925
Copy link
Member

Description

Support by-value explore embeddables without stored saved object. In previous implementation, we can only render a visualization using saved explore embeddable if the object has been saved. This PR allows providing a JSON input and render it directly, without storing the saved object.

Sample code to use it:

  const factory = DepsStart.embeddable.getEmbeddableFactory('explore')!;

  const promqlInput = {
    id: 'explore-demo-promql-' + Date.now(),
    timeRange: { from: 'now-15m', to: 'now' },
    attributes: {
      title: 'Demo PromQL Visualization',
      visualization: JSON.stringify({
        chartType: 'line',
        params: { addLegend: true, legendPosition: 'bottom', lineMode: 'straight', lineWidth: 2 },
        axesMapping: { x: 'Time', y: '{instance="localhost:9090", job="prometheus"}' },
      }),
      uiState: JSON.stringify({ activeTab: 'explore_visualization_tab' }),
      kibanaSavedObjectMeta: {
        searchSourceJSON: JSON.stringify({
          query: {
            query: 'up',
            language: 'PROMQL',
            dataset: {
              id: 'my_prometheus',
              title: 'Prometheus connection 1',
              type: 'PROMETHEUS',
              timeFieldName: 'Time',
            },
          },
          filter: [],
        }),
      },
    },
    references: [],
  };

  const pplInput = {
    id: 'explore-demo-ppl-' + Date.now(),
    timeRange: { from: 'now-15m', to: 'now' },
    attributes: {
      title: 'index-example',
      visualization: JSON.stringify({
        title: '',
        chartType: 'bar',
        params: {
          switchAxes: false,
          addLegend: true,
          legendTitle: '',
          legendPosition: 'bottom',
          tooltipOptions: { mode: 'all' },
          barSizeMode: 'auto',
          barWidth: 0.7,
          barPadding: 0.1,
          showBarBorder: false,
          barBorderWidth: 1,
          barBorderColor: '#000000',
          thresholdOptions: { baseColor: '#00BD6B', thresholds: [], thresholdStyle: 'off' },
          useThresholdColor: false,
          standardAxes: [
            {
              id: 'Axis-1',
              position: 'bottom',
              show: true,
              style: {},
              labels: { show: true, rotate: 0, filter: false, truncate: 100 },
              title: { text: '' },
              grid: { showLines: false },
              axisRole: 'x',
            },
            {
              id: 'Axis-2',
              position: 'left',
              show: true,
              style: {},
              labels: { show: true, rotate: 0, filter: false, truncate: 100 },
              title: { text: '' },
              grid: { showLines: true },
              axisRole: 'y',
            },
          ],
          titleOptions: { show: false, titleName: '' },
          bucket: { aggregationType: 'sum', bucketTimeUnit: 'auto' },
          showFullTimeRange: false,
        },
        axesMapping: { x: 'referer', y: 'count()' },
      }),
      uiState: JSON.stringify({ activeTab: 'explore_visualization_tab' }),
      kibanaSavedObjectMeta: {
        searchSourceJSON: JSON.stringify({
          query: {
            language: 'PPL',
            dataset: {
              id: '02ced1b0-c95f-11f0-a5f2-dfc60f85a7e3::flog',
              title: 'flog',
              type: 'INDEXES',
              timeFieldName: 'datetime',
              isRemoteDataset: false,
              dataSource: {
                id: '02ced1b0-c95f-11f0-a5f2-dfc60f85a7e3',
                title: 'remote',
                type: 'DATA_SOURCE',
              },
              schemaMappings: {},
            },
            query: 'source = `flog` | stats count() by referer',
          },
          filter: [],
          indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
        }),
      },
    },
    references: [
      {
        name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
        type: 'index-pattern',
        id: '02ced1b0-c95f-11f0-a5f2-dfc60f85a7e3::flog',
      },
    ],
  };

  return (
    <EuiPage>
      <EuiPageBody>
        <EuiTitle size="s">
          <h3>Example 1: PromQL Visualization (Line Chart)</h3>
        </EuiTitle>
        <EuiSpacer size="s" />
        <div style={{ height: '500px' }}>
          <EmbeddableRenderer factory={factory} input={promqlInput} />
        </div>

        <EuiSpacer size="xl" />

        <EuiTitle size="s">
          <h3>Example 2: PPL/Index-based Visualization (Bar Chart)</h3>
        </EuiTitle>
        <EuiSpacer size="s" />
        <div style={{ height: '500px' }}>
          <EmbeddableRenderer factory={factory} input={pplInput} />
        </div>
      </EuiPageBody>
    </EuiPage>
  );

Issues Resolved

Screenshot

image

Testing the changes

added UT

Changelog

  • feat: Support by-value explore embeddables without stored saved object

Check List

  • All tests pass
    • yarn test:jest
    • yarn test:jest_integration
  • New functionality includes testing.
  • New functionality has been documented.
  • Update CHANGELOG.md
  • Commits are signed per the DCO using --signoff

@codecov
Copy link

codecov bot commented Nov 24, 2025

Codecov Report

❌ Patch coverage is 95.23810% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 60.80%. Comparing base (1d6b317) to head (62a8d9d).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...e/public/embeddable/explore_embeddable_factory.tsx 94.44% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #10970      +/-   ##
==========================================
+ Coverage   60.78%   60.80%   +0.01%     
==========================================
  Files        4531     4531              
  Lines      122243   122279      +36     
  Branches    20492    20503      +11     
==========================================
+ Hits        74304    74347      +43     
+ Misses      42697    42689       -8     
- Partials     5242     5243       +1     
Flag Coverage Δ
Linux_1 26.55% <0.00%> (-0.01%) ⬇️
Linux_2 38.92% <0.00%> (ø)
Linux_3 39.52% <100.00%> (?)
Linux_4 33.74% <85.71%> (+<0.01%) ⬆️
Windows_1 26.57% <0.00%> (-0.01%) ⬇️
Windows_2 38.90% <0.00%> (ø)
Windows_3 39.53% <100.00%> (+0.04%) ⬆️
Windows_4 33.74% <85.71%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

ps48
ps48 previously approved these changes Nov 25, 2025
Signed-off-by: Joshua Li <[email protected]>
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.

2 participants