Mirror of https://github.com/roostorg/osprey github.com/roostorg/osprey
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 189 lines 5.5 kB view raw
1import { saveAs } from 'file-saver'; 2import { matchPath } from 'react-router'; 3 4import { history } from '../stores/QueryStore'; 5import { LabelMutation, LabelStatusAPIMapping } from '../types/LabelTypes'; 6import { 7 TopNComparisonResult, 8 ScanResult, 9 ScanQueryRequest, 10 TimeseriesResult, 11 StoredExecutionResult, 12 QueryRequest, 13 ScanQueryOrder, 14 BaseQueryRequest, 15 FeatureLocations, 16} from '../types/QueryTypes'; 17import HTTPUtils, { HTTPResponse } from '../utils/HTTPUtils'; 18 19import { BULK_LABEL_DEFAULT_LIMIT, Routes } from '../Constants'; 20 21export function getBaseRequest({ 22 start, 23 end, 24 queryFilter, 25 entityFeatureFilters = new Set(), 26}: BaseQueryRequest): QueryRequest { 27 const entityViewMatch = matchPath<{ entityId: string; entityType: string }>(history.location.pathname, { 28 path: Routes.ENTITY, 29 }); 30 31 /* eslint-disable */ 32 const queryRequest: QueryRequest = { 33 start, 34 end, 35 query_filter: queryFilter, 36 entity: null, 37 }; 38 39 if (entityViewMatch != null) { 40 queryRequest.entity = { 41 id: decodeURIComponent(entityViewMatch.params.entityId), 42 type: decodeURIComponent(entityViewMatch.params.entityType), 43 feature_filters: entityFeatureFilters.size > 0 ? [...entityFeatureFilters] : null, 44 }; 45 } 46 /* eslint-enable */ 47 48 return queryRequest; 49} 50 51export async function getTopNQueryResults( 52 query: BaseQueryRequest, 53 dimension: string | null, 54 limit: number = 100, 55 precision: number = 0 56): Promise<TopNComparisonResult> { 57 if (dimension === '' || dimension == null) { 58 return { comparison: [], current_period: [], previous_period: [] }; 59 } 60 61 const response = await HTTPUtils.post('events/topn', { 62 ...getBaseRequest(query), 63 dimension, 64 limit, 65 precision, 66 }); 67 68 if (response.data.length > 0) { 69 return response.data[0].result; 70 } 71 72 return response.data; 73} 74 75export async function getGroupByApproximateCountResults( 76 query: BaseQueryRequest, 77 dimension: string | null 78): Promise<number | null> { 79 if (dimension === '' || dimension == null) { 80 return null; 81 } 82 83 const response = await HTTPUtils.post('events/groupby/approximate-count', { 84 ...getBaseRequest(query), 85 dimension, 86 }); 87 return response.data?.count ?? null; 88} 89 90export async function getScanQueryResults( 91 query: BaseQueryRequest, 92 sortOrder: ScanQueryOrder, 93 limit: number, 94 offset?: string | null 95): Promise<ScanResult> { 96 const requestData: ScanQueryRequest = { 97 ...getBaseRequest(query), 98 order: sortOrder, 99 limit, 100 }; 101 102 if (offset != null) { 103 requestData.next_page = offset; /* eslint-disable-line */ 104 } 105 106 const response: HTTPResponse = await HTTPUtils.post('events/scan', requestData); 107 108 if (!response.ok) return { events: [], offset: null, queryStart: null }; 109 return { 110 events: response.data.events, 111 offset: response.data.next_page, 112 queryStart: response.data.next_page != null ? query.start : null, 113 }; 114} 115 116export async function getFeatureLocations(): Promise<FeatureLocations> { 117 const response: HTTPResponse = await HTTPUtils.get('docs/feature-locations', { 118 validateStatus: (status) => status === 200 || status === 401, 119 }); 120 121 if (!response.ok || !response.data?.locations) return { locations: [] }; 122 return response.data; 123} 124 125export async function getTopNQueryResultCSV(query: BaseQueryRequest, dimension: string, limit: number): Promise<void> { 126 const response: HTTPResponse = await HTTPUtils.post('events/topn/csv', { 127 ...getBaseRequest(query), 128 dimension, 129 limit, 130 }); 131 132 if (response.ok) { 133 const fileBlob = new Blob([response.data], { type: 'text/csv' }); 134 saveAs(fileBlob, `osprey-${query.start}-${query.end}.csv`); 135 } else { 136 throw new Error(response.error.message); 137 } 138} 139 140export async function getTimeseriesQueryResults( 141 query: BaseQueryRequest, 142 granularity: string 143): Promise<TimeseriesResult[]> { 144 const response: HTTPResponse = await HTTPUtils.post('events/timeseries', { 145 ...getBaseRequest(query), 146 granularity, 147 }); 148 149 if (!response.ok) return []; 150 return response.data; 151} 152 153export async function getDetailedEventFeatures(eventId: string): Promise<StoredExecutionResult> { 154 const response: HTTPResponse = await HTTPUtils.get(`events/event/${eventId}`); 155 156 if (!response.ok) throw new Error('Failed to load detailed event features: ' + response.error.message); 157 return response.data; 158} 159 160export async function postTopBulkLabelTask( 161 query: BaseQueryRequest, 162 dimension: string, 163 excludedEntities: Set<string>, 164 entitiesToLabelCount: number, 165 noLimit: boolean, 166 labelMutation: LabelMutation 167): Promise<number | null> { 168 // The entity count is separate from the limiter; This check makes 169 // sure that a limited job will expect to label the correct amount of entities. 170 // If the expected count is more than 10% different from the actual count, 171 // the job will fail downstream. 172 if (!noLimit && entitiesToLabelCount > BULK_LABEL_DEFAULT_LIMIT) { 173 entitiesToLabelCount = BULK_LABEL_DEFAULT_LIMIT; 174 } 175 /* eslint-disable */ 176 const response = await HTTPUtils.post('events/topn/bulk_label', { 177 ...getBaseRequest(query), 178 dimension, 179 excluded_entities: [...excludedEntities], 180 expected_entities: entitiesToLabelCount, 181 no_limit: noLimit, 182 label_name: labelMutation.label_name, 183 label_status: LabelStatusAPIMapping[labelMutation.status], 184 label_reason: labelMutation.reason, 185 label_expiry: labelMutation.expires_at, 186 }); 187 /* eslint-enable */ 188 return response.data?.task_id ?? null; 189}