| | |
| | | 'use client' |
| | | import type { FC } from 'react' |
| | | import React, { useCallback, useEffect, useState } from 'react' |
| | | import { |
| | | RiArrowDownDoubleLine, |
| | | } from '@remixicon/react' |
| | | import { useTranslation } from 'react-i18next' |
| | | import { usePathname } from 'next/navigation' |
| | | import { useBoolean } from 'ahooks' |
| | | import type { LangFuseConfig, LangSmithConfig, OpikConfig, WeaveConfig } from './type' |
| | | import type { LangFuseConfig, LangSmithConfig } from './type' |
| | | import { TracingProvider } from './type' |
| | | import TracingIcon from './tracing-icon' |
| | | import ConfigButton from './config-button' |
| | | import cn from '@/utils/classnames' |
| | | import { LangfuseIcon, LangsmithIcon, OpikIcon, WeaveIcon } from '@/app/components/base/icons/src/public/tracing' |
| | | import { LangfuseIcon, LangsmithIcon, OpikIcon } from '@/app/components/base/icons/src/public/tracing' |
| | | import Indicator from '@/app/components/header/indicator' |
| | | import { fetchTracingConfig as doFetchTracingConfig, fetchTracingStatus, updateTracingStatus } from '@/service/apps' |
| | | import type { TracingStatus } from '@/models/app' |
| | | import Toast from '@/app/components/base/toast' |
| | | import { useAppContext } from '@/context/app-context' |
| | | import Loading from '@/app/components/base/loading' |
| | | import Divider from '@/app/components/base/divider' |
| | | |
| | | const I18N_PREFIX = 'app.tracing' |
| | | |
| | |
| | | const { t } = useTranslation() |
| | | |
| | | return ( |
| | | <div className={cn('system-xl-semibold flex items-center text-text-primary', className)}> |
| | | <div className={cn(className, 'flex items-center text-lg font-semibold text-gray-900')}> |
| | | {t('common.appMenus.overview')} |
| | | </div> |
| | | ) |
| | |
| | | ? LangfuseIcon |
| | | : inUseTracingProvider === TracingProvider.opik |
| | | ? OpikIcon |
| | | : inUseTracingProvider === TracingProvider.weave |
| | | ? WeaveIcon |
| | | : LangsmithIcon |
| | | : null |
| | | |
| | | const [langSmithConfig, setLangSmithConfig] = useState<LangSmithConfig | null>(null) |
| | | const [langFuseConfig, setLangFuseConfig] = useState<LangFuseConfig | null>(null) |
| | | const [opikConfig, setOpikConfig] = useState<OpikConfig | null>(null) |
| | | const [weaveConfig, setWeaveConfig] = useState<WeaveConfig | null>(null) |
| | | const hasConfiguredTracing = !!(langSmithConfig || langFuseConfig || opikConfig || weaveConfig) |
| | | const hasConfiguredTracing = !!(langSmithConfig || langFuseConfig || opikConfig) |
| | | |
| | | const fetchTracingConfig = async () => { |
| | | const { tracing_config: langSmithConfig, has_not_configured: langSmithHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.langSmith }) |
| | |
| | | const { tracing_config: opikConfig, has_not_configured: OpikHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.opik }) |
| | | if (!OpikHasNotConfig) |
| | | setOpikConfig(opikConfig as OpikConfig) |
| | | const { tracing_config: weaveConfig, has_not_configured: weaveHasNotConfig } = await doFetchTracingConfig({ appId, provider: TracingProvider.weave }) |
| | | if (!weaveHasNotConfig) |
| | | setWeaveConfig(weaveConfig as WeaveConfig) |
| | | } |
| | | |
| | | const handleTracingConfigUpdated = async (provider: TracingProvider) => { |
| | |
| | | const { tracing_config } = await doFetchTracingConfig({ appId, provider }) |
| | | if (provider === TracingProvider.langSmith) |
| | | setLangSmithConfig(tracing_config as LangSmithConfig) |
| | | else if (provider === TracingProvider.langfuse) |
| | | else if (provider === TracingProvider.langSmith) |
| | | setLangFuseConfig(tracing_config as LangFuseConfig) |
| | | else if (provider === TracingProvider.opik) |
| | | setOpikConfig(tracing_config as OpikConfig) |
| | | else if (provider === TracingProvider.weave) |
| | | setWeaveConfig(tracing_config as WeaveConfig) |
| | | } |
| | | |
| | | const handleTracingConfigRemoved = (provider: TracingProvider) => { |
| | | if (provider === TracingProvider.langSmith) |
| | | setLangSmithConfig(null) |
| | | else if (provider === TracingProvider.langfuse) |
| | | else if (provider === TracingProvider.langSmith) |
| | | setLangFuseConfig(null) |
| | | else if (provider === TracingProvider.opik) |
| | | setOpikConfig(null) |
| | | else if (provider === TracingProvider.weave) |
| | | setWeaveConfig(null) |
| | | if (provider === inUseTracingProvider) { |
| | | handleTracingStatusChange({ |
| | | enabled: false, |
| | |
| | | }, [setControlShowPopup]) |
| | | if (!isLoaded) { |
| | | return ( |
| | | <div className='mb-3 flex items-center justify-between'> |
| | | <div className='flex items-center justify-between mb-3'> |
| | | <Title className='h-[41px]' /> |
| | | <div className='w-[200px]'> |
| | | <Loading /> |
| | |
| | | } |
| | | |
| | | return ( |
| | | <div className={cn('mb-3 flex items-center justify-between')}> |
| | | <div className={cn('mb-3 flex justify-between items-center')}> |
| | | <Title className='h-[41px]' /> |
| | | <div |
| | | className={cn( |
| | | 'flex cursor-pointer items-center rounded-xl border-l-[0.5px] border-t border-effects-highlight bg-background-default-dodge p-2 shadow-xs hover:border-effects-highlight-lightmode-off hover:bg-background-default-lighter', |
| | | controlShowPopup && 'border-effects-highlight-lightmode-off bg-background-default-lighter', |
| | | )} |
| | | onClick={showPopup} |
| | | > |
| | | {!inUseTracingProvider && ( |
| | | <> |
| | | <TracingIcon size='md' /> |
| | | <div className='system-sm-semibold mx-2 text-text-secondary'>{t(`${I18N_PREFIX}.title`)}</div> |
| | | <div className='flex items-center' onClick={e => e.stopPropagation()}> |
| | | <ConfigButton |
| | | appId={appId} |
| | | readOnly={readOnly} |
| | | hasConfigured={false} |
| | | enabled={enabled} |
| | | onStatusChange={handleTracingEnabledChange} |
| | | chosenProvider={inUseTracingProvider} |
| | | onChooseProvider={handleChooseProvider} |
| | | langSmithConfig={langSmithConfig} |
| | | langFuseConfig={langFuseConfig} |
| | | opikConfig={opikConfig} |
| | | weaveConfig={weaveConfig} |
| | | onConfigUpdated={handleTracingConfigUpdated} |
| | | onConfigRemoved={handleTracingConfigRemoved} |
| | | controlShowPopup={controlShowPopup} |
| | | /> |
| | | </div> |
| | | <Divider type='vertical' className='h-3.5' /> |
| | | <div className='rounded-md p-1'> |
| | | <RiArrowDownDoubleLine className='h-4 w-4 text-text-tertiary' /> |
| | | </div> |
| | | <div className='flex items-center p-2 rounded-xl border-[0.5px] border-gray-200 shadow-xs cursor-pointer hover:bg-gray-100' onClick={showPopup}> |
| | | {!inUseTracingProvider |
| | | ? <> |
| | | <TracingIcon size='md' className='mr-2' /> |
| | | <div className='leading-5 text-sm font-semibold text-gray-700'>{t(`${I18N_PREFIX}.title`)}</div> |
| | | </> |
| | | )} |
| | | : <InUseProviderIcon className='ml-1 h-4' />} |
| | | |
| | | {hasConfiguredTracing && ( |
| | | <> |
| | | <div className='ml-4 mr-1 flex items-center'> |
| | | <Indicator color={enabled ? 'green' : 'gray'} /> |
| | | <div className='system-xs-semibold-uppercase ml-1.5 text-text-tertiary'> |
| | | <div className='ml-1.5 text-xs font-semibold text-gray-500 uppercase'> |
| | | {t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)} |
| | | </div> |
| | | </div> |
| | | {InUseProviderIcon && <InUseProviderIcon className='ml-1 h-4' />} |
| | | <Divider type='vertical' className='h-3.5' /> |
| | | )} |
| | | |
| | | {hasConfiguredTracing && ( |
| | | <div className='ml-2 w-px h-3.5 bg-gray-200'></div> |
| | | )} |
| | | <div className='flex items-center' onClick={e => e.stopPropagation()}> |
| | | <ConfigButton |
| | | appId={appId} |
| | |
| | | langSmithConfig={langSmithConfig} |
| | | langFuseConfig={langFuseConfig} |
| | | opikConfig={opikConfig} |
| | | weaveConfig={weaveConfig} |
| | | onConfigUpdated={handleTracingConfigUpdated} |
| | | onConfigRemoved={handleTracingConfigRemoved} |
| | | controlShowPopup={controlShowPopup} |
| | | /> |
| | | </div> |
| | | </> |
| | | )} |
| | | </div > |
| | | </div > |
| | | ) |