From 4eb6919e022cfb3ec2dfbd2ab336b1603a5887af Mon Sep 17 00:00:00 2001 From: Prabhat Sharma Date: Tue, 29 Sep 2026 07:10:28 -0700 Subject: [PATCH] fix(ingestion): restore Kinesis Firehose and GCP Pub/Sub tabs under Custom > Logs (#14916) --- scripts/translations/.translation_state.json | 2 + .../components/ingestion/logs/Index.spec.ts | 26 +++++++ web/src/components/ingestion/logs/Index.vue | 26 +++++++ .../ingestion/logs/KinesisFirehose.spec.ts | 76 +++++++++++++++++++ .../ingestion/logs/KinesisFirehose.vue | 53 +++++++++++++ .../ingestion/logs/ingestionIndex.spec.ts | 4 + .../shared/useIngestionRoutes.spec.ts | 35 +++++++++ .../composables/shared/useIngestionRoutes.ts | 17 +++++ web/src/locales/languages/ar-SA.json | 2 + web/src/locales/languages/de-DE.json | 2 + web/src/locales/languages/en-US.json | 2 + web/src/locales/languages/es-ES.json | 2 + web/src/locales/languages/fr-FR.json | 2 + web/src/locales/languages/it-IT.json | 2 + web/src/locales/languages/ja-JP.json | 2 + web/src/locales/languages/ko-KR.json | 2 + web/src/locales/languages/nl-NL.json | 2 + web/src/locales/languages/pl-PL.json | 2 + web/src/locales/languages/pt-PT.json | 2 + web/src/locales/languages/ru-RU.json | 2 + web/src/locales/languages/tr-TR.json | 2 + web/src/locales/languages/vi-VN.json | 2 + web/src/locales/languages/zh-CN.json | 2 + web/src/locales/languages/zh-TW.json | 2 + web/src/utils/routeTabMaps.spec.ts | 12 ++- web/src/utils/routeTabMaps.ts | 2 + 26 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 web/src/components/ingestion/logs/KinesisFirehose.spec.ts create mode 100644 web/src/components/ingestion/logs/KinesisFirehose.vue diff --git a/scripts/translations/.translation_state.json b/scripts/translations/.translation_state.json index e36d304a14..784dcdf7e2 100644 --- a/scripts/translations/.translation_state.json +++ b/scripts/translations/.translation_state.json @@ -9517,6 +9517,7 @@ "fluentbit": "b6344fe6e6115ccf", "fluentd": "4f2c848b37c5a944", "gactions": "fae83bd48c808f08", + "gcpLogs": "c54590f981ee31f1", "generateRUMTokenLabel": "475c7f1c1a5cff60", "generateRUMTokenMessage": "ea76eb1e37cb811f", "header": "a22bd608ff67405e", @@ -9649,6 +9650,7 @@ } }, "jenkins": "9a4d10e69361c7d6", + "kinesisFirehose": "d1e2ebf59ff37b7d", "languagesLabel": "73d87075dd9f09ac", "launchCloudFormationStack": "2e4bfaf27c788b70", "linuxUnixMacosManualInstall": "4cce8d7c825eec13", diff --git a/web/src/components/ingestion/logs/Index.spec.ts b/web/src/components/ingestion/logs/Index.spec.ts index 2040efee46..620c402c5a 100644 --- a/web/src/components/ingestion/logs/Index.spec.ts +++ b/web/src/components/ingestion/logs/Index.spec.ts @@ -129,7 +129,9 @@ describe("IngestLogs Component", () => { "curl", "fluentbit", "fluentd", + "kinesisfirehose", "vector", + "gcpLogs", "syslogNg", "splunkHec", "loongcollector", @@ -243,6 +245,30 @@ describe("IngestLogs Component", () => { tw.unmount(); }); + it("should push with org_identifier query when route is 'kinesisfirehose'", () => { + mockRouter.currentRoute.value.name = "kinesisfirehose"; + const tw = mount(IngestLogs, buildMountOptions()); + expect(mockRouter.push).toHaveBeenCalledWith({ + name: "kinesisfirehose", + query: { + org_identifier: store.state.selectedOrganization.identifier, + }, + }); + tw.unmount(); + }); + + it("should push with org_identifier query when route is 'gcpLogs'", () => { + mockRouter.currentRoute.value.name = "gcpLogs"; + const tw = mount(IngestLogs, buildMountOptions()); + expect(mockRouter.push).toHaveBeenCalledWith({ + name: "gcpLogs", + query: { + org_identifier: store.state.selectedOrganization.identifier, + }, + }); + tw.unmount(); + }); + it("should push with org_identifier query when route is 'syslogNg'", () => { mockRouter.currentRoute.value.name = "syslogNg"; const tw = mount(IngestLogs, buildMountOptions()); diff --git a/web/src/components/ingestion/logs/Index.vue b/web/src/components/ingestion/logs/Index.vue index 399f8c9e2e..8ffb680965 100644 --- a/web/src/components/ingestion/logs/Index.vue +++ b/web/src/components/ingestion/logs/Index.vue @@ -77,6 +77,30 @@ along with this program. If not, see . :icon="'img:' + getImageURL('images/ingestion/vector.png')" :label="t('ingestion.vector')" /> + + . + +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { mount } from "@vue/test-utils"; +import { createStore } from "vuex"; +import KinesisFirehose from "./KinesisFirehose.vue"; + +vi.mock("@/utils/zincutils", () => ({ + getEndPoint: vi.fn(() => ({ + url: "https://test.example.com:5080", + host: "test.example.com", + port: "5080", + protocol: "https", + tls: true, + })), + getIngestionURL: vi.fn(() => "https://test.example.com:5080"), +})); + +vi.mock("@/components/CopyContent.vue", () => ({ + default: { + name: "CopyContent", + props: ["content"], + template: "
{{ content }}
", + }, +})); + +describe("KinesisFirehose.vue", () => { + let wrapper: any; + + beforeEach(() => { + const store = createStore({ + state: { + selectedOrganization: { + identifier: "test-org", + }, + }, + }); + + wrapper = mount(KinesisFirehose, { + global: { + plugins: [store], + }, + props: { + currOrgIdentifier: "test-org", + currUserEmail: "test@example.com", + }, + }); + }); + + it("has the expected component name", () => { + expect(wrapper.vm.$options.name).toBe("KinesisFirehose"); + }); + + it("shows the org's Kinesis Firehose HTTP endpoint", () => { + expect(wrapper.find(".copy-content").text()).toContain( + "HTTP Endpoint: https://test.example.com:5080/aws/test-org/default/_kinesis_firehose", + ); + }); + + it("uses the basic passcode placeholder as the access key", () => { + expect(wrapper.vm.content).toContain("Access Key: [BASIC_PASSCODE]"); + }); +}); diff --git a/web/src/components/ingestion/logs/KinesisFirehose.vue b/web/src/components/ingestion/logs/KinesisFirehose.vue new file mode 100644 index 0000000000..60969abe54 --- /dev/null +++ b/web/src/components/ingestion/logs/KinesisFirehose.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/web/src/components/ingestion/logs/ingestionIndex.spec.ts b/web/src/components/ingestion/logs/ingestionIndex.spec.ts index 33a6715baa..c85a71296f 100644 --- a/web/src/components/ingestion/logs/ingestionIndex.spec.ts +++ b/web/src/components/ingestion/logs/ingestionIndex.spec.ts @@ -110,7 +110,9 @@ describe("IngestLogs Index Component", () => { "curl", "fluentbit", "fluentd", + "kinesisfirehose", "vector", + "gcpLogs", "syslogNg", "splunkHec", "loongcollector", @@ -306,7 +308,9 @@ describe("IngestLogs Index Component", () => { "curl", "fluentbit", "fluentd", + "kinesisfirehose", "vector", + "gcpLogs", "syslogNg", "splunkHec", "loongcollector", diff --git a/web/src/composables/shared/useIngestionRoutes.spec.ts b/web/src/composables/shared/useIngestionRoutes.spec.ts index b16e30bea4..b67fdd626e 100644 --- a/web/src/composables/shared/useIngestionRoutes.spec.ts +++ b/web/src/composables/shared/useIngestionRoutes.spec.ts @@ -33,6 +33,7 @@ vi.mock("@/components/ingestion/logs/FluentBit.vue", () => ({ default: {} })); vi.mock("@/components/ingestion/logs/Fluentd.vue", () => ({ default: {} })); vi.mock("@/components/ingestion/logs/Vector.vue", () => ({ default: {} })); vi.mock("@/components/ingestion/logs/Curl.vue", () => ({ default: {} })); +vi.mock("@/components/ingestion/logs/KinesisFirehose.vue", () => ({ default: {} })); vi.mock("@/components/ingestion/recommended/AWSConfig.vue", () => ({ default: {} })); vi.mock("@/components/ingestion/recommended/GCPConfig.vue", () => ({ default: {} })); vi.mock("@/components/ingestion/recommended/AzureConfig.vue", () => ({ default: {} })); @@ -206,6 +207,8 @@ describe("useIngestionRoutes", () => { expect(logRouteNames).toContain("logstash"); expect(logRouteNames).toContain("syslogNg"); expect(logRouteNames).toContain("loongcollector"); + expect(logRouteNames).toContain("kinesisfirehose"); + expect(logRouteNames).toContain("gcpLogs"); }); it("should have metrics routes under custom", () => { @@ -965,6 +968,38 @@ describe("useIngestionRoutes", () => { expect(typeof fluentbitRoute.beforeEnter).toBe("function"); }); + it("should have kinesisfirehose route with correct configuration", () => { + const routes = useIngestionRoutes(); + const customRoute = routes[0].children.find((child: any) => child.name === "custom"); + const logsRoute = customRoute.children.find((child: any) => child.name === "ingestLogs"); + const firehoseRoute = logsRoute.children.find( + (child: any) => child.name === "kinesisfirehose", + ); + + expect(firehoseRoute).toBeDefined(); + expect(firehoseRoute.path).toBe("kinesisfirehose"); + expect(firehoseRoute.component).toBeDefined(); + expect(typeof firehoseRoute.beforeEnter).toBe("function"); + }); + + it("should have gcpLogs route reusing the recommended GCP page", () => { + const routes = useIngestionRoutes(); + const customRoute = routes[0].children.find((child: any) => child.name === "custom"); + const logsRoute = customRoute.children.find((child: any) => child.name === "ingestLogs"); + const gcpLogsRoute = logsRoute.children.find((child: any) => child.name === "gcpLogs"); + const recommendedRoute = routes[0].children.find( + (child: any) => child.name === "recommended", + ); + const gcpConfigRoute = recommendedRoute.children.find( + (child: any) => child.name === "GCPConfig", + ); + + expect(gcpLogsRoute).toBeDefined(); + expect(gcpLogsRoute.path).toBe("gcp"); + expect(gcpLogsRoute.component).toBe(gcpConfigRoute.component); + expect(typeof gcpLogsRoute.beforeEnter).toBe("function"); + }); + it("should have prometheus route with correct configuration", () => { const routes = useIngestionRoutes(); const customRoute = routes[0].children.find((child: any) => child.name === "custom"); diff --git a/web/src/composables/shared/useIngestionRoutes.ts b/web/src/composables/shared/useIngestionRoutes.ts index 13a6180778..f8dd557041 100644 --- a/web/src/composables/shared/useIngestionRoutes.ts +++ b/web/src/composables/shared/useIngestionRoutes.ts @@ -23,6 +23,7 @@ import FluentBit from "@/components/ingestion/logs/FluentBit.vue"; import Fluentd from "@/components/ingestion/logs/Fluentd.vue"; import Vector from "@/components/ingestion/logs/Vector.vue"; import Curl from "@/components/ingestion/logs/Curl.vue"; +import KinesisFirehose from "@/components/ingestion/logs/KinesisFirehose.vue"; import AWSConfig from "@/components/ingestion/recommended/AWSConfig.vue"; import GCPConfig from "@/components/ingestion/recommended/GCPConfig.vue"; import AzureConfig from "@/components/ingestion/recommended/AzureConfig.vue"; @@ -199,6 +200,22 @@ const useIngestionRoutes = () => { routeGuard(to, from, next); }, }, + { + path: "kinesisfirehose", + name: "kinesisfirehose", + component: KinesisFirehose, + beforeEnter(to: any, from: any, next: any) { + routeGuard(to, from, next); + }, + }, + { + path: "gcp", + name: "gcpLogs", + component: GCPConfig, + beforeEnter(to: any, from: any, next: any) { + routeGuard(to, from, next); + }, + }, { path: "filebeat", name: "filebeat", diff --git a/web/src/locales/languages/ar-SA.json b/web/src/locales/languages/ar-SA.json index e0541754d9..ca9620f04b 100644 --- a/web/src/locales/languages/ar-SA.json +++ b/web/src/locales/languages/ar-SA.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "سجلات GCP عبر (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/de-DE.json b/web/src/locales/languages/de-DE.json index dcc1c126f9..ca05c80888 100644 --- a/web/src/locales/languages/de-DE.json +++ b/web/src/locales/languages/de-DE.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "GCP Logs über (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/en-US.json b/web/src/locales/languages/en-US.json index 7b8e9739f4..f92179b8aa 100644 --- a/web/src/locales/languages/en-US.json +++ b/web/src/locales/languages/en-US.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "GCP Logs via (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/es-ES.json b/web/src/locales/languages/es-ES.json index 21e92fe92f..f60a3916cd 100644 --- a/web/src/locales/languages/es-ES.json +++ b/web/src/locales/languages/es-ES.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Logs de GCP vía (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/fr-FR.json b/web/src/locales/languages/fr-FR.json index a1194a7c21..3d67d2ebdf 100644 --- a/web/src/locales/languages/fr-FR.json +++ b/web/src/locales/languages/fr-FR.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Logs GCP via (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/it-IT.json b/web/src/locales/languages/it-IT.json index d80ccaa5de..92e069060b 100644 --- a/web/src/locales/languages/it-IT.json +++ b/web/src/locales/languages/it-IT.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Log GCP tramite (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/ja-JP.json b/web/src/locales/languages/ja-JP.json index 249cb547e5..5eec461625 100644 --- a/web/src/locales/languages/ja-JP.json +++ b/web/src/locales/languages/ja-JP.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "GCP ログ (Pub/Sub 経由)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/ko-KR.json b/web/src/locales/languages/ko-KR.json index 4007176015..f0f5eb359e 100644 --- a/web/src/locales/languages/ko-KR.json +++ b/web/src/locales/languages/ko-KR.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Pub/Sub을 통한 GCP 로그", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/nl-NL.json b/web/src/locales/languages/nl-NL.json index eae776273e..ff603cf3ba 100644 --- a/web/src/locales/languages/nl-NL.json +++ b/web/src/locales/languages/nl-NL.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "GCP Logboeken via (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/pl-PL.json b/web/src/locales/languages/pl-PL.json index aeaf640659..045d0e7121 100644 --- a/web/src/locales/languages/pl-PL.json +++ b/web/src/locales/languages/pl-PL.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Logi GCP przez (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/pt-PT.json b/web/src/locales/languages/pt-PT.json index f89af96939..fc74fc7268 100644 --- a/web/src/locales/languages/pt-PT.json +++ b/web/src/locales/languages/pt-PT.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Registros do GCP via (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/ru-RU.json b/web/src/locales/languages/ru-RU.json index ff98ceba17..2cec3449c8 100644 --- a/web/src/locales/languages/ru-RU.json +++ b/web/src/locales/languages/ru-RU.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Логи GCP через (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/tr-TR.json b/web/src/locales/languages/tr-TR.json index c7420e861b..e0fd375ac5 100644 --- a/web/src/locales/languages/tr-TR.json +++ b/web/src/locales/languages/tr-TR.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Pub/Sub üzerinden GCP Günlükleri", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/vi-VN.json b/web/src/locales/languages/vi-VN.json index 555ee106bc..7a4e74213f 100644 --- a/web/src/locales/languages/vi-VN.json +++ b/web/src/locales/languages/vi-VN.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "Nhật ký GCP qua (Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/zh-CN.json b/web/src/locales/languages/zh-CN.json index 976e60162a..195662838f 100644 --- a/web/src/locales/languages/zh-CN.json +++ b/web/src/locales/languages/zh-CN.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "GCP 日志(通过 Pub/Sub)", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/locales/languages/zh-TW.json b/web/src/locales/languages/zh-TW.json index 641938649e..a37f968d6f 100644 --- a/web/src/locales/languages/zh-TW.json +++ b/web/src/locales/languages/zh-TW.json @@ -3748,6 +3748,8 @@ "logstash": "Logstash", "syslogNg": "Syslog-ng", "loongCollector": "LoongCollector", + "kinesisFirehose": "Kinesis Firehose", + "gcpLogs": "透過 (Pub/Sub) 的 GCP 日誌", "metrics": { "prometheus": "Prometheus", "vmagent": "vmagent", diff --git a/web/src/utils/routeTabMaps.spec.ts b/web/src/utils/routeTabMaps.spec.ts index b48b57e43d..89fea3e565 100644 --- a/web/src/utils/routeTabMaps.spec.ts +++ b/web/src/utils/routeTabMaps.spec.ts @@ -267,6 +267,14 @@ describe("resolveTab", () => { expect(resolveTab("ingestLogs", "vector", "curl")).toBe("vector"); }); + it("ingestLogs – kinesisfirehose", () => { + expect(resolveTab("ingestLogs", "kinesisfirehose", "curl")).toBe("kinesisfirehose"); + }); + + it("ingestLogs – gcpLogs", () => { + expect(resolveTab("ingestLogs", "gcpLogs", "curl")).toBe("gcpLogs"); + }); + it("ingestLogs – ingestLogsFromOtel", () => { expect(resolveTab("ingestLogs", "ingestLogsFromOtel", "curl")).toBe("ingestLogsFromOtel"); }); @@ -469,8 +477,8 @@ describe("ROUTE_TAB_MAPS", () => { expect(Object.keys(ROUTE_TAB_MAPS.ingestMetrics)).toHaveLength(7); }); - it("ingestLogs has 10 entries", () => { - expect(Object.keys(ROUTE_TAB_MAPS.ingestLogs)).toHaveLength(10); + it("ingestLogs has 12 entries", () => { + expect(Object.keys(ROUTE_TAB_MAPS.ingestLogs)).toHaveLength(12); }); it("billings has 4 entries", () => { diff --git a/web/src/utils/routeTabMaps.ts b/web/src/utils/routeTabMaps.ts index 8eb8dc2930..396a0344b8 100644 --- a/web/src/utils/routeTabMaps.ts +++ b/web/src/utils/routeTabMaps.ts @@ -119,6 +119,8 @@ const ROUTE_TAB_MAPS: Record> = { fluentbit: "fluentbit", fluentd: "fluentd", vector: "vector", + kinesisfirehose: "kinesisfirehose", + gcpLogs: "gcpLogs", ingestLogsFromOtel: "ingestLogsFromOtel", logstash: "logstash", syslogNg: "syslogNg",