diff --git a/App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics.ts b/App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics.ts index 81f1296e78..2d57948f80 100644 --- a/App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics.ts +++ b/App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics.ts @@ -12,7 +12,6 @@ import URL from "Common/Types/API/URL"; import { APP_API_URL } from "Common/UI/Config"; import AggregatedModel from "Common/Types/BaseDatabase/AggregatedModel"; import MetricsAggregationType from "Common/Types/Metrics/MetricsAggregationType"; -import Dictionary from "Common/Types/Dictionary"; import AggregatedResult from "Common/Types/BaseDatabase/AggregatedResult"; import MetricViewData from "Common/Types/Metrics/MetricViewData"; import OneUptimeDate from "Common/Types/Date"; @@ -35,8 +34,7 @@ export default class MetricUtil { projectId: ProjectUtil.getCurrentProjectId()!, time: metricViewData.startAndEndDate!, name: queryConfig.metricQueryData.filterData.metricName!, - attributes: queryConfig.metricQueryData.filterData - .attributes as Dictionary, + attributes: queryConfig.metricQueryData.filterData.attributes as any, }, aggregationType: (queryConfig.metricQueryData.filterData diff --git a/App/FeatureSet/Dashboard/src/Components/Monitor/MonitorIncidentMetrics.tsx b/App/FeatureSet/Dashboard/src/Components/Monitor/MonitorIncidentMetrics.tsx index 6bf5ae04aa..773991563e 100644 --- a/App/FeatureSet/Dashboard/src/Components/Monitor/MonitorIncidentMetrics.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Monitor/MonitorIncidentMetrics.tsx @@ -5,6 +5,7 @@ import React, { useState, } from "react"; import ObjectID from "Common/Types/ObjectID"; +import Search from "Common/Types/BaseDatabase/Search"; import IncidentMetricType from "Common/Types/Incident/IncidentMetricType"; import IncidentMetricTypeUtil from "Common/Utils/Incident/IncidentMetricType"; import MetricView from "../Metrics/MetricView"; @@ -60,7 +61,7 @@ const MonitorIncidentMetrics: FunctionComponent = ( filterData: { metricName: metricType, attributes: { - monitorIds: props.monitorId.toString(), + monitorIds: new Search(props.monitorId.toString()), projectId: ProjectUtil.getCurrentProjectId()?.toString() || "", }, aggegationType: diff --git a/Common/Server/Services/IncidentService.ts b/Common/Server/Services/IncidentService.ts index 8d6dfb12dd..d90920a9ee 100644 --- a/Common/Server/Services/IncidentService.ts +++ b/Common/Server/Services/IncidentService.ts @@ -2287,23 +2287,33 @@ ${incidentSeverity.name} const metricTypesMap: Dictionary = {}; // common attributes shared by all incident metrics + // All values must be strings for ClickHouse Map(String, String) storage. + // Arrays are joined as comma-separated strings. const baseMetricAttributes: JSONObject = { incidentId: data.incidentId.toString(), projectId: incident.projectId.toString(), monitorIds: - incident.monitors?.map((monitor: Monitor) => { - return monitor._id?.toString(); - }) || [], + ( + incident.monitors + ?.map((monitor: Monitor) => { + return monitor._id?.toString(); + }) + .filter(Boolean) || [] + ).join(", "), monitorNames: - incident.monitors?.map((monitor: Monitor) => { - return monitor.name?.toString(); - }) || [], + ( + incident.monitors + ?.map((monitor: Monitor) => { + return monitor.name?.toString(); + }) + .filter(Boolean) || [] + ).join(", "), incidentSeverityId: incident.incidentSeverity?._id?.toString(), incidentSeverityName: incident.incidentSeverity?.name?.toString(), - ownerUserIds: ownerUserIds, - ownerUserNames: ownerUserNames, - ownerTeamIds: ownerTeamIds, - ownerTeamNames: ownerTeamNames, + ownerUserIds: ownerUserIds.join(", "), + ownerUserNames: ownerUserNames.join(", "), + ownerTeamIds: ownerTeamIds.join(", "), + ownerTeamNames: ownerTeamNames.join(", "), }; const incidentCountMetric: Metric = new Metric(); diff --git a/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts b/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts index 26b7d4f05b..ac23b07045 100644 --- a/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +++ b/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts @@ -419,23 +419,33 @@ export default class StatementGenerator { tableColumn.type === TableColumnType.MapStringString && typeof value === "object" ) { - const mapValue: Record = value as Record< - string, - string - >; + const mapValue: Record> = + value as Record>; for (const mapKey in mapValue) { if (mapValue[mapKey] === undefined) { continue; } - whereStatement.append( - SQL`AND ${key}[${{ - value: mapKey, - type: TableColumnType.Text, - }}] = ${{ - value: mapValue[mapKey] as string, - type: TableColumnType.Text, - }}`, - ); + if (mapValue[mapKey] instanceof Search) { + whereStatement.append( + SQL`AND ${key}[${{ + value: mapKey, + type: TableColumnType.Text, + }}] ILIKE ${{ + value: mapValue[mapKey] as Search, + type: TableColumnType.Text, + }}`, + ); + } else { + whereStatement.append( + SQL`AND ${key}[${{ + value: mapKey, + type: TableColumnType.Text, + }}] = ${{ + value: mapValue[mapKey] as string, + type: TableColumnType.Text, + }}`, + ); + } } } else if ( (tableColumn.type === TableColumnType.JSON || diff --git a/Common/Types/Metrics/MetricsQuery.ts b/Common/Types/Metrics/MetricsQuery.ts index 36a05c0203..ef3c4f7699 100644 --- a/Common/Types/Metrics/MetricsQuery.ts +++ b/Common/Types/Metrics/MetricsQuery.ts @@ -1,9 +1,10 @@ +import Search from "../BaseDatabase/Search"; import Dictionary from "../Dictionary"; import MetricsAggregationType from "./MetricsAggregationType"; export default interface MetricsQuery { metricName: string; - attributes: Dictionary; + attributes: Dictionary>; aggegationType: MetricsAggregationType; aggregateBy: Dictionary;