From 5841993ba22de0c3b1e26c4bf1550be1bcdcaae7 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Sun, 15 Dec 2024 16:39:33 +0200 Subject: [PATCH 1/5] feat: "other agent" for new UI --- .../configured-destinations-list/index.tsx | 137 +++--------------- .../sources/source-drawer-container/index.tsx | 8 +- .../condition-details/index.tsx | 2 +- .../data-card/data-card-fields/index.tsx | 23 ++- .../reuseable-components/data-tab/index.tsx | 114 +++++++++------ .../extend-icon/index.tsx | 6 +- .../monitors-icons/index.tsx | 9 +- 7 files changed, 129 insertions(+), 170 deletions(-) diff --git a/frontend/webapp/containers/main/destinations/add-destination/configured-destinations-list/index.tsx b/frontend/webapp/containers/main/destinations/add-destination/configured-destinations-list/index.tsx index 89360955a..0991e1761 100644 --- a/frontend/webapp/containers/main/destinations/add-destination/configured-destinations-list/index.tsx +++ b/frontend/webapp/containers/main/destinations/add-destination/configured-destinations-list/index.tsx @@ -1,10 +1,11 @@ import React, { useState } from 'react'; import Image from 'next/image'; import styled from 'styled-components'; +import { extractMonitors } from '@/utils'; import { DeleteWarning } from '@/components'; import { IAppState, useAppStore } from '@/store'; import { OVERVIEW_ENTITY_TYPES, type ConfiguredDestination } from '@/types'; -import { Button, DataCardFields, Divider, ExtendIcon, Text } from '@/reuseable-components'; +import { DataCardFields, DataTab, IconButton, Text } from '@/reuseable-components'; const Container = styled.div` display: flex; @@ -18,128 +19,26 @@ const Container = styled.div` overflow-y: scroll; `; -const ListItem = styled.div` - width: 100%; - border-radius: 16px; - background: ${({ theme }) => theme.colors.translucent_bg}; -`; - -const ListItemBody = styled.div` - width: 100%; - padding: 16px; -`; - -const ListItemHeader = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - padding: 16px 0px; -`; - -const ListItemContent = styled.div` - display: flex; - gap: 12px; - margin-left: 16px; -`; - -const DestinationIconWrapper = styled.div` - display: flex; - width: 36px; - height: 36px; - justify-content: center; - align-items: center; - gap: 8px; - border-radius: 8px; - background: linear-gradient(180deg, rgba(249, 249, 249, 0.06) 0%, rgba(249, 249, 249, 0.02) 100%); -`; - -const SignalsWrapper = styled.div` - display: flex; - align-items: center; - gap: 4px; -`; - -const SignalText = styled(Text)` - color: rgba(249, 249, 249, 0.8); - font-size: 10px; - text-transform: capitalize; -`; - -const TextWrapper = styled.div` - display: flex; - flex-direction: column; - height: 36px; - justify-content: space-between; -`; - -const IconsContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - margin-right: 16px; -`; - -const IconButton = styled(Button)<{ $expand?: boolean }>` - transition: background 0.3s ease 0s, transform 0.3s ease 0s; - transform: ${({ $expand }) => ($expand ? 'rotate(-180deg)' : 'rotate(0deg)')}; -`; - -const ConfiguredDestinationsListItem: React.FC<{ item: ConfiguredDestination; isLastItem: boolean }> = ({ item, isLastItem }) => { - const [expand, setExpand] = useState(false); - const [deleteWarning, setDeleteWarning] = useState(false); +const ListItem: React.FC<{ item: ConfiguredDestination; isLastItem: boolean }> = ({ item, isLastItem }) => { const { removeConfiguredDestination } = useAppStore((state) => state); - - function renderSupportedSignals(item: ConfiguredDestination) { - const supportedSignals = item.exportedSignals; - const signals = Object.keys(supportedSignals); - const supportedSignalsList = signals.filter((signal) => supportedSignals[signal].supported); - - return Object.keys(supportedSignals).map( - (signal, index) => - supportedSignals[signal] && ( - - monitor - - {signal} - {index < supportedSignalsList.length - 1 && ·} - - ), - ); - } + const [deleteWarning, setDeleteWarning] = useState(false); return ( <> - - - - - destination - - - {item.displayName} - {renderSupportedSignals(item)} - - - - - setDeleteWarning(true)}> - delete - - - setExpand(!expand)}> - - - - - - {expand && ( - - - - + } + renderActions={() => ( + setDeleteWarning(true)}> + delete + )} - + /> {data.map(({ stored }) => ( - + ))} ); diff --git a/frontend/webapp/containers/main/sources/source-drawer-container/index.tsx b/frontend/webapp/containers/main/sources/source-drawer-container/index.tsx index b1feeeb42..5a86fbf4e 100644 --- a/frontend/webapp/containers/main/sources/source-drawer-container/index.tsx +++ b/frontend/webapp/containers/main/sources/source-drawer-container/index.tsx @@ -8,7 +8,7 @@ import { useDescribeSource, useSourceCRUD } from '@/hooks'; import OverviewDrawer from '../../overview/overview-drawer'; import { OVERVIEW_ENTITY_TYPES, type WorkloadId, type K8sActualSource } from '@/types'; import { ConditionDetails, DataCard, DataCardRow, DataCardFieldTypes } from '@/reuseable-components'; -import { ACTION, DATA_CARDS, getMainContainerLanguage, getProgrammingLanguageIcon, safeJsonStringify } from '@/utils'; +import { ACTION, BACKEND_BOOLEAN, DATA_CARDS, getMainContainerLanguage, getProgrammingLanguageIcon, safeJsonStringify } from '@/utils'; interface Props {} @@ -79,13 +79,17 @@ export const SourceDrawer: React.FC = () => { const { item } = selectedItem as { item: K8sActualSource }; + const hasPresenceOfOtherAgent = item.instrumentedApplicationDetails.conditions.some( + (condition) => condition.status === BACKEND_BOOLEAN.FALSE && condition.message.includes('device not added to any container due to the presence of another agent'), + ); + return ( item.instrumentedApplicationDetails.containers.map( (container) => ({ type: DataCardFieldTypes.SOURCE_CONTAINER, width: '100%', - value: JSON.stringify(container), + value: JSON.stringify({ ...container, hasPresenceOfOtherAgent }), } as DataCardRow), ) || [] ); diff --git a/frontend/webapp/reuseable-components/condition-details/index.tsx b/frontend/webapp/reuseable-components/condition-details/index.tsx index 392a66c06..3c91cb800 100644 --- a/frontend/webapp/reuseable-components/condition-details/index.tsx +++ b/frontend/webapp/reuseable-components/condition-details/index.tsx @@ -60,7 +60,7 @@ export const ConditionDetails: React.FC = ({ conditions }) => { ({hasErrors ? errors.length : conditions.length}/{conditions.length}) - + {extend && ( diff --git a/frontend/webapp/reuseable-components/data-card/data-card-fields/index.tsx b/frontend/webapp/reuseable-components/data-card/data-card-fields/index.tsx index c09ce002e..7527d9928 100644 --- a/frontend/webapp/reuseable-components/data-card/data-card-fields/index.tsx +++ b/frontend/webapp/reuseable-components/data-card/data-card-fields/index.tsx @@ -1,7 +1,8 @@ import React, { useId } from 'react'; import styled from 'styled-components'; -import { ActiveStatus, Code, DataTab, Divider, InstrumentStatus, MonitorsIcons, Text, Tooltip } from '@/reuseable-components'; +import { ActiveStatus, Code, DataTab, Divider, InstrumentStatus, MonitorsIcons, NotificationNote, Text, Tooltip } from '@/reuseable-components'; import { capitalizeFirstLetter, getProgrammingLanguageIcon, parseJsonStringToPrettyString, safeJsonParse, WORKLOAD_PROGRAMMING_LANGUAGES } from '@/utils'; +import { NOTIFICATION_TYPE } from '@/types'; export enum DataCardFieldTypes { DIVIDER = 'divider', @@ -81,17 +82,35 @@ const renderValue = (type: DataCardRow['type'], value: DataCardRow['value']) => return ; case DataCardFieldTypes.SOURCE_CONTAINER: { - const { containerName, language, runtimeVersion } = safeJsonParse(value, { + const { containerName, language, runtimeVersion, otherAgent, hasPresenceOfOtherAgent } = safeJsonParse(value, { containerName: '-', language: WORKLOAD_PROGRAMMING_LANGUAGES.UNKNOWN, runtimeVersion: '-', + otherAgent: null, + hasPresenceOfOtherAgent: false, }); + // Determine if running concurrently is possible based on language and other_agent + const canRunInParallel = !hasPresenceOfOtherAgent && (language === WORKLOAD_PROGRAMMING_LANGUAGES.PYTHON || language === WORKLOAD_PROGRAMMING_LANGUAGES.JAVA); + return ( ( + + )} > diff --git a/frontend/webapp/reuseable-components/data-tab/index.tsx b/frontend/webapp/reuseable-components/data-tab/index.tsx index 71575cc7e..b9d79a6b7 100644 --- a/frontend/webapp/reuseable-components/data-tab/index.tsx +++ b/frontend/webapp/reuseable-components/data-tab/index.tsx @@ -1,24 +1,28 @@ -import React, { PropsWithChildren, useCallback } from 'react'; +import React, { Fragment, PropsWithChildren, useCallback, useState } from 'react'; import Image from 'next/image'; -import { FlexColumn } from '@/styles'; +import { FlexColumn, FlexRow } from '@/styles'; import styled, { css } from 'styled-components'; -import { ActiveStatus, MonitorsIcons, Text } from '@/reuseable-components'; +import { ActiveStatus, Divider, ExtendIcon, IconButton, MonitorsIcons, Text } from '@/reuseable-components'; interface Props extends PropsWithChildren { title: string; subTitle: string; logo: string; monitors?: string[]; + monitorsWithLabels?: boolean; isActive?: boolean; isError?: boolean; + withExtend?: boolean; + isExtended?: boolean; + renderExtended?: () => JSX.Element; + renderActions?: () => JSX.Element; onClick?: () => void; } const Container = styled.div<{ $withClick: boolean; $isError: Props['isError'] }>` display: flex; - align-items: center; + flex-direction: column; align-self: stretch; - gap: 8px; padding: 16px; width: calc(100% - 32px); border-radius: 16px; @@ -51,6 +55,7 @@ const Title = styled(Text)` overflow: hidden; white-space: nowrap; text-overflow: ellipsis; + font-size: 14px; `; const SubTitleWrapper = styled.div` @@ -71,45 +76,72 @@ const ActionsWrapper = styled.div` margin-left: auto; `; -export const DataTab: React.FC = ({ title, subTitle, logo, monitors, isActive, isError, onClick, children }) => { - const renderMonitors = useCallback(() => { - if (!monitors) return null; - - return ( - <> - {'•'} - - - ); - }, [monitors]); - - const renderActiveStatus = useCallback(() => { - if (typeof isActive !== 'boolean') return null; - - return ( - <> - {'•'} - - - ); - }, [isActive]); +export const DataTab: React.FC = ({ title, subTitle, logo, monitors, monitorsWithLabels, isActive, isError, withExtend, isExtended, renderExtended, renderActions, onClick }) => { + const [extend, setExtend] = useState(isExtended || false); + + const renderMonitors = useCallback( + (withSeperator: boolean) => { + if (!monitors || !monitors.length) return null; + + return ( + <> + {withSeperator && {'•'}} + + + ); + }, + [monitors], + ); + + const renderActiveStatus = useCallback( + (withSeperator: boolean) => { + if (typeof isActive !== 'boolean') return null; + + return ( + <> + {withSeperator && {'•'}} + + + ); + }, + [isActive], + ); return ( - - - - - - {title} - - {subTitle} - {renderMonitors()} - {renderActiveStatus()} - - - - {children} + + + + + + + {title} + + {subTitle && {subTitle}} + {renderMonitors(!!subTitle)} + {renderActiveStatus(!!monitors?.length)} + + + + + {renderActions && renderActions()} + {withExtend && ( + + + setExtend((prev) => !prev)}> + + + + )} + + + + {extend && renderExtended && ( + + + {renderExtended()} + + )} ); }; diff --git a/frontend/webapp/reuseable-components/extend-icon/index.tsx b/frontend/webapp/reuseable-components/extend-icon/index.tsx index c36caae5e..62b93d8e4 100644 --- a/frontend/webapp/reuseable-components/extend-icon/index.tsx +++ b/frontend/webapp/reuseable-components/extend-icon/index.tsx @@ -5,10 +5,11 @@ import styled from 'styled-components'; interface Props { extend: boolean; size?: number; - align?: 'left' | 'right'; + align?: 'left' | 'right' | 'center'; } const Icon = styled(Image)<{ $align?: Props['align'] }>` + margin: ${({ $align }) => ($align === 'right' ? 'auto 0 auto auto' : $align === 'left' ? 'auto auto auto 0' : 'auto')}; &.open { transform: rotate(180deg); } @@ -16,9 +17,8 @@ const Icon = styled(Image)<{ $align?: Props['align'] }>` transform: rotate(0deg); } transition: transform 0.3s; - margin-${({ $align }) => ($align === 'right' ? 'left' : 'right')}: auto; `; -export const ExtendIcon: React.FC = ({ extend, size = 14, align = 'right' }) => { +export const ExtendIcon: React.FC = ({ extend, size = 14, align = 'center' }) => { return ; }; diff --git a/frontend/webapp/reuseable-components/monitors-icons/index.tsx b/frontend/webapp/reuseable-components/monitors-icons/index.tsx index 9c580d451..ccd8ae1fa 100644 --- a/frontend/webapp/reuseable-components/monitors-icons/index.tsx +++ b/frontend/webapp/reuseable-components/monitors-icons/index.tsx @@ -1,5 +1,6 @@ import React from 'react'; import Image from 'next/image'; +import theme from '@/styles/theme'; import { FlexRow } from '@/styles'; import { capitalizeFirstLetter } from '@/utils'; import { Text, Tooltip } from '@/reuseable-components'; @@ -15,14 +16,18 @@ export const MonitorsIcons: React.FC = ({ monitors, withTooltips, withLab return ( {monitors.map((str) => { - const signal = str.toLocaleLowerCase(); + const signal = str.toLowerCase(); const signalDisplayName = capitalizeFirstLetter(signal); return ( {signal} - {withLabels && {signalDisplayName}} + {withLabels && ( + + {signalDisplayName} + + )} ); From 0f9d51d6cb1c5859506986ce41cf216ba2fec83e Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Thu, 19 Dec 2024 15:58:07 +0200 Subject: [PATCH 2/5] Refactor configuration handling to replace deprecated string values with boolean values for Clickhouse and Qryn destinations --- common/config/clickhouse.go | 4 ++-- common/config/qryn.go | 8 +++---- common/config/qryn_oss.go | 14 +++++++++++-- destinations/data/clickhouse.yaml | 9 +++----- destinations/data/gigapipe.yaml | 10 ++------- destinations/data/qryn.yaml | 10 ++------- docs/backends/clickhouse.mdx | 12 +++++------ docs/backends/gigapipe.mdx | 4 ++-- docs/backends/qryn.mdx | 4 ++-- .../compute-platform/useComputePlatform.ts | 21 +++++++++++++++++++ 10 files changed, 56 insertions(+), 40 deletions(-) diff --git a/common/config/clickhouse.go b/common/config/clickhouse.go index 3ed3ad5f9..9aa13c299 100644 --- a/common/config/clickhouse.go +++ b/common/config/clickhouse.go @@ -55,8 +55,8 @@ func (c *Clickhouse) ModifyConfig(dest ExporterConfigurer, currentConfig *Config exporterConfig["password"] = clickhousePassword } - createSchema, exists := dest.GetConfig()[clickhouseCreateSchema] - createSchemaBoolValue := exists && strings.ToLower(createSchema) == "create" + createSchema := dest.GetConfig()[clickhouseCreateSchema] + createSchemaBoolValue := strings.ToLower(createSchema) == "true" || strings.ToLower(createSchema) == "create" // create is deprecated, use true exporterConfig["create_schema"] = createSchemaBoolValue dbName, exists := dest.GetConfig()[clickhouseDatabaseName] diff --git a/common/config/qryn.go b/common/config/qryn.go index 8386110ec..f68de265a 100644 --- a/common/config/qryn.go +++ b/common/config/qryn.go @@ -45,7 +45,7 @@ func (g *Qryn) ModifyConfig(dest ExporterConfigurer, currentConfig *Config) erro if conf.passwordFieldName != "" { passwordPlaceholder = "${" + conf.passwordFieldName + "}" } - baseURL, err := parseURL(dest.GetConfig()[qrynHost], conf.key, passwordPlaceholder) + baseURL, err := parseURL(conf.host, conf.key, passwordPlaceholder) if err != nil { return errors.Join(err, errors.New("invalid qryn endpoint. gateway will not be configured with qryn")) } @@ -55,7 +55,7 @@ func (g *Qryn) ModifyConfig(dest ExporterConfigurer, currentConfig *Config) erro currentConfig.Exporters[rwExporterName] = GenericMap{ "endpoint": fmt.Sprintf("%s/api/v1/prom/remote/write", baseURL), "resource_to_telemetry_conversion": GenericMap{ - "enabled": dest.GetConfig()[resourceToTelemetryConversion] == "Yes", + "enabled": conf.resourceToTelemetryConversion, }, } metricsPipelineName := "metrics/qryn-" + dest.GetID() @@ -126,8 +126,8 @@ func (g *Qryn) getConfigs(dest ExporterConfigurer) qrynConf { return qrynConf{ host: dest.GetConfig()[qrynHost], key: dest.GetConfig()[qrynAPIKey], - addExporterName: dest.GetConfig()[qrynAddExporterName] == "Yes", - resourceToTelemetryConversion: dest.GetConfig()[resourceToTelemetryConversion] == "Yes", + addExporterName: dest.GetConfig()[qrynAddExporterName] == "true" || dest.GetConfig()[qrynAddExporterName] == "Yes", // yes is deprecated, use true + resourceToTelemetryConversion: dest.GetConfig()[resourceToTelemetryConversion] == "true" || dest.GetConfig()[resourceToTelemetryConversion] == "Yes", // yes is deprecated, use true secretsOptional: dest.GetConfig()[qrynSecretsOptional] == "1", passwordFieldName: dest.GetConfig()[qrynPasswordFieldName], } diff --git a/common/config/qryn_oss.go b/common/config/qryn_oss.go index b09b306d5..2eada2dca 100644 --- a/common/config/qryn_oss.go +++ b/common/config/qryn_oss.go @@ -23,9 +23,19 @@ func (d QrynOssDest) GetConfig() map[string]string { conf := d.ExporterConfigurer.GetConfig() conf[qrynHost] = conf[qrynOssHost] conf[qrynAPIKey] = conf[qrynOssUsername] - conf[resourceToTelemetryConversion] = conf[qrynOssresourceToTelemetryConversion] + // Yes/No are deperecated, use true/false + if conf[qrynOssresourceToTelemetryConversion] == "true" || conf[qrynOssresourceToTelemetryConversion] == "Yes" { + conf[resourceToTelemetryConversion] = "true" + } else { + conf[resourceToTelemetryConversion] = "false" + } + // Yes/No are deperecated, use true/false + if conf[qrynOssAddExporterName] == "true" || conf[qrynOssAddExporterName] == "Yes" { + conf[qrynAddExporterName] = "true" + } else { + conf[qrynAddExporterName] = "false" + } conf[qrynSecretsOptional] = "1" - conf[qrynAddExporterName] = conf[qrynOssAddExporterName] conf[qrynPasswordFieldName] = "QRYN_OSS_PASSWORD" return conf } diff --git a/destinations/data/clickhouse.yaml b/destinations/data/clickhouse.yaml index 26f9f565a..97158e01d 100644 --- a/destinations/data/clickhouse.yaml +++ b/destinations/data/clickhouse.yaml @@ -20,7 +20,7 @@ spec: componentProps: type: text required: true - placeholder: "http://host:port" + placeholder: 'http://host:port' tooltip: 'Clickhouse server address' - name: CLICKHOUSE_USERNAME displayName: Username @@ -39,14 +39,11 @@ spec: tooltip: 'If Clickhouse Authentication is used, provide the password' - name: CLICKHOUSE_CREATE_SCHEME displayName: Create Scheme - componentType: dropdown + componentType: checkbox componentProps: - values: - - Create - - Skip required: true tooltip: 'Should the destination create the schema for you?' - initialValue: Create + initialValue: true - name: CLICKHOUSE_DATABASE_NAME displayName: Database Name componentType: input diff --git a/destinations/data/gigapipe.yaml b/destinations/data/gigapipe.yaml index 7b71600ba..7c52e3d0f 100644 --- a/destinations/data/gigapipe.yaml +++ b/destinations/data/gigapipe.yaml @@ -35,19 +35,13 @@ spec: required: true - name: QRYN_RESOURCE_TO_TELEMETRY_CONVERSION displayName: Convert container attributes to labels - componentType: dropdown + componentType: checkbox componentProps: - values: - - "Yes" - - "No" required: false initialValue: Yes - name: QRYN_ADD_EXPORTER_NAME displayName: Add exporter name to labels - componentType: dropdown + componentType: checkbox componentProps: - values: - - "Yes" - - "No" required: false initialValue: Yes diff --git a/destinations/data/qryn.yaml b/destinations/data/qryn.yaml index 0397d4d61..93ac8135c 100644 --- a/destinations/data/qryn.yaml +++ b/destinations/data/qryn.yaml @@ -33,19 +33,13 @@ spec: type: text - name: QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION displayName: Convert container attributes to labels - componentType: dropdown + componentType: checkbox componentProps: - values: - - "Yes" - - "No" required: false initialValue: Yes - name: QRYN_OSS_ADD_EXPORTER_NAME displayName: Add exporter name to labels - componentType: dropdown + componentType: checkbox componentProps: - values: - - "Yes" - - "No" required: false initialValue: Yes diff --git a/docs/backends/clickhouse.mdx b/docs/backends/clickhouse.mdx index fb6e91e8c..cf89a980d 100644 --- a/docs/backends/clickhouse.mdx +++ b/docs/backends/clickhouse.mdx @@ -35,8 +35,8 @@ The benefit of this option is that you can see the value fast, without needing t The downside is that the schema may not be optimized for your specific use case, and may make changes more complicated. To use it: -- Odigos UI - When adding a new ClickHouse destination, select the `Create` Option under the `Create Scheme` field. -- Destination K8s Manifest - Set the `CLICKHOUSE_CREATE_SCHEME` setting to value `Create`. +- Odigos UI - When adding a new ClickHouse destination, select the `Create Scheme` checkbox field. +- Destination K8s Manifest - Set the `CLICKHOUSE_CREATE_SCHEME` setting to value `true`. The schema which will be used by default can be found [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/clickhouseexporter/example/default_ddl). @@ -54,8 +54,8 @@ This option is not recommended for production workloads: With this option, you are responsible for creating and managing the schema yourself. To use it: -- Odigos UI - In `Create Scheme` field, select the the `Skip` Option. -- Destination K8s Manifest - Set the `CLICKHOUSE_CREATE_SCHEME` setting to value `Skip`. +- Odigos UI - Unselect the `Create Scheme` checkbox field. +- Destination K8s Manifest - Set the `CLICKHOUSE_CREATE_SCHEME` setting to value `false`. The benefit of this option is that you have full control over the schema, and can optimize it for your specific use case. @@ -103,7 +103,7 @@ These are optional, keep empty if your ClickHouse server does not require authen ### Schema -- Create Schema - Set to `Skip` if you manage your own schema, or `Create` to have Odigos create the schema for you. See [Create Schema](#create-schema) for more details. +- Create Schema - Set to `false` if you manage your own schema, or `true` to have Odigos create the schema for you. See [Create Schema](#create-schema) for more details. - Database Name (Required) - The name of the Clickhouse Database where the telemetry data will be stored. The default is `otel`. The Database will not be created when not exists, so make sure you have created it before. - Table Names - Allows you to customize the names of the tables where the telemetry data will be stored. The default is `otel_traces` for traces and `otel_metrics` for metrics. @@ -140,7 +140,7 @@ metadata: namespace: odigos-system spec: data: - CLICKHOUSE_CREATE_SCHEME: + CLICKHOUSE_CREATE_SCHEME: # CLICKHOUSE_USERNAME: # Note: The commented fields above are optional. CLICKHOUSE_DATABASE_NAME: diff --git a/docs/backends/gigapipe.mdx b/docs/backends/gigapipe.mdx index fb9f9d203..ec9215049 100644 --- a/docs/backends/gigapipe.mdx +++ b/docs/backends/gigapipe.mdx @@ -56,8 +56,8 @@ metadata: spec: data: QRYN_API_KEY: - # QRYN_RESOURCE_TO_TELEMETRY_CONVERSION: - # QRYN_ADD_EXPORTER_NAME: + # QRYN_RESOURCE_TO_TELEMETRY_CONVERSION: + # QRYN_ADD_EXPORTER_NAME: # Note: The commented fields above are optional. QRYN_URL: destinationName: qryn diff --git a/docs/backends/qryn.mdx b/docs/backends/qryn.mdx index 1a7a31080..6e80ce270 100644 --- a/docs/backends/qryn.mdx +++ b/docs/backends/qryn.mdx @@ -49,8 +49,8 @@ spec: data: QRYN_OSS_URL: # QRYN_OSS_USERNAME: - # QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION: - # QRYN_OSS_ADD_EXPORTER_NAME: + # QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION: + # QRYN_OSS_ADD_EXPORTER_NAME: # Note: The commented fields above are optional. destinationName: qryn-oss # Uncomment the secretRef below if you are using the optional Secret. diff --git a/frontend/webapp/hooks/compute-platform/useComputePlatform.ts b/frontend/webapp/hooks/compute-platform/useComputePlatform.ts index 0253168f6..da943fe0c 100644 --- a/frontend/webapp/hooks/compute-platform/useComputePlatform.ts +++ b/frontend/webapp/hooks/compute-platform/useComputePlatform.ts @@ -45,6 +45,27 @@ export const useComputePlatform = (): UseComputePlatformHook => { return { ...item, type }; }), + destinations: data.computePlatform.destinations.map((item) => { + // Replace deprecated string values, with boolean values + const fields = + item.destinationType.type === 'clickhouse' + ? item.fields.replace('"CLICKHOUSE_CREATE_SCHEME":"Create"', '"CLICKHOUSE_CREATE_SCHEME":"true"').replace('"CLICKHOUSE_CREATE_SCHEME":"Skip"', '"CLICKHOUSE_CREATE_SCHEME":"false"') + : item.destinationType.type === 'qryn' + ? item.fields + .replace('"QRYN_ADD_EXPORTER_NAME":"Yes"', '"QRYN_ADD_EXPORTER_NAME":"true"') + .replace('"QRYN_ADD_EXPORTER_NAME":"No"', '"QRYN_ADD_EXPORTER_NAME":"false"') + .replace('"QRYN_RESOURCE_TO_TELEMETRY_CONVERSION":"Yes"', '"QRYN_RESOURCE_TO_TELEMETRY_CONVERSION":"true"') + .replace('"QRYN_RESOURCE_TO_TELEMETRY_CONVERSION":"No"', '"QRYN_RESOURCE_TO_TELEMETRY_CONVERSION":"false"') + : item.destinationType.type === 'qryn-oss' + ? item.fields + .replace('"QRYN_OSS_ADD_EXPORTER_NAME":"Yes"', '"QRYN_OSS_ADD_EXPORTER_NAME":"true"') + .replace('"QRYN_OSS_ADD_EXPORTER_NAME":"No"', '"QRYN_OSS_ADD_EXPORTER_NAME":"false"') + .replace('"QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION":"Yes"', '"QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION":"true"') + .replace('"QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION":"No"', '"QRYN_OSS_RESOURCE_TO_TELEMETRY_CONVERSION":"false"') + : item.fields; + + return { ...item, fields }; + }), }, }; }, [data]); From 0c6ba1534b95fa8d142679243b088528374d935f Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Thu, 19 Dec 2024 16:57:12 +0200 Subject: [PATCH 3/5] Refactor Clickhouse and Qryn configuration handling to use a dedicated function for boolean conversion, replacing deprecated string values --- common/config/clickhouse.go | 3 +-- common/config/qryn.go | 4 ++-- common/config/utils.go | 5 +++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/common/config/clickhouse.go b/common/config/clickhouse.go index 9aa13c299..32d591c28 100644 --- a/common/config/clickhouse.go +++ b/common/config/clickhouse.go @@ -56,8 +56,7 @@ func (c *Clickhouse) ModifyConfig(dest ExporterConfigurer, currentConfig *Config } createSchema := dest.GetConfig()[clickhouseCreateSchema] - createSchemaBoolValue := strings.ToLower(createSchema) == "true" || strings.ToLower(createSchema) == "create" // create is deprecated, use true - exporterConfig["create_schema"] = createSchemaBoolValue + exporterConfig["create_schema"] = getBooleanConfig(createSchema, "create") dbName, exists := dest.GetConfig()[clickhouseDatabaseName] if !exists { diff --git a/common/config/qryn.go b/common/config/qryn.go index f68de265a..4de118726 100644 --- a/common/config/qryn.go +++ b/common/config/qryn.go @@ -126,8 +126,8 @@ func (g *Qryn) getConfigs(dest ExporterConfigurer) qrynConf { return qrynConf{ host: dest.GetConfig()[qrynHost], key: dest.GetConfig()[qrynAPIKey], - addExporterName: dest.GetConfig()[qrynAddExporterName] == "true" || dest.GetConfig()[qrynAddExporterName] == "Yes", // yes is deprecated, use true - resourceToTelemetryConversion: dest.GetConfig()[resourceToTelemetryConversion] == "true" || dest.GetConfig()[resourceToTelemetryConversion] == "Yes", // yes is deprecated, use true + addExporterName: getBooleanConfig(dest.GetConfig()[qrynAddExporterName], "Yes"), + resourceToTelemetryConversion: getBooleanConfig(dest.GetConfig()[resourceToTelemetryConversion], "Yes"), secretsOptional: dest.GetConfig()[qrynSecretsOptional] == "1", passwordFieldName: dest.GetConfig()[qrynPasswordFieldName], } diff --git a/common/config/utils.go b/common/config/utils.go index c0d8aaac9..5cdc9d95d 100644 --- a/common/config/utils.go +++ b/common/config/utils.go @@ -92,3 +92,8 @@ func urlHostContainsPort(host string) bool { return strings.Contains(host, ":") } } + +func getBooleanConfig(currentValue string, deprecatedValue string) bool { + lowerCaseValue := strings.ToLower(currentValue) + return lowerCaseValue == "true" || lowerCaseValue == deprecatedValue // create is deprecated, use true +} From bed07399ec6ec30aa28f56847781f7d84961315f Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Thu, 19 Dec 2024 17:04:25 +0200 Subject: [PATCH 4/5] Refactor destination CRUD operations to ensure consistent handling of fields and improve readability --- .../webapp/hooks/destinations/useDestinationCRUD.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/webapp/hooks/destinations/useDestinationCRUD.ts b/frontend/webapp/hooks/destinations/useDestinationCRUD.ts index cc52de26d..4870b6617 100644 --- a/frontend/webapp/hooks/destinations/useDestinationCRUD.ts +++ b/frontend/webapp/hooks/destinations/useDestinationCRUD.ts @@ -75,8 +75,14 @@ export const useDestinationCRUD = (params?: Params) => { loading: cState.loading || uState.loading || dState.loading, destinations: data?.computePlatform.destinations || [], - createDestination: (destination: DestinationInput) => createDestination({ variables: { destination: { ...destination, fields: destination.fields.filter(({ value }) => value !== undefined) } } }), - updateDestination: (id: string, destination: DestinationInput) => updateDestination({ variables: { id, destination } }), - deleteDestination: (id: string) => deleteDestination({ variables: { id } }), + createDestination: (destination: DestinationInput) => { + createDestination({ variables: { destination: { ...destination, fields: destination.fields.filter(({ value }) => value !== undefined) } } }); + }, + updateDestination: (id: string, destination: DestinationInput) => { + updateDestination({ variables: { id, destination: { ...destination, fields: destination.fields.filter(({ value }) => value !== undefined) } } }); + }, + deleteDestination: (id: string) => { + deleteDestination({ variables: { id } }); + }, }; }; From b7c0866ad07ab26d3964782fd0b4af37b42b26c7 Mon Sep 17 00:00:00 2001 From: Ben Elferink Date: Thu, 19 Dec 2024 19:52:35 +0200 Subject: [PATCH 5/5] fix: remove unrelated comment --- common/config/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/config/utils.go b/common/config/utils.go index 5cdc9d95d..f9173bb46 100644 --- a/common/config/utils.go +++ b/common/config/utils.go @@ -95,5 +95,5 @@ func urlHostContainsPort(host string) bool { func getBooleanConfig(currentValue string, deprecatedValue string) bool { lowerCaseValue := strings.ToLower(currentValue) - return lowerCaseValue == "true" || lowerCaseValue == deprecatedValue // create is deprecated, use true + return lowerCaseValue == "true" || lowerCaseValue == deprecatedValue }