The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/features/explore/utils/links.ts

92 lines
3.3 KiB

import { splitOpen } from '../state/actions';
import { ExploreMode, Field, LinkModel, locationUtil, TimeRange } from '@grafana/data';
import { getLinksFromLogsField } from '../../panel/panellinks/linkSuppliers';
import { serializeStateToUrlParam } from '../../../core/utils/explore';
import { getDataSourceSrv } from '@grafana/runtime';
/**
* Get links from the filed of a dataframe that was given to as and in addition check if there is associated
* metadata with datasource in which case we will add onClick to open the link in new split window. This assumes
* that we just supply datasource name and field value and Explore split window will know how to render that
* appropriately. This is for example used for transition from log with traceId to trace datasource to show that
* trace.
*/
export function getFieldLinksForExplore(
field: Field,
rowIndex: number,
splitOpenFn: typeof splitOpen,
range: TimeRange
): Array<LinkModel<Field>> {
const data = getLinksFromLogsField(field, rowIndex);
return data.map(d => {
if (d.link.meta?.datasourceUid) {
return {
...d.linkModel,
title:
d.linkModel.title ||
getDataSourceSrv().getDataSourceSettingsByUid(d.link.meta.datasourceUid)?.name ||
'Unknown datasource',
onClick: () => {
splitOpenFn({
datasourceUid: d.link.meta.datasourceUid,
// TODO: fix the ambiguity here
// This looks weird but in case meta.datasourceUid is set we save the query in url which will get
// interpolated into href
query: d.linkModel.href,
});
},
// We need to create real href here as the linkModel.href actually contains query. As in this case this is
// meant to be internal link (opens split view by default) the href will also points to explore but this
// way you can open it in new tab.
href: generateInternalHref(d.link.meta.datasourceUid, d.linkModel.href, range),
};
}
if (!d.linkModel.title) {
let href = d.linkModel.href;
// The URL constructor needs the url to have protocol
if (href.indexOf('://') < 0) {
// Doesn't really matter what protocol we use.
href = `http://${href}`;
}
let title;
try {
const parsedUrl = new URL(href);
title = parsedUrl.hostname;
} catch (_e) {
// Should be good enough fallback, user probably did not input valid url.
title = href;
}
return {
...d.linkModel,
title,
};
}
return d.linkModel;
});
}
/**
* Generates href for internal derived field link.
*/
function generateInternalHref(datasourceUid: string, query: string, range: TimeRange): string {
return locationUtil.assureBaseUrl(
`/explore?left=${serializeStateToUrlParam({
range: range.raw,
datasource: getDataSourceSrv().getDataSourceSettingsByUid(datasourceUid).name,
// Again hardcoded for Jaeger query structure
// TODO: fix
queries: [{ query }],
// This should get overwritten if datasource does not support that mode and we do not know what mode is
// preferred anyway.
mode: ExploreMode.Metrics,
ui: {
showingGraph: true,
showingTable: true,
showingLogs: true,
},
})}`
);
}