Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/manager/apps/hpc-vmware-vsphere/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"test:coverage": "manager-test --config vitest.config.mjs run --coverage"
},
"dependencies": {
"@ovh-ux/logs-to-customer": "^1.11.0",
"@ovh-ux/logs-to-customer": "1.12.0",
"@ovh-ux/manager-common-translations": "^0.29.0",
"@ovh-ux/manager-config": "^8.9.0",
"@ovh-ux/manager-core-api": "^0.21.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/manager/apps/okms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"dependencies": {
"@hookform/resolvers": "5.2.1",
"@ovh-ux/logs-to-customer": "^1.11.0",
"@ovh-ux/logs-to-customer": "1.12.0",
"@ovh-ux/manager-billing-informations": "^1.6.6",
"@ovh-ux/manager-common-translations": "^0.29.0",
"@ovh-ux/manager-config": "^8.9.0",
Expand Down
1 change: 0 additions & 1 deletion packages/manager/apps/web-domains/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"test": "manager-test run"
},
"dependencies": {
"@ovh-ux/logs-to-customer": "^1.11.0",
"@ovh-ux/manager-common-translations": "^0.29.0",
"@ovh-ux/manager-config": "^8.9.0",
"@ovh-ux/manager-core-api": "^0.19.4",
Expand Down
7 changes: 7 additions & 0 deletions packages/manager/modules/logs-to-customer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ This module provides the necessary pages and components to add the "Logs to Cust
- Logs live tail
- Create, read, update, and delete subscriptions to data-streams

## Version Compatibility

| Version | Design System | Component Library | Last Stable |
|---------|---------------|-------------------|-------------|
| v1.x | ODS 18 | MRC | 1.12.0 |
| v2.x | ODS 19 | MUK | latest |

## Configuration

### Add the package to your uapp
Expand Down
29 changes: 16 additions & 13 deletions packages/manager/modules/logs-to-customer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ovh-ux/logs-to-customer",
"version": "1.12.0",
"version": "2.0.0-beta.0",
"description": "OVHcloud - observability - logs to customer module",
"license": "BSD-3-Clause",
"author": "OVH SAS",
Expand All @@ -15,7 +15,8 @@
"./vite-config": {
"import": "./vite-config-consumer.mjs"
},
"./dist/style.css": "./dist/style.css"
"./dist/style.css": "./dist/style.css",
"./package.json": "./package.json"
},
"main": "dist/src/lib.js",
"types": "dist/types/src/lib.d.ts",
Expand All @@ -31,21 +32,23 @@
"build": "vite build",
"dev": "vite build",
"dev:watch": "vite build --watch",
"lint": "manager-lint --config eslint.config.mjs src/**.ts src/**/**.ts src/**/**.tsx",
"lint:fix": "manager-lint --fix --config eslint.config.mjs src/**.ts src/**/**.ts src/**/**.tsx",
"lint:modern": "manager-lint --config eslint.config.mjs src",
"lint:modern:fix": "manager-lint --fix --config eslint.config.mjs src",
"prepare": "tsc && vite build",
"test": "manager-test run",
"test:coverage": "manager-test run --coverage"
},
"devDependencies": {
"@ovh-ux/manager-core-api": "^0.21.2",
"@ovh-ux/manager-core-test-utils": "^0.11.8",
"@ovh-ux/manager-react-components": "2.43.1",
"@ovh-ux/manager-config": "*",
"@ovh-ux/manager-core-api": "*",
"@ovh-ux/manager-core-test-utils": "*",
"@ovh-ux/manager-react-shell-client": "1.0.1",
"@ovh-ux/manager-static-analysis-kit": "*",
"@ovh-ux/manager-tests-setup": "latest",
"@ovh-ux/manager-vite-config": "^0.15.6",
"@ovhcloud/ods-components": "18.6.4",
"@ovhcloud/ods-themes": "18.6.4",
"@ovh-ux/manager-vite-config": "*",
"@ovh-ux/muk": "*",
"@ovhcloud/ods-react": "19.5.0",
"@ovhcloud/ods-themes": "19.5.0",
"@tanstack/react-virtual": "3.10.9",
"date-fns": "~4.1.0",
"element-internals-polyfill": "^1.3.11",
Expand All @@ -57,10 +60,10 @@
"@ovh-ux/manager-config": "^8.6.8",
"@ovh-ux/manager-core-api": "^0.19.1",
"@ovh-ux/manager-core-utils": "^0.3.0",
"@ovh-ux/manager-react-components": "^2.43.1",
"@ovh-ux/manager-react-shell-client": "^0.11.2",
"@ovhcloud/ods-components": "^18.6.4",
"@ovhcloud/ods-themes": "^18.6.4",
"@ovh-ux/muk": "^1.2.0",
"@ovhcloud/ods-react": "^19.5.0",
"@ovhcloud/ods-themes": "^19.5.0",
"@tanstack/react-query": "^5.51.21",
"@tanstack/react-virtual": "^3.10.9",
"date-fns": "~4.1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createContext } from 'react';

import { LogApiVersion } from '@/data/types/apiVersion';
import { LogKind } from '@/data/types/dbaas/logs';
import { ApiUrls, LogIamActions } from '@/LogsToCustomer.props';
import { LogApiVersion } from '@/data/types/apiVersion';
import { LogKind } from '@/data/types/dbaas/logs/Logs.type';

export interface LogProviderProps {
currentLogKind?: LogKind;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import React, { useEffect, useMemo, useState } from 'react';
import React, { useMemo, useState } from 'react';

import { useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';

import { OdsSelect, OdsSpinner, OdsText } from '@ovhcloud/ods-components/react';
import { Select, SelectContent, SelectControl, Spinner, Text } from '@ovhcloud/ods-react';

import {
ButtonType,
PageLocation,
useOvhTracking,
} from '@ovh-ux/manager-react-shell-client';
import { ButtonType, PageLocation, useOvhTracking } from '@ovh-ux/manager-react-shell-client';

import { LogsContext } from '@/LogsToCustomer.context';
import { ApiUrls, LogIamActions } from '@/LogsToCustomer.props';
import ApiError from '@/components/apiError/ApiError.component';
import { NAMESPACES } from '@/LogsToCustomer.translations';
import ApiError from '@/components/api-error/ApiError.component';
import { getLogKindsQueryKey, useLogKinds } from '@/data/hooks/useLogKinds';
import { LogApiVersion } from '@/data/types/apiVersion';
import { LogKind } from '@/data/types/dbaas/logs';
import { LogKind } from '@/data/types/dbaas/logs/Logs.type';
import useLogTrackingActions from '@/hooks/useLogTrackingActions';
import { ZoomedInOutProvider } from '@/hooks/useZoomedInOut';
import { LogsActionEnum } from '@/types/logsTracking';
import { LogsToCustomerRoutes } from '@/routes/routes';
import { NAMESPACES } from '@/LogsToCustomer.translations';
import { LogsActionEnum } from '@/types/logsTracking';

export interface ILogsToCustomerModule {
logApiUrls: ApiUrls;
Expand All @@ -41,45 +37,43 @@ export function LogsToCustomerModule({
trackingOptions = undefined,
}: ILogsToCustomerModule) {
const queryClient = useQueryClient();
const [currentLogKind, setCurrentLogKind] = useState<LogKind>();
const { t } = useTranslation(NAMESPACES.LOG_KIND);
const { trackClick } = useOvhTracking();
const selectKindLogsAccess = useLogTrackingActions(
LogsActionEnum.select_kind_logs_access,
);
const { data: logKinds, error, isPending } = useLogKinds({
const selectKindLogsAccess = useLogTrackingActions(LogsActionEnum.select_kind_logs_access);
const {
data: logKinds,
error,
isPending,
} = useLogKinds({
logKindUrl: logApiUrls.logKind,
apiVersion: logApiVersion,
});

useEffect(() => {
if (!isPending && logKinds && logKinds.length > 0)
setCurrentLogKind(logKinds[0]);
}, [logKinds, isPending]);
const defaultLogKind = useMemo(
() => (logKinds && logKinds.length > 0 ? logKinds[0] : undefined),
[logKinds],
);

const [currentLogKind, setCurrentLogKind] = useState<LogKind | undefined>(defaultLogKind);

const effectiveLogKind = currentLogKind ?? defaultLogKind;

const LogsContextValues = useMemo(
() => ({
currentLogKind,
currentLogKind: effectiveLogKind,
logApiUrls,
logApiVersion,
logIamActions,
resourceURN,
trackingOptions,
}),
[
currentLogKind,
logApiUrls,
logApiVersion,
logIamActions,
resourceURN,
trackingOptions,
],
[effectiveLogKind, logApiUrls, logApiVersion, logIamActions, resourceURN, trackingOptions],
);

if (isPending)
return (
<div className="flex py-8">
<OdsSpinner size="md" data-testid="logKinds-spinner" />
<Spinner size="md" data-testid="logKinds-spinner" />
</div>
);

Expand All @@ -97,32 +91,26 @@ export function LogsToCustomerModule({
);

if (logKinds.length === 0)
return (
<OdsText preset="paragraph">
{t('log_kind_empty_state_description')}
</OdsText>
);
return <Text preset="paragraph">{t('log_kind_empty_state_description')}</Text>;

if (!currentLogKind)
return (
<OdsText preset="paragraph">{t('log_kind_no_kind_selected')}</OdsText>
);
if (!effectiveLogKind) return <Text preset="paragraph">{t('log_kind_no_kind_selected')}</Text>;

const selectItems = logKinds.map((k) => ({
label: k.displayName,
value: k.kindId,
}));

return (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<OdsText preset="paragraph">
{t('log_kind_selector_select_label')}
</OdsText>
<OdsSelect
className="w-full md:w-96 "
<Text preset="paragraph">{t('log_kind_selector_select_label')}</Text>
<Select
className="w-96 max-w-full"
name="select-log-kind"
isDisabled={logKinds.length === 1}
value={currentLogKind?.kindId}
onOdsChange={(event) => {
const newLogKind = logKinds.find(
(k) => k.kindId === event.detail.value,
);
disabled={logKinds.length === 1}
value={effectiveLogKind?.kindId ? [effectiveLogKind.kindId] : []}
onValueChange={(detail) => {
const newLogKind = logKinds.find((k) => k.kindId === detail?.value?.[0]);
if (newLogKind) {
setCurrentLogKind(newLogKind);
trackClick({
Expand All @@ -133,18 +121,12 @@ export function LogsToCustomerModule({
});
}
}}
data-testid={'logKindSelect'}
data-testid="logKindSelect"
items={selectItems}
>
{logKinds.map((k) => (
<option
key={k.kindId}
value={k.kindId}
data-testid={'logKindOption'}
>
{k.displayName}
</option>
))}
</OdsSelect>
<SelectControl />
<SelectContent />
</Select>
</div>
<LogsContext.Provider value={LogsContextValues}>
<ZoomedInOutProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LogKind } from '@/data/types/dbaas/logs';
import { LogKind } from '@/data/types/dbaas/logs/Logs.type';

export const logKindsMock: LogKind[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ClusterRetention, RetentionTypeEnum } from '@/data/types/dbaas/logs';
import { ClusterRetention, RetentionTypeEnum } from '@/data/types/dbaas/logs/Logs.type';

export const logRetentionsMock: ClusterRetention[] = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ export const LogServicesError = 'log services error';
export const getLogServicesMocks = ({
isLogServicesKO,
nbLogServices = logServicesMock.length,
}: GetLogServicesMocksParams): Handler[] => [
{
url: '/dbaas/logs',
response: isLogServicesKO
? { message: LogServicesError }
: logServicesMock.slice(0, nbLogServices),
status: isLogServicesKO ? 500 : 200,
api: 'v6',
},
];
}: GetLogServicesMocksParams): Handler[] => {
const services = logServicesMock.slice(0, nbLogServices);
return [
{
url: '/dbaas/logs',
response: isLogServicesKO ? { message: LogServicesError } : services,
icebergResponse: isLogServicesKO ? { message: LogServicesError } : services,
headers: { 'x-pagination-elements': `${services.length}` },
status: isLogServicesKO ? 500 : 200,
api: 'v6',
delay: 100,
},
];
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Service, ServicePlanEnum, ServiceStateEnum } from '@/data/types/dbaas/logs';
import { Service, ServicePlanEnum, ServiceStateEnum } from '@/data/types/dbaas/logs/Logs.type';

export const logServicesMock: Service[] = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ export const getLogStreamsMocks = ({ isLogStreamsKO }: GetLogStreamsMocksParams)
{
url: '/dbaas/logs/:serviceName/output/graylog/stream',
response: isLogStreamsKO ? { message: LogStreamsError } : logStreamsMock,
icebergResponse: isLogStreamsKO ? { message: LogStreamsError } : logStreamsMock,
headers: { 'x-pagination-elements': `${logStreamsMock.length}` },
status: isLogStreamsKO ? 500 : 200,
api: 'v6',
delay: 100,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
StreamColdStorageCompressionEnum,
StreamColdStorageContentEnum,
StreamColdStorageTargetEnum,
} from '@/data/types/dbaas/logs';
} from '@/data/types/dbaas/logs/Logs.type';

export const logStreamsMock: Stream[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Url, UrlTypeEnum } from '@/data/types/dbaas/logs';
import { Url, UrlTypeEnum } from '@/data/types/dbaas/logs/Logs.type';

export const logStreamUrlMock: Url[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LogSubscription, LogSubscriptionResource } from '@/data/types/dbaas/logs';
import { LogSubscription, LogSubscriptionResource } from '@/data/types/dbaas/logs/Logs.type';

export const logSubscriptionsMock: LogSubscription[] = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TemporaryLogsLink } from '@/data/types/dbaas/logs';
import { TemporaryLogsLink } from '@/data/types/dbaas/logs/Logs.type';

export const logTailUrlMock: TemporaryLogsLink = {
url: 'https://get.logs.ovh.com/mock/messages',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ describe('LogsToCustomer module', () => {
});

it('should render the log kind select when there is 2 or more log kinds', async () => {
await renderTest();
const { container } = await renderTest();

await waitFor(() => expect(screen.queryByTestId('logKindSelect')).toBeInTheDocument(), {
timeout: 10_000,
});
expect(screen.queryByText('log_kind_selector_select_label')).toBeInTheDocument();
expect(screen.queryAllByTestId('logKindOption')).toHaveLength(logKindsMock.length);
// ODS 19 Select renders options inside a native <select> element
const selectElement = container.querySelector('select[name="select-log-kind"]');
expect(selectElement?.querySelectorAll('option')).toHaveLength(logKindsMock.length);
});
});
Loading
Loading