diff --git a/splunk_add_on_ucc_framework/dashboard.py b/splunk_add_on_ucc_framework/dashboard.py index 083b34063..9cb75f22a 100644 --- a/splunk_add_on_ucc_framework/dashboard.py +++ b/splunk_add_on_ucc_framework/dashboard.py @@ -63,7 +63,34 @@ "| join _time [search index=_internal source=*{addon_name}* action=events_ingested " '| timechart sum(n_events) as \\"Number of events\\" ]' ) -errors_count = "index=_internal source=*{addon_name}* log_level IN ({log_lvl}) | timechart count as Errors by exc_l" + +errors_count = "index=_internal source=*{addon_name}* log_level IN ({log_lvl}) | timechart count as Errors by exc_l " + +zero_line_search_query = ( + "| append [ gentimes increment=5m [ makeresults " + "| eval start=strftime( " + 'if(\\"${time_token}.earliest$\\"=\\"now\\"' + ",now()," + 'if(match(\\"${time_token}.earliest$\\",\\"^\\\\d+-\\\\d+-\\\\d+(T?\\\\d+:\\\\d+:\\\\d+(\\\\.\\\\d{{3}}Z)?)$\\"),' + 'strptime(\\"${time_token}.earliest$\\", \\"%Y-%m-%dT%H:%M:%S.%N\\")' + ',relative_time(now(), \\"${time_token}.earliest$\\")' + ")" + "), " + '\\"%m/%d/%Y:%T\\")' + "| eval end=strftime(" + 'if(\\"${time_token}.latest$\\"=\\"now\\",' + "now()," + 'if(match(\\"${time_token}.latest$\\",\\"^\\\\d+-\\\\d+-\\\\d+(T?\\\\d+:\\\\d+:\\\\d+(\\\\.\\\\d{{3}}Z)?)$\\"),' + 'strptime(\\"${time_token}.latest$\\", \\"%Y-%m-%dT%H:%M:%S.%N\\") ' + ',relative_time(now(), \\"${time_token}.latest$\\")' + ")" + "), " + '\\"%m/%d/%Y:%T\\")' + "| return start end] " + "| eval {value_label} = 0 | fields - endhuman starthuman starttime " + "| rename endtime as _time | head (${basic_query_token}:job.resultCount$==0)]" +) + events_count = ( "index=_internal source=*{addon_name}* action=events_ingested | " 'timechart sum(n_events) as \\"Number of events\\"' @@ -81,6 +108,7 @@ '| rename st as \\"Source type\\", Bytes as \\"Data volume\\", events as \\"Number of events\\", ' 'sparkvolume as \\"Volume trendline (Bytes)\\", sparkevent as \\"Event trendline\\"' ) + table_source_query = ( "index=_internal source=*license_usage.log type=Usage ({determine_by} IN ({lic_usg_condition})) " "| stats sparkline(sum(b)) as sparkvolume, sum(b) as Bytes by s " @@ -174,6 +202,16 @@ def generate_dashboard_content( errors_count=errors_count.format( addon_name=addon_name.lower(), log_lvl=error_panel_log_lvl ), + errors_count_zero_line=zero_line_search_query.format( + value_label="Errors", + basic_query_token="error_count", + time_token="overview_time", + ), + data_ingestion_and_events_zero_line=zero_line_search_query.format( + value_label="Number of events", + basic_query_token="data_volume", + time_token="overview_time", + ), events_count=events_count.format(addon_name=addon_name.lower()), ) ) @@ -186,10 +224,17 @@ def generate_dashboard_content( data_ingestion=data_ingestion.format( lic_usg_condition=lic_usg_condition, determine_by=determine_by ), - errors_count=errors_count.format( - addon_name=addon_name.lower(), log_lvl=error_panel_log_lvl + data_ingestion_volume_zero_line=zero_line_search_query.format( + value_label="Data volume", + basic_query_token="data_volume", + time_token="data_ingestion_time", ), events_count=events_count.format(addon_name=addon_name.lower()), + data_ingestion_event_count_zero_line=zero_line_search_query.format( + value_label="Number of events", + basic_query_token="data_ingestion_events_count", + time_token="data_ingestion_time", + ), table_sourcetype=table_sourcetype_query.format( lic_usg_condition=lic_usg_condition, addon_name=addon_name.lower(), @@ -225,6 +270,11 @@ def generate_dashboard_content( errors_count=errors_count.format( addon_name=addon_name.lower(), log_lvl=error_panel_log_lvl ), + errors_count_tab_zero_line=zero_line_search_query.format( + value_label="Errors", + basic_query_token="error_count_tab", + time_token="errors_tab_time", + ), errors_list=errors_list_query.format( addon_name=addon_name.lower(), log_lvl=error_panel_log_lvl ), diff --git a/splunk_add_on_ucc_framework/templates/data_ingestion_tab_definition.json b/splunk_add_on_ucc_framework/templates/data_ingestion_tab_definition.json index 3528f4955..7e16e483e 100644 --- a/splunk_add_on_ucc_framework/templates/data_ingestion_tab_definition.json +++ b/splunk_add_on_ucc_framework/templates/data_ingestion_tab_definition.json @@ -46,7 +46,7 @@ }, "title": "Data volume", "dataSources": { - "primary": "data_ingestion_data_volume_ds" + "primary": "data_ingestion_data_volume_ds_chain" } }, "data_ingestion_events_count_viz": { @@ -61,7 +61,7 @@ }, "title": "Number of events", "dataSources": { - "primary": "data_ingestion_events_count_ds" + "primary": "data_ingestion_events_count_ds_chain" } }, "data_ingestion_table_viz": { @@ -136,6 +136,19 @@ "type": "ds.search", "options": { "query": "{{data_ingestion}}", + "queryParameters": { + "earliest": "$data_ingestion_time.earliest$", + "latest": "$data_ingestion_time.latest$" + }, + "enableSmartSources": true + }, + "name": "data_volume" + }, + "data_ingestion_data_volume_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "data_ingestion_data_volume_ds", + "query": "{{data_ingestion_volume_zero_line}}", "queryParameters": { "earliest": "$data_ingestion_time.earliest$", "latest": "$data_ingestion_time.latest$" @@ -146,6 +159,19 @@ "type": "ds.search", "options": { "query": "{{events_count}}", + "queryParameters": { + "earliest": "$data_ingestion_time.earliest$", + "latest": "$data_ingestion_time.latest$" + }, + "enableSmartSources": true + }, + "name": "data_ingestion_events_count" + }, + "data_ingestion_events_count_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "data_ingestion_events_count_ds", + "query": "{{data_ingestion_event_count_zero_line}}", "queryParameters": { "earliest": "$data_ingestion_time.earliest$", "latest": "$data_ingestion_time.latest$" diff --git a/splunk_add_on_ucc_framework/templates/errors_tab_definition.json b/splunk_add_on_ucc_framework/templates/errors_tab_definition.json index e37605929..1c02b97e9 100644 --- a/splunk_add_on_ucc_framework/templates/errors_tab_definition.json +++ b/splunk_add_on_ucc_framework/templates/errors_tab_definition.json @@ -45,7 +45,7 @@ }, "title": "Errors count", "dataSources": { - "primary": "errors_tab_errors_count_ds" + "primary": "errors_tab_errors_count_ds_chain" } }, "errors_tab_errors_list_viz": { @@ -81,6 +81,19 @@ "type": "ds.search", "options": { "query": "{{errors_count}}", + "queryParameters": { + "earliest": "$errors_tab_time.earliest$", + "latest": "$errors_tab_time.latest$" + }, + "enableSmartSources": true + }, + "name": "error_count_tab" + }, + "errors_tab_errors_count_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "errors_tab_errors_count_ds", + "query": "{{errors_count_tab_zero_line}}", "queryParameters": { "earliest": "$errors_tab_time.earliest$", "latest": "$errors_tab_time.latest$" diff --git a/splunk_add_on_ucc_framework/templates/overview_definition.json b/splunk_add_on_ucc_framework/templates/overview_definition.json index 935e62b1b..e409d2dce 100644 --- a/splunk_add_on_ucc_framework/templates/overview_definition.json +++ b/splunk_add_on_ucc_framework/templates/overview_definition.json @@ -62,7 +62,7 @@ }, "title": "Data ingestion", "dataSources": { - "primary": "overview_data_volume_ds" + "primary": "overview_data_volume_ds_chain" } }, "overview_errors_viz": { @@ -74,7 +74,7 @@ }, "title": "Errors", "dataSources": { - "primary": "overview_errors_count_ds" + "primary": "overview_errors_count_ds_chain" } } }, @@ -103,6 +103,19 @@ "type": "ds.search", "options": { "query": "{{data_ingestion_and_events}}", + "queryParameters": { + "earliest": "$overview_time.earliest$", + "latest": "$overview_time.latest$" + }, + "enableSmartSources": true + }, + "name": "data_volume" + }, + "overview_data_volume_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "overview_data_volume_ds", + "query": "{{data_ingestion_and_events_zero_line}}", "queryParameters": { "earliest": "$overview_time.earliest$", "latest": "$overview_time.latest$" @@ -113,6 +126,19 @@ "type": "ds.search", "options": { "query": "{{errors_count}}", + "queryParameters": { + "earliest": "$overview_time.earliest$", + "latest": "$overview_time.latest$" + }, + "enableSmartSources": true + }, + "name": "error_count" + }, + "overview_errors_count_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "overview_errors_count_ds", + "query": "{{errors_count_zero_line}}", "queryParameters": { "earliest": "$overview_time.earliest$", "latest": "$overview_time.latest$" diff --git a/tests/unit/expected_results/data_ingestion_tab_definition.json b/tests/unit/expected_results/data_ingestion_tab_definition.json index ae470a03d..da8dac9ba 100644 --- a/tests/unit/expected_results/data_ingestion_tab_definition.json +++ b/tests/unit/expected_results/data_ingestion_tab_definition.json @@ -46,7 +46,7 @@ }, "title": "Data volume", "dataSources": { - "primary": "data_ingestion_data_volume_ds" + "primary": "data_ingestion_data_volume_ds_chain" } }, "data_ingestion_events_count_viz": { @@ -61,7 +61,7 @@ }, "title": "Number of events", "dataSources": { - "primary": "data_ingestion_events_count_ds" + "primary": "data_ingestion_events_count_ds_chain" } }, "data_ingestion_table_viz": { @@ -136,6 +136,19 @@ "type": "ds.search", "options": { "query": "index=_internal source=*license_usage.log type=Usage (s IN (example_input_one*,example_input_two*)) | timechart sum(b) as Usage | rename Usage as \"Data volume\"", + "queryParameters": { + "earliest": "$data_ingestion_time.earliest$", + "latest": "$data_ingestion_time.latest$" + }, + "enableSmartSources": true + }, + "name": "data_volume" + }, + "data_ingestion_data_volume_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "data_ingestion_data_volume_ds", + "query": "| append [ gentimes increment=5m [ makeresults | eval start=strftime( if(\"$data_ingestion_time.earliest$\"=\"now\",now(),if(match(\"$data_ingestion_time.earliest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$data_ingestion_time.earliest$\", \"%Y-%m-%dT%H:%M:%S.%N\"),relative_time(now(), \"$data_ingestion_time.earliest$\"))), \"%m/%d/%Y:%T\")| eval end=strftime(if(\"$data_ingestion_time.latest$\"=\"now\",now(),if(match(\"$data_ingestion_time.latest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$data_ingestion_time.latest$\", \"%Y-%m-%dT%H:%M:%S.%N\") ,relative_time(now(), \"$data_ingestion_time.latest$\"))), \"%m/%d/%Y:%T\")| return start end] | eval Data volume = 0 | fields - endhuman starthuman starttime | rename endtime as _time | head ($data_volume:job.resultCount$==0)]", "queryParameters": { "earliest": "$data_ingestion_time.earliest$", "latest": "$data_ingestion_time.latest$" @@ -146,6 +159,19 @@ "type": "ds.search", "options": { "query": "index=_internal source=*splunk_ta_uccexample* action=events_ingested | timechart sum(n_events) as \"Number of events\"", + "queryParameters": { + "earliest": "$data_ingestion_time.earliest$", + "latest": "$data_ingestion_time.latest$" + }, + "enableSmartSources": true + }, + "name": "data_ingestion_events_count" + }, + "data_ingestion_events_count_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "data_ingestion_events_count_ds", + "query": "| append [ gentimes increment=5m [ makeresults | eval start=strftime( if(\"$data_ingestion_time.earliest$\"=\"now\",now(),if(match(\"$data_ingestion_time.earliest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$data_ingestion_time.earliest$\", \"%Y-%m-%dT%H:%M:%S.%N\"),relative_time(now(), \"$data_ingestion_time.earliest$\"))), \"%m/%d/%Y:%T\")| eval end=strftime(if(\"$data_ingestion_time.latest$\"=\"now\",now(),if(match(\"$data_ingestion_time.latest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$data_ingestion_time.latest$\", \"%Y-%m-%dT%H:%M:%S.%N\") ,relative_time(now(), \"$data_ingestion_time.latest$\"))), \"%m/%d/%Y:%T\")| return start end] | eval Number of events = 0 | fields - endhuman starthuman starttime | rename endtime as _time | head ($data_ingestion_events_count:job.resultCount$==0)]", "queryParameters": { "earliest": "$data_ingestion_time.earliest$", "latest": "$data_ingestion_time.latest$" diff --git a/tests/unit/expected_results/errors_tab_definition.json b/tests/unit/expected_results/errors_tab_definition.json index d0863e824..3c23590ad 100644 --- a/tests/unit/expected_results/errors_tab_definition.json +++ b/tests/unit/expected_results/errors_tab_definition.json @@ -45,7 +45,7 @@ }, "title": "Errors count", "dataSources": { - "primary": "errors_tab_errors_count_ds" + "primary": "errors_tab_errors_count_ds_chain" } }, "errors_tab_errors_list_viz": { @@ -80,7 +80,20 @@ "errors_tab_errors_count_ds": { "type": "ds.search", "options": { - "query": "index=_internal source=*splunk_ta_uccexample* log_level IN (ERROR, CRITICAL) | timechart count as Errors by exc_l", + "query": "index=_internal source=*splunk_ta_uccexample* log_level IN (ERROR, CRITICAL) | timechart count as Errors by exc_l ", + "queryParameters": { + "earliest": "$errors_tab_time.earliest$", + "latest": "$errors_tab_time.latest$" + }, + "enableSmartSources": true + }, + "name": "error_count_tab" + }, + "errors_tab_errors_count_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "errors_tab_errors_count_ds", + "query": "| append [ gentimes increment=5m [ makeresults | eval start=strftime( if(\"$errors_tab_time.earliest$\"=\"now\",now(),if(match(\"$errors_tab_time.earliest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$errors_tab_time.earliest$\", \"%Y-%m-%dT%H:%M:%S.%N\"),relative_time(now(), \"$errors_tab_time.earliest$\"))), \"%m/%d/%Y:%T\")| eval end=strftime(if(\"$errors_tab_time.latest$\"=\"now\",now(),if(match(\"$errors_tab_time.latest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$errors_tab_time.latest$\", \"%Y-%m-%dT%H:%M:%S.%N\") ,relative_time(now(), \"$errors_tab_time.latest$\"))), \"%m/%d/%Y:%T\")| return start end] | eval Errors = 0 | fields - endhuman starthuman starttime | rename endtime as _time | head ($error_count_tab:job.resultCount$==0)]", "queryParameters": { "earliest": "$errors_tab_time.earliest$", "latest": "$errors_tab_time.latest$" diff --git a/tests/unit/expected_results/overview_definition.json b/tests/unit/expected_results/overview_definition.json index 27bb620c4..be76046ad 100644 --- a/tests/unit/expected_results/overview_definition.json +++ b/tests/unit/expected_results/overview_definition.json @@ -62,7 +62,7 @@ }, "title": "Data ingestion", "dataSources": { - "primary": "overview_data_volume_ds" + "primary": "overview_data_volume_ds_chain" } }, "overview_errors_viz": { @@ -74,7 +74,7 @@ }, "title": "Errors", "dataSources": { - "primary": "overview_errors_count_ds" + "primary": "overview_errors_count_ds_chain" } } }, @@ -103,6 +103,19 @@ "type": "ds.search", "options": { "query": "index=_internal source=*license_usage.log type=Usage (s IN (example_input_one*,example_input_two*)) | timechart sum(b) as Usage | rename Usage as \"Data volume\" | join _time [search index=_internal source=*splunk_ta_uccexample* action=events_ingested | timechart sum(n_events) as \"Number of events\" ]", + "queryParameters": { + "earliest": "$overview_time.earliest$", + "latest": "$overview_time.latest$" + }, + "enableSmartSources": true + }, + "name": "data_volume" + }, + "overview_data_volume_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "overview_data_volume_ds", + "query": "| append [ gentimes increment=5m [ makeresults | eval start=strftime( if(\"$overview_time.earliest$\"=\"now\",now(),if(match(\"$overview_time.earliest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$overview_time.earliest$\", \"%Y-%m-%dT%H:%M:%S.%N\"),relative_time(now(), \"$overview_time.earliest$\"))), \"%m/%d/%Y:%T\")| eval end=strftime(if(\"$overview_time.latest$\"=\"now\",now(),if(match(\"$overview_time.latest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$overview_time.latest$\", \"%Y-%m-%dT%H:%M:%S.%N\") ,relative_time(now(), \"$overview_time.latest$\"))), \"%m/%d/%Y:%T\")| return start end] | eval Number of events = 0 | fields - endhuman starthuman starttime | rename endtime as _time | head ($data_volume:job.resultCount$==0)]", "queryParameters": { "earliest": "$overview_time.earliest$", "latest": "$overview_time.latest$" @@ -112,7 +125,20 @@ "overview_errors_count_ds": { "type": "ds.search", "options": { - "query": "index=_internal source=*splunk_ta_uccexample* log_level IN (ERROR, CRITICAL) | timechart count as Errors by exc_l", + "query": "index=_internal source=*splunk_ta_uccexample* log_level IN (ERROR, CRITICAL) | timechart count as Errors by exc_l ", + "queryParameters": { + "earliest": "$overview_time.earliest$", + "latest": "$overview_time.latest$" + }, + "enableSmartSources": true + }, + "name": "error_count" + }, + "overview_errors_count_ds_chain": { + "type": "ds.chain", + "options": { + "extend": "overview_errors_count_ds", + "query": "| append [ gentimes increment=5m [ makeresults | eval start=strftime( if(\"$overview_time.earliest$\"=\"now\",now(),if(match(\"$overview_time.earliest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$overview_time.earliest$\", \"%Y-%m-%dT%H:%M:%S.%N\"),relative_time(now(), \"$overview_time.earliest$\"))), \"%m/%d/%Y:%T\")| eval end=strftime(if(\"$overview_time.latest$\"=\"now\",now(),if(match(\"$overview_time.latest$\",\"^\\d+-\\d+-\\d+(T?\\d+:\\d+:\\d+(\\.\\d{3}Z)?)$\"),strptime(\"$overview_time.latest$\", \"%Y-%m-%dT%H:%M:%S.%N\") ,relative_time(now(), \"$overview_time.latest$\"))), \"%m/%d/%Y:%T\")| return start end] | eval Errors = 0 | fields - endhuman starthuman starttime | rename endtime as _time | head ($error_count:job.resultCount$==0)]", "queryParameters": { "earliest": "$overview_time.earliest$", "latest": "$overview_time.latest$" diff --git a/ui/src/pages/Dashboard/DashboardModal.tsx b/ui/src/pages/Dashboard/DashboardModal.tsx index 96d72aaf2..30403f285 100644 --- a/ui/src/pages/Dashboard/DashboardModal.tsx +++ b/ui/src/pages/Dashboard/DashboardModal.tsx @@ -15,6 +15,7 @@ import { queryMap, } from './utils'; import { FieldValue, SearchResponse } from './DataIngestion.types'; +import { FEATURE_FLAGS } from './consts'; /** * @param {object} props @@ -196,7 +197,7 @@ export const DashboardModal = ({ }, []); return dataIngestionModalDef ? ( - + = { Input: 'Volume metrics are not available when the Input view is selected.', @@ -154,6 +155,7 @@ export const DataIngestionDashboard = ({ preset={EnterpriseViewOnlyPreset} initialDefinition={dashboardDefinition} dashboardPlugin={dashboardPlugin} + featureFlags={FEATURE_FLAGS} > <> <> | null; }) => { + const dashboardCoreApi = useRef(null); + useEffect(() => { waitForElementToDisplayAndMoveThemToCanvas( '[data-input-id="overview_input"]', @@ -18,12 +22,22 @@ export const OverviewDashboard = ({ return () => {}; }, []); + const setDashboardCoreApi = useCallback((api: DashboardCoreApi | null) => { + dashboardCoreApi.current = api; + }, []); + return dashboardDefinition ? ( - + ) : null; }; diff --git a/ui/src/pages/Dashboard/consts.ts b/ui/src/pages/Dashboard/consts.ts new file mode 100644 index 000000000..b3f0e1d1b --- /dev/null +++ b/ui/src/pages/Dashboard/consts.ts @@ -0,0 +1,3 @@ +export const FEATURE_FLAGS = { + enableSmartSourceDS: true, +};