mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Uses RFC3339Nano string to retrieve LogRow contexts from Loki API (#17813)
* Refactor: Uses nanosecond string to retreive LogRow contexts * Reafactor: Small changes to comments after PR comments
This commit is contained in:
@@ -103,12 +103,6 @@ const LogRowContextGroupHeader: React.FunctionComponent<LogRowContextGroupHeader
|
||||
const theme = useContext(ThemeContext);
|
||||
const { header } = getLogRowContextStyles(theme);
|
||||
|
||||
// Filtering out the original row from the context.
|
||||
// Loki requires a rowTimestamp+1ns for the following logs to be queried.
|
||||
// We don't to ns-precision calculations in Loki log row context retrieval, hence the filtering here
|
||||
// Also see: https://github.com/grafana/loki/issues/597
|
||||
const logRowsToRender = rows.filter(contextRow => contextRow !== row.raw);
|
||||
|
||||
return (
|
||||
<div className={header}>
|
||||
<span
|
||||
@@ -116,7 +110,7 @@ const LogRowContextGroupHeader: React.FunctionComponent<LogRowContextGroupHeader
|
||||
opacity: 0.6;
|
||||
`}
|
||||
>
|
||||
Found {logRowsToRender.length} rows.
|
||||
Found {rows.length} rows.
|
||||
</span>
|
||||
{(rows.length >= 10 || (rows.length > 10 && rows.length % 10 !== 0)) && canLoadMoreRows && (
|
||||
<span
|
||||
|
||||
@@ -28,54 +28,85 @@ interface LogRowContextProviderProps {
|
||||
}) => JSX.Element;
|
||||
}
|
||||
|
||||
export const getRowContexts = async (
|
||||
getRowContext: (row: LogRowModel, options?: any) => Promise<DataQueryResponse>,
|
||||
row: LogRowModel,
|
||||
limit: number
|
||||
) => {
|
||||
const promises = [
|
||||
getRowContext(row, {
|
||||
limit,
|
||||
}),
|
||||
getRowContext(row, {
|
||||
limit: limit + 1, // Lets add one more to the limit as we're filtering out one row see comment below
|
||||
direction: 'FORWARD',
|
||||
}),
|
||||
];
|
||||
|
||||
const results: Array<DataQueryResponse | DataQueryError> = await Promise.all(promises.map(p => p.catch(e => e)));
|
||||
|
||||
return {
|
||||
data: results.map((result, index) => {
|
||||
const dataResult: DataQueryResponse = result as DataQueryResponse;
|
||||
if (!dataResult.data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// We need to filter out the row we're basing our search from because of how start/end params work in Loki API
|
||||
// see https://github.com/grafana/loki/issues/597#issuecomment-506408980
|
||||
// the alternative to create our own add 1 nanosecond method to the a timestamp string would be quite complex
|
||||
return dataResult.data.map(series => {
|
||||
const filteredRows = series.rows.filter((r: any) => r[0] !== row.timestamp);
|
||||
return filteredRows.map((row: any) => row[1]);
|
||||
});
|
||||
}),
|
||||
errors: results.map(result => {
|
||||
const errorResult: DataQueryError = result as DataQueryError;
|
||||
if (!errorResult.message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return errorResult.message;
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export const LogRowContextProvider: React.FunctionComponent<LogRowContextProviderProps> = ({
|
||||
getRowContext,
|
||||
row,
|
||||
children,
|
||||
}) => {
|
||||
// React Hook that creates a number state value called limit to component state and a setter function called setLimit
|
||||
// The intial value for limit is 10
|
||||
// Used for the number of rows to retrieve from backend from a specific point in time
|
||||
const [limit, setLimit] = useState(10);
|
||||
|
||||
// React Hook that creates an object state value called result to component state and a setter function called setResult
|
||||
// The intial value for result is null
|
||||
// Used for sorting the response from backend
|
||||
const [result, setResult] = useState<{
|
||||
data: string[][];
|
||||
errors: string[];
|
||||
}>(null);
|
||||
|
||||
// React Hook that creates an object state value called hasMoreContextRows to component state and a setter function called setHasMoreContextRows
|
||||
// The intial value for hasMoreContextRows is {before: true, after: true}
|
||||
// Used for indicating in UI if there are more rows to load in a given direction
|
||||
const [hasMoreContextRows, setHasMoreContextRows] = useState({
|
||||
before: true,
|
||||
after: true,
|
||||
});
|
||||
|
||||
// React Hook that resolves two promises every time the limit prop changes
|
||||
// First promise fetches limit number of rows backwards in time from a specific point in time
|
||||
// Second promise fetches limit number of rows forwards in time from a specific point in time
|
||||
const { value } = useAsync(async () => {
|
||||
const promises = [
|
||||
getRowContext(row, {
|
||||
limit,
|
||||
}),
|
||||
getRowContext(row, {
|
||||
limit,
|
||||
direction: 'FORWARD',
|
||||
}),
|
||||
];
|
||||
|
||||
const results: Array<DataQueryResponse | DataQueryError> = await Promise.all(promises.map(p => p.catch(e => e)));
|
||||
|
||||
return {
|
||||
data: results.map(result => {
|
||||
if ((result as DataQueryResponse).data) {
|
||||
return (result as DataQueryResponse).data.map(series => {
|
||||
return series.rows.map(row => row[1]);
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}),
|
||||
errors: results.map(result => {
|
||||
if ((result as DataQueryError).message) {
|
||||
return (result as DataQueryError).message;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}),
|
||||
};
|
||||
return await getRowContexts(getRowContext, row, limit); // Moved it to a separate function for debugging purposes
|
||||
}, [limit]);
|
||||
|
||||
// React Hook that performs a side effect every time the value (from useAsync hook) prop changes
|
||||
// The side effect changes the result state with the response from the useAsync hook
|
||||
// The side effect changes the hasMoreContextRows state if there are more context rows before or after the current result
|
||||
useEffect(() => {
|
||||
if (value) {
|
||||
setResult(currentResult => {
|
||||
|
||||
@@ -310,13 +310,13 @@ export class LokiDatasource extends DataSourceApi<LokiQuery, LokiOptions> {
|
||||
return {
|
||||
...commontTargetOptons,
|
||||
start: timeEpochNs - contextTimeBuffer,
|
||||
end: timeEpochNs,
|
||||
end: row.timestamp,
|
||||
direction,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...commontTargetOptons,
|
||||
start: timeEpochNs, // TODO: We should add 1ns here for the original row not no be included in the result
|
||||
start: row.timestamp, // start param in Loki API is inclusive so we'll have to filter out the row that this request is based from
|
||||
end: timeEpochNs + contextTimeBuffer,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user