feat: add configuration option to show field as JSON in dashboard (#11091) (#11104)

Design at:

https://github.com/openobserve/designs/tree/main/dashboards/show-field-as-json-default-value-env

---------

Co-authored-by: ktx-abhay <abhay.padamani@kiara.tech>
Co-authored-by: Abhay Padamani
<141122205+ktx-abhay@users.noreply.github.com>

---------

Co-authored-by: ktx-vaidehi <134508096+ktx-vaidehi@users.noreply.github.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Abhay Padamani <undefined@users.noreply.github.com>
This commit is contained in:
Abhay Padamani
2026-04-03 07:34:12 +00:00
committed by GitHub
co-authored by ktx-vaidehi claude[bot] Abhay Padamani
parent 81120c4388
commit 773c87018b
6 changed files with 44 additions and 12 deletions
+6
View File
@@ -1334,6 +1334,12 @@ pub struct Common {
help = "Enable to show symbol in dashboard"
)]
pub dashboard_show_symbol_enabled: bool,
#[env_config(
name = "ZO_DASHBOARD_SHOW_FIELD_AS_JSON_ENABLED",
default = false,
help = "Enable to show field as JSON in dashboard table"
)]
pub dashboard_show_field_as_json_enabled: bool,
#[env_config(name = "ZO_INGEST_DEFAULT_HEC_STREAM", default = "")]
pub default_hec_stream: String,
#[env_config(
+2
View File
@@ -173,6 +173,7 @@ struct ConfigResponse<'a> {
ai_enabled: bool,
dashboard_placeholder: String,
dashboard_show_symbol_enabled: bool,
dashboard_show_field_as_json_enabled: bool,
ingest_flatten_level: u32,
#[cfg(feature = "enterprise")]
license_expiry: i64,
@@ -410,6 +411,7 @@ pub async fn zo_config() -> impl IntoResponse {
ai_enabled,
dashboard_placeholder: cfg.common.dashboard_placeholder.to_string(),
dashboard_show_symbol_enabled: cfg.common.dashboard_show_symbol_enabled,
dashboard_show_field_as_json_enabled: cfg.common.dashboard_show_field_as_json_enabled,
ingest_flatten_level: cfg.limit.ingest_flatten_level,
#[cfg(feature = "enterprise")]
license_expiry: expiry_time,
@@ -821,7 +821,11 @@ export default defineComponent({
field.showFieldAsJson === undefined ||
field.showFieldAsJson === null
) {
field.showFieldAsJson = false;
field.showFieldAsJson =
dashboardPanelDataPageKey === "logs"
? (store?.state?.zoConfig?.dashboard_show_field_as_json_enabled ??
false)
: false;
}
};
@@ -15,7 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<template>
<div class="json-field-renderer">
<div :class="['json-field-renderer', { 'json-structured': isValidJSON }]">
<div v-if="parsedData === null || parsedData === undefined">
{{ value }}
</div>
@@ -66,9 +66,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</template>
<span class="json-brace">}</span>
</div>
<!-- Primitive value -->
<!-- Primitive value: only apply JSON coloring if the value was valid JSON -->
<div v-else>
<span :style="{ color: getValueColor(parsedData) }">{{ formatValue(parsedData) }}</span>
<span :style="isValidJSON ? { color: getValueColor(parsedData) } : {}">{{ formatValue(parsedData) }}</span>
</div>
</div>
</template>
@@ -85,17 +85,29 @@ const props = defineProps<Props>();
const store = useStore();
// Parse the value if it's a string, otherwise use as-is
const parsedData = computed(() => {
// Also tracks whether JSON parsing succeeded so we don't color plain strings as JSON
const parseResult = computed(() => {
if (typeof props.value === "string") {
try {
return JSON.parse(props.value);
const parsed = JSON.parse(props.value);
// Only treat as JSON if the parsed result is an object or array.
// Bare primitives ("42", "true", "null") are valid JSON but should
// not be colored -> they're just plain field values stored as strings.
const isStructuredJSON = parsed !== null && typeof parsed === "object";
return { data: parsed, isJSON: isStructuredJSON };
} catch (e) {
return props.value;
return { data: props.value, isJSON: false };
}
}
return props.value;
return { data: props.value, isJSON: false };
});
const parsedData = computed(() => parseResult.value.data);
// True when the original string was valid JSON (or value was not a string).
// Used to avoid coloring plain non-JSON strings (e.g. timestamps) like JSON values.
const isValidJSON = computed(() => parseResult.value.isJSON);
// Check if theme is dark - memoized
const isDarkTheme = computed(() => store.state.theme === "dark");
@@ -202,7 +214,7 @@ const isLastDefinedEntry = (obj: any, currentKey: string): boolean => {
</script>
<style lang="scss" scoped>
.json-field-renderer {
.json-structured {
font-family: monospace;
font-size: 12px;
line-height: 1.5;
@@ -105,7 +105,7 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => {
removeXYFilters,
setFieldsBasedOnChartTypeValidation,
isPivotMode,
} = usePanelFields({ dashboardPanelData, store });
} = usePanelFields({ dashboardPanelData, store, pageKey });
const { resetAggregationFunction } = usePanelAggregation({
dashboardPanelData,
@@ -33,9 +33,11 @@ const colors = [
export const usePanelFields = ({
dashboardPanelData,
store,
pageKey = "dashboard",
}: {
dashboardPanelData: any;
store: any;
pageKey?: string;
}) => {
const promqlMode = computed(
() => dashboardPanelData.data.queryType == "promql",
@@ -259,7 +261,10 @@ export const usePanelFields = ({
havingConditions: [],
treatAsNonTimestamp:
row.name === store.state.zoConfig.timestamp_column ? false : true,
showFieldAsJson: false,
showFieldAsJson:
pageKey === "logs"
? (store?.state?.zoConfig?.dashboard_show_field_as_json_enabled ?? false)
: false,
});
updateArrayAlias();
@@ -399,7 +404,10 @@ export const usePanelFields = ({
havingConditions: [],
treatAsNonTimestamp:
row.name === store.state.zoConfig.timestamp_column ? false : true,
showFieldAsJson: false,
showFieldAsJson:
pageKey === "logs"
? (store?.state?.zoConfig?.dashboard_show_field_as_json_enabled ?? false)
: false,
});
updateArrayAlias();
};