diff --git a/backend/modules/integrations/usecase/module.go b/backend/modules/integrations/usecase/module.go index b1507e7a5..fd06d1b70 100644 --- a/backend/modules/integrations/usecase/module.go +++ b/backend/modules/integrations/usecase/module.go @@ -167,6 +167,7 @@ func (u *moduleUsecase) Create(ctx context.Context, req dto.CreateModuleRequest) } if _,err:= u.opensearch.Create(ctx,os_dto.CreateIndexPatternRequest{ + Pattern: req.DataType, PatternModule: &req.ModuleName, });err!=nil{ //opensearch insertion fails, rolling back database diff --git a/backend/modules/opensearch/usecase/index_pattern.go b/backend/modules/opensearch/usecase/index_pattern.go index 193fdaf5f..cf5007190 100644 --- a/backend/modules/opensearch/usecase/index_pattern.go +++ b/backend/modules/opensearch/usecase/index_pattern.go @@ -49,6 +49,12 @@ func (u *indexPatternUsecase) Create(ctx context.Context, req dto.CreateIndexPat return nil, errInvalidPattern } + if !strings.HasPrefix(req.Pattern,constants.CUSTOM_INDEX_PREFIX) { + normalized := strings.ReplaceAll(strings.Trim(strings.ToLower(req.Pattern), ""), " ", "-") + req.Pattern = fmt.Sprintf("%s-%s-*", constants.CUSTOM_INDEX_PREFIX, normalized) + } + + p := &domain.UtmIndexPattern{ Pattern: req.Pattern, PatternModule: req.PatternModule, diff --git a/frontend/src/features/log-explorer/pages/LogExplorerPage.tsx b/frontend/src/features/log-explorer/pages/LogExplorerPage.tsx index f5cdd33b1..77af83b3c 100644 --- a/frontend/src/features/log-explorer/pages/LogExplorerPage.tsx +++ b/frontend/src/features/log-explorer/pages/LogExplorerPage.tsx @@ -4,6 +4,9 @@ import { presetRange } from '@/shared/components/ui/time-range-picker' import { LogExplorerTabsBar } from '../components/LogExplorerTabsBar' import { LogExplorerView } from '../components/LogExplorerView' import { useLogExplorerTabs } from '../hooks/useLogExplorerTabs' +import type { FilterType } from '../types/log-explorer.types' + +const TS_FIELD = '@timestamp' export function LogExplorerPage() { const location = useLocation() @@ -11,18 +14,43 @@ export function LogExplorerPage() { const tabs = useLogExplorerTabs() const seededRef = useRef(false) - // Integration "View events" deep-link (?dataType=) → open in a NEW tab. + // Deep-link seed: any query param becomes a filter (?field=value; comma-list + // ?field=a,b,c → IS_ONE_OF_TERMS). Reserved: ?@timestamp= sets the + // range (e.g. 24h, 7d, 30d). No params → normal open, existing tabs shown. useEffect(() => { if (seededRef.current) return - const dataType = new URLSearchParams(location.search).get('dataType') - if (!dataType) return + const params = new URLSearchParams(location.search) + + let range = presetRange('30d') + const filters: FilterType[] = [] + for (const [field, raw] of params.entries()) { + if (field === TS_FIELD) { + range = presetRange(raw) + continue + } + const values = raw.split(',').map((s) => s.trim()).filter(Boolean) + if (values.length === 0) continue + filters.push( + values.length === 1 + ? { field, operator: 'IS', value: values[0] } + : { field, operator: 'IS_ONE_OF_TERMS', value: values } + ) + } + + if (filters.length === 0) return + seededRef.current = true + const first = filters[0] + const name = + filters.length === 1 + ? `${first.field}: ${Array.isArray(first.value) ? first.value.join(',') : String(first.value)}` + : 'Filtered' tabs.addTab({ - name: `dataType: ${dataType}`, + name, patternStr: 'v11-log-*', - filters: [{ field: 'dataType', operator: 'IS', value: dataType }], - range: presetRange('30d'), - columns: ['dataType'], + filters, + range, + columns: filters.map((f) => f.field), }) navigate(location.pathname, { replace: true }) // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/frontend/src/features/user-auditor/pages/UserAuditorPage.tsx b/frontend/src/features/user-auditor/pages/UserAuditorPage.tsx index dc11a3a46..84b518a16 100644 --- a/frontend/src/features/user-auditor/pages/UserAuditorPage.tsx +++ b/frontend/src/features/user-auditor/pages/UserAuditorPage.tsx @@ -612,7 +612,15 @@ function UserDrawer({ user, onClose, t }: { user: ADUser; onClose: () => void; t