diff --git a/hack/docker-compose/loki/promtail-config.yml b/hack/docker-compose/loki/promtail-config.yml index 585d71f81..60e47d3ec 100644 --- a/hack/docker-compose/loki/promtail-config.yml +++ b/hack/docker-compose/loki/promtail-config.yml @@ -46,5 +46,5 @@ scrape_configs: k8s_namespace_name: kube-public log_type: application __path__: /var/log/*log - kubernetes_pod_name: alertmanager-main-0 - kubernetes_container_name: test-container + kubernetes_pod_name: kube-public-0 + kubernetes_container_name: test-container-kube diff --git a/web/locales/en/plugin__logging-view-plugin.json b/web/locales/en/plugin__logging-view-plugin.json index a601aed80..160aa32f4 100644 --- a/web/locales/en/plugin__logging-view-plugin.json +++ b/web/locales/en/plugin__logging-view-plugin.json @@ -1,4 +1,9 @@ { + "No namespaces found": "No namespaces found", + "No pods found in the selected namespace(s)": "No pods found in the selected namespace(s)", + "No pods found": "No pods found", + "No containers found in the selected namespace(s)": "No containers found in the selected namespace(s)", + "No containers found": "No containers found", "Label {{tenantKey}} is required to display the alert metrics": "label {{tenantKey}} is required to display the alert metrics", "Select a smaller time range to reduce the number of results": "Select a smaller time range to reduce the number of results", "Select a namespace, pod, or container filter to improve the query performance": "Select a namespace, pod, or container filter to improve the query performance", @@ -18,6 +23,7 @@ "Explain Log Volume": "Explain Log Volume", "Search by {{attributeName}}": "Search by {{attributeName}}", "Attribute": "Attribute", + "No results found": "No results found", "Filter by {{attributeName}}": "Filter by {{attributeName}}", "Search": "Search", "Loading...": "Loading...", @@ -141,4 +147,4 @@ "Aggregated Logs": "Aggregated Logs", "Logs": "Logs", "Please select a namespace": "Please select a namespace" -} +} \ No newline at end of file diff --git a/web/src/attribute-filters.tsx b/web/src/attribute-filters.tsx index 44f64a934..ed38fe270 100644 --- a/web/src/attribute-filters.tsx +++ b/web/src/attribute-filters.tsx @@ -107,7 +107,11 @@ const lokiSeriesDataSource = mapper: (data: SeriesResponse) => Array<{ option: string; value: string }>; }) => async (): Promise> => { - const { abort, request } = executeSeries({ match, tenant, config }); + const { abort, request } = executeSeries({ + match: match.filter(notEmptyString), + tenant, + config, + }); if (resourceAbort.lokiSeries) { resourceAbort.lokiSeries(); @@ -142,12 +146,14 @@ const resourceDataSource = const { request, abort } = cancellableFetch(endpoint); - const abortFunction = resourceAbort[resource]; + const abortKey = namespace ? `${resource}-${namespace}` : resource; + + const abortFunction = resourceAbort[abortKey]; if (abortFunction) { abortFunction(); } - resourceAbort[resource] = abort; + resourceAbort[abortKey] = abort; const response = await request(); @@ -211,10 +217,12 @@ export const availableAttributes = ({ tenant, config, schema, + t, }: { tenant: string; config: Config; schema: Schema; + t: (key: string) => string; }): AttributeList => { const { namespaceLabel, podLabel, containerLabel } = getAttributeLabels(schema); @@ -249,19 +257,35 @@ export const availableAttributes = ({ }, }), valueType: 'checkbox-select', + emptyStateMessage: t('No namespaces found'), }, { name: 'Pods', label: podLabel, id: 'pod', - options: getPodAttributeOptions(tenant, config, schema), + options: (filters) => { + const selectedNamespaces = filters?.namespace ? Array.from(filters.namespace) : undefined; + + return getPodAttributeOptions(tenant, config, schema, selectedNamespaces)(); + }, valueType: 'checkbox-select', + emptyStateMessage: (filters) => { + const selectedNamespaces = filters?.namespace ? Array.from(filters.namespace) : undefined; + if (selectedNamespaces && selectedNamespaces.length > 0) { + return t('No pods found in the selected namespace(s)'); + } + return t('No pods found'); + }, }, { name: 'Containers', label: containerLabel, id: 'container', - options: getContainerAttributeOptions(tenant, config, schema), + options: (filters) => { + const selectedNamespaces = filters?.namespace ? Array.from(filters.namespace) : undefined; + + return getContainerAttributeOptions(tenant, config, schema, selectedNamespaces)(); + }, expandSelection: (selections) => { const podSelections = new Set(); const containerSelections = new Set(); @@ -313,6 +337,13 @@ export const availableAttributes = ({ return filters.pod.has(pod) && filters.container.has(container); }, valueType: 'checkbox-select', + emptyStateMessage: (filters) => { + const selectedNamespaces = filters?.namespace ? Array.from(filters.namespace) : undefined; + if (selectedNamespaces && selectedNamespaces.length > 0) { + return t('No containers found in the selected namespace(s)'); + } + return t('No containers found'); + }, }, ]; }; @@ -724,17 +755,51 @@ const getPodAttributeOptions = ( tenant: string, config: Config, schema: Schema, + namespaces?: Array, ): (() => Promise) => { const { podLabel } = getAttributeLabels(schema); + const namespacedPodsResources: Array> = []; + + // get pods in selected namespaces for users that have restricted access + for (const ns of namespaces || []) { + namespacedPodsResources.push(resourceDataSource({ resource: 'pods', namespace: ns })()); + } + + const namespaceLabel = getStreamLabelsFromSchema(schema).Namespace; + const namespacesQuery = + namespaces && namespaces.length > 0 ? `${namespaceLabel}=~"${namespaces.join('|')}"` : ''; + + const podResource = + namespaces && namespaces.length > 0 + ? namespacedPodsResources + : [ + resourceDataSource({ + resource: 'pods', + filter: (resource) => { + switch (tenant) { + case 'infrastructure': + return namespaceBelongsToInfrastructureTenant(resource.metadata?.namespace || ''); + case 'application': + return !namespaceBelongsToInfrastructureTenant( + resource.metadata?.namespace || '', + ); + } + + return true; + }, + })(), + ]; + return () => Promise.allSettled>([ lokiLabelValuesDataSource({ config, tenant, labelName: podLabel, + query: namespacesQuery ? `{ ${namespacesQuery} }` : undefined, })(), - resourceDataSource({ resource: 'pods' })(), + ...podResource, ]).then((results) => { const podOptions: Set