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",