Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ai.notebooks): logs tab #14313

Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"attachedDataTitle": "Attacher des conteneurs de données",
"breadcrumb": "Conteneurs de données",
"attachedDataTitle": "Conteneurs de données",
"attachedDataDescription": "Si nécessaire, vous pouvez attacher des conteneurs Object Storage OVHcloud à votre notebook. Une fois attachés, ceux-ci seront temporairement chargés et mis en cache près de votre instance afin de réduire la latence et d’améliorer les performances. La bonne pratique est d’attacher un conteneur avec vos données entrantes et un autre avec vos données sortantes.",
"attachedDataInfoLink": "En savoir plus sur le stockage de données.",
"synchroniseDataButton": "Synchronisation globale des données",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"breadcrumb": "Logs",
"title": "Logs",
"description": "Pour vous aider à suivre et à piloter votre notebook, vous trouverez les derniers événements (logs) ci-dessous, quasiment en direct.",
"autoRefreshInputLabel": "Auto-Refresh"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as ai from '@/types/cloud/project/ai';

export const mockedDataSyncSpec: ai.volume.DataSyncSpec = {
direction: ai.volume.DataSyncEnum.pull,
manual: true,
volume: '1934e1d3-2ba0-4000-8fd3-6f11081e4401',
};

Expand All @@ -10,7 +11,35 @@ export const mockedDataSync: ai.volume.DataSync = {
id: 'idDuDataSync',
spec: {
direction: ai.volume.DataSyncEnum.pull,
manual: true,
volume: '1934e1d3-2ba0-4000-8fd3-6f11081e4401',
},
status: {
endedAt: 'endedAT',
info: {
code: ai.InfoCodeEnum.APP_ERROR,
message: 'error_message',
},
progress: [
{
completed: 1,
createdAt: 'createdAt',
deleted: 1,
direction: ai.volume.DataSyncEnum.pull,
failed: 3,
id: 'id',
info: 'info',
processed: 1,
skipped: 1,
state: ai.volume.DataSyncProgressStateEnum.DONE,
total: 1,
transferredBytes: 1,
updatedAt: 'updatedAt',
},
],
queuedAt: 'queudAt',
startedAt: 'startedAt',
state: ai.volume.DataSyncStateEnum.DONE,
},
updatedAt: 'updatedAt',
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as ai from '@/types/cloud/project/ai';
import { mockedDataSync } from './datasync';

export const mockedJobSpec: ai.job.JobSpec = {
image: 'image',
Expand All @@ -15,38 +16,7 @@ export const mockedJobSpec: ai.job.JobSpec = {
},
};
export const mockedJobStatus: ai.job.JobStatus = {
dataSync: [
{
createdAt: 'createdAt',
id: 'datasyncId',
status: {
info: {
code: ai.InfoCodeEnum.APP_RUNNING,
message: 'message',
},
progress: [
{
completed: 1,
createdAt: 'createdAt',
deleted: 0,
direction: ai.volume.DataSyncEnum.push,
failed: 0,
id: 'progressId',
info: 'info',
processed: 3,
skipped: 1,
state: ai.volume.DataSyncProgressStateEnum.DONE,
total: 2,
transferredBytes: 30,
updatedAt: 'updatedAt',
},
],
queuedAt: 'queuedAt',
state: ai.volume.DataSyncStateEnum.DONE,
},
updatedAt: 'updatedAt',
},
],
dataSync: [mockedDataSync],
history: [
{
date: 'date',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as ai from '@/types/cloud/project/ai';

export const mockedLogs: ai.Logs = {
lastActivity: 'now',
logs: [
{
content: 'my first line log',
timestamp: '2024-11-27T15:15:35.684Z',
},
{
content: 'my second line log',
timestamp: '2024-11-27T15:15:36.684Z',
},
{
content: 'my third line log',
timestamp: '2024-11-27T15:15:37.684Z',
},
{
content: 'another line log',
timestamp: '2024-11-27T15:15:38.684Z',
},
],
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ai from '@/types/cloud/project/ai';
import { mockedJobStatus } from './job';
import { mockedDataSync } from './datasync';

export const mockedNotebookSpec: ai.notebook.NotebookSpec = {
env: {
Expand Down Expand Up @@ -27,38 +28,7 @@ export const mockedNotebookSpec: ai.notebook.NotebookSpec = {
};

export const mockedNotebookStatus: ai.notebook.NotebookStatus = {
dataSync: [
{
createdAt: 'createdAt',
id: 'datasyncId',
status: {
info: {
code: ai.InfoCodeEnum.APP_RUNNING,
message: 'message',
},
progress: [
{
completed: 1,
createdAt: 'createdAt',
deleted: 0,
direction: ai.volume.DataSyncEnum.push,
failed: 0,
id: 'progressId',
info: 'info',
processed: 3,
skipped: 1,
state: ai.volume.DataSyncProgressStateEnum.DONE,
total: 2,
transferredBytes: 30,
updatedAt: 'updatedAt',
},
],
queuedAt: 'queuedAt',
state: ai.volume.DataSyncStateEnum.DONE,
},
updatedAt: 'updatedAt',
},
],
dataSync: [mockedDataSync],

info: {
code: ai.InfoCodeEnum.JOB_DONE,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as ai from '@/types/cloud/project/ai';

export const mockedEditor: ai.notebook.Editor = {
export const mockedEditor: ai.capabilities.notebook.Editor = {
description: 'description',
docUrl: 'docURl',
id: 'editorId',
logoUrl: 'logo',
name: 'EditorName',
version: 'version',
versions: ['version'],
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ export const mockedSshKey: sshkey.SshKey = {
publicKey: 'publicKey',
regions: ['GRA'],
};

export const mockedSshKeyDetail: sshkey.SshKeyDetail = {
fingerPrint: 'fingerPrint',
id: 'id',
name: 'name',
publicKey: 'publicKey',
regions: ['GRA', 'BHS'],
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export const POLLING = {
NOTEBOOKS: 30_000,
NOTEBOOK: 30_000,
LOGS: 30_000,
};

export const USER_INACTIVITY_TIMEOUT = 5 * 60_000; // inactivity after 5 minutes

export const TERMINATE_CONFIRMATION = 'TERMINATE';

export const TIMELINE_MAX = -7;
export const TIMELINE_MAX = -7;
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ export const getEditor = async ({ projectId }: PCIAi) =>
'X-Pagination-Size': '50000',
},
})
.then((res) => res.data as ai.notebook.Editor[]);
.then((res) => res.data as ai.capabilities.notebook.Editor[]);
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ export const getFramework = async ({ projectId }: PCIAi) =>
'X-Pagination-Size': '50000',
},
})
.then((res) => res.data as ai.notebook.Framework[]);
.then((res) => res.data as ai.capabilities.notebook.Framework[]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { apiClient } from '@ovh-ux/manager-core-api';
import * as ai from '@/types/cloud/project/ai';
import { NotebookData } from '@/data/api';
import { mockedLogs } from '@/__tests__/helpers/mocks/logs';

export const getLogs = async ({ projectId, notebookId }: NotebookData) => {
// apiClient.v6
// .get(`/cloud/project/${projectId}/ai/notebook/${notebookId}/log`)
// .then((res) => res.data as ai.Logs);
return mockedLogs;
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const getNotebook = async ({ projectId, notebookId }: NotebookData) =>
.then((res) => res.data as ai.notebook.Notebook);

export interface AddNotebook extends PCIAi {
notebookInfo: ai.notebook.NotebookSpec;
notebookInfo: ai.notebook.NotebookSpecInput;
}
export const addNotebook = async ({ projectId, notebookInfo }: AddNotebook) =>
apiClient.v6
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { apiClient } from '@ovh-ux/manager-core-api';

import { PCIAi } from '../..';
import { Suggestions } from '@/types/orderFunnel';
import { mockedSuggestion } from '@/__tests__/helpers/mocks/suggestion';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ export function useGetEditor(
queryKey,
queryFn: () => getEditor({ projectId }),
...options,
}) as UseQueryResult<ai.notebook.Editor[], Error>;
}) as UseQueryResult<ai.capabilities.notebook.Editor[], Error>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ export function useGetFramework(
queryKey,
queryFn: () => getFramework({ projectId }),
...options,
}) as UseQueryResult<ai.notebook.Editor[], Error>;
}) as UseQueryResult<ai.capabilities.notebook.Framework[], Error>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { QueryObserverOptions, UseQueryResult } from '@tanstack/react-query';
import * as ai from '@/types/cloud/project/ai';
import { useQueryImmediateRefetch } from '@/hooks/api/useImmediateRefetch';
import { AIError } from '@/data/api';
import { getLogs } from '@/data/api/ai/notebook/logs/logs.api';

export function useGetLogs(
projectId: string,
notebookId: string,
options: Omit<QueryObserverOptions, 'queryKey'> = {},
) {
const queryKey = [projectId, 'ai/notebook', notebookId, 'log'];
return useQueryImmediateRefetch({
queryKey,
queryFn: () => getLogs({ projectId, notebookId }),
...options,
}) as UseQueryResult<ai.Logs, AIError>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { renderHook, waitFor } from '@testing-library/react';
import { vi } from 'vitest';
import { QueryClientWrapper } from '@/__tests__/helpers/wrappers/QueryClientWrapper';
import * as notebookApi from '@/data/api/ai/notebook/logs/logs.api';
import { mockedNotebook } from '@/__tests__/helpers/mocks/notebook';
import { mockedLogs } from '@/__tests__/helpers/mocks/logs';
import { useGetLogs } from './useGetLogs.hook';

vi.mock('@/data/api/ai/notebook/logs/logs.api', () => ({
getLogs: vi.fn(),
}));

describe('useGetNotebook', () => {
it('should return Logs', async () => {
const projectId = 'projectId';
const notebookId = 'notebookId';

vi.mocked(notebookApi.getLogs).mockResolvedValue(mockedLogs);

const { result } = renderHook(() => useGetLogs(projectId, notebookId), {
wrapper: QueryClientWrapper,
});

await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
expect(result.current.data).toEqual(mockedLogs);
expect(notebookApi.getLogs).toHaveBeenCalledWith({
projectId,
notebookId,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function useAddNotebook({ onError, onSuccess }: AddNotebookProps) {
const queryClient = useQueryClient();
const { projectId } = useParams();
const mutation = useMutation({
mutationFn: (notebookInfo: ai.notebook.NotebookSpec) => {
mutationFn: (notebookInfo: ai.notebook.NotebookSpecInput) => {
return addNotebook({ projectId, notebookInfo });
},
onError,
Expand All @@ -30,7 +30,7 @@ export function useAddNotebook({ onError, onSuccess }: AddNotebookProps) {
});

return {
addNotebook: (notebookInfo: ai.notebook.NotebookSpec) => {
addNotebook: (notebookInfo: ai.notebook.NotebookSpecInput) => {
return mutation.mutate(notebookInfo);
},
...mutation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function useGetCommand({ onError, onSuccess }: GetCommandProps) {
const queryClient = useQueryClient();
const { projectId } = useParams();
const mutation = useMutation({
mutationFn: (notebookInfo: ai.notebook.NotebookSpec) => {
mutationFn: (notebookInfo: ai.notebook.NotebookSpecInput) => {
return getCommand({ projectId, notebookInfo });
},
onError,
Expand All @@ -30,7 +30,7 @@ export function useGetCommand({ onError, onSuccess }: GetCommandProps) {
});

return {
getCommand: (notebookInfo: ai.notebook.NotebookSpec) => {
getCommand: (notebookInfo: ai.notebook.NotebookSpecInput) => {
return mutation.mutate(notebookInfo);
},
...mutation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function useAddSshKey({ onError, onAddKeySuccess }: UseAddSshKey) {
const mutation = useMutation({
mutationFn: (sshKey: AddSSHKey) => addSSHKey(sshKey),
onError,
onSuccess: (data: sshkey.SshKey) => {
onSuccess: (data: sshkey.SshKeyDetail) => {
onAddKeySuccess(data);
// Invalidate service list query to get the latest data
queryClient.invalidateQueries({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { renderHook, waitFor } from '@testing-library/react';
import { vi } from 'vitest';
import { QueryClientWrapper } from '@/__tests__/helpers/wrappers/QueryClientWrapper';
import * as sshkeyApi from '@/data/api/sshkey/sshkey.api';
import { mockedSshKey } from '@/__tests__/helpers/mocks/sshkey';
import {
mockedSshKey,
mockedSshKeyDetail,
} from '@/__tests__/helpers/mocks/sshkey';
import { useAddSshKey } from './useAddSshKey.hook';

vi.mock('@/data/api/sshkey/sshkey.api', () => ({
Expand All @@ -14,7 +17,7 @@ describe('useAddSshKey', () => {
const onAddKeySuccess = vi.fn();
const onError = vi.fn();

vi.mocked(sshkeyApi.addSSHKey).mockResolvedValue(mockedSshKey);
vi.mocked(sshkeyApi.addSSHKey).mockResolvedValue(mockedSshKeyDetail);

const { result } = renderHook(
() => useAddSshKey({ onError, onAddKeySuccess }),
Expand Down
Loading
Loading