mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FalconLogScale: Traces to logs support (#64174)
* Humio traces to logs support * Update tag formatting * Add tests for humio * Correct naming
This commit is contained in:
parent
80e8ac640e
commit
a814357d6d
@ -75,6 +75,7 @@ export function TraceToLogsSettings({ options, onOptionsChange }: Props) {
|
|||||||
'elasticsearch',
|
'elasticsearch',
|
||||||
'grafana-splunk-datasource', // external
|
'grafana-splunk-datasource', // external
|
||||||
'grafana-opensearch-datasource', // external
|
'grafana-opensearch-datasource', // external
|
||||||
|
'grafana-falconlogscale-datasource', // external
|
||||||
];
|
];
|
||||||
|
|
||||||
const traceToLogs = useMemo(
|
const traceToLogs = useMemo(
|
||||||
|
@ -863,6 +863,133 @@ describe('createSpanLinkFactory', () => {
|
|||||||
expect(links?.logLinks).toBeUndefined();
|
expect(links?.logLinks).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('should return falconLogScale link', () => {
|
||||||
|
const falconLogScaleUID = 'falconLogScaleUID';
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
setDataSourceSrv({
|
||||||
|
getInstanceSettings() {
|
||||||
|
return {
|
||||||
|
uid: falconLogScaleUID,
|
||||||
|
name: 'FalconLogScale',
|
||||||
|
type: 'grafana-falconlogscale-datasource',
|
||||||
|
} as unknown as DataSourceInstanceSettings;
|
||||||
|
},
|
||||||
|
} as unknown as DataSourceSrv);
|
||||||
|
|
||||||
|
setLinkSrv(new LinkSrv());
|
||||||
|
setTemplateSrv(new TemplateSrv());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('the `lsql` keyword is used in the link', () => {
|
||||||
|
const createLink = setupSpanLinkFactory({
|
||||||
|
datasourceUid: falconLogScaleUID,
|
||||||
|
});
|
||||||
|
const links = createLink!(createTraceSpan());
|
||||||
|
|
||||||
|
const linkDef = links?.logLinks?.[0];
|
||||||
|
expect(linkDef).toBeDefined();
|
||||||
|
expect(linkDef!.href).toContain(`${encodeURIComponent('datasource":"falconLogScaleUID","queries":[{"lsql"')}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('formats query correctly if filterByTraceID and or filterBySpanID is true', () => {
|
||||||
|
const createLink = setupSpanLinkFactory({
|
||||||
|
datasourceUid: falconLogScaleUID,
|
||||||
|
filterByTraceID: true,
|
||||||
|
filterBySpanID: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(createLink).toBeDefined();
|
||||||
|
const links = createLink!(createTraceSpan());
|
||||||
|
|
||||||
|
const linkDef = links?.logLinks?.[0];
|
||||||
|
expect(linkDef).toBeDefined();
|
||||||
|
expect(linkDef!.href).toBe(
|
||||||
|
`/explore?left=${encodeURIComponent(
|
||||||
|
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"cluster=\\"cluster1\\" OR hostname=\\"hostname1\\" or \\"7946b05c2e2e4e5a\\" or \\"6605c7b08e715d6c\\"","refId":""}]}'
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should format one tag correctly', () => {
|
||||||
|
const createLink = setupSpanLinkFactory({
|
||||||
|
tags: [{ key: 'ip' }],
|
||||||
|
});
|
||||||
|
expect(createLink).toBeDefined();
|
||||||
|
const links = createLink!(
|
||||||
|
createTraceSpan({
|
||||||
|
process: {
|
||||||
|
serviceName: 'service',
|
||||||
|
tags: [{ key: 'ip', value: '192.168.0.1' }],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const linkDef = links?.logLinks?.[0];
|
||||||
|
expect(linkDef).toBeDefined();
|
||||||
|
expect(linkDef!.href).toBe(
|
||||||
|
`/explore?left=${encodeURIComponent(
|
||||||
|
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"ip=\\"192.168.0.1\\"","refId":""}]}'
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should format multiple tags correctly', () => {
|
||||||
|
const createLink = setupSpanLinkFactory({
|
||||||
|
tags: [{ key: 'ip' }, { key: 'hostname' }],
|
||||||
|
});
|
||||||
|
expect(createLink).toBeDefined();
|
||||||
|
const links = createLink!(
|
||||||
|
createTraceSpan({
|
||||||
|
process: {
|
||||||
|
serviceName: 'service',
|
||||||
|
tags: [
|
||||||
|
{ key: 'hostname', value: 'hostname1' },
|
||||||
|
{ key: 'ip', value: '192.168.0.1' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const linkDef = links?.logLinks?.[0];
|
||||||
|
expect(linkDef).toBeDefined();
|
||||||
|
expect(linkDef!.href).toBe(
|
||||||
|
`/explore?left=${encodeURIComponent(
|
||||||
|
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"hostname=\\"hostname1\\" OR ip=\\"192.168.0.1\\"","refId":""}]}'
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles renamed tags', () => {
|
||||||
|
const createLink = setupSpanLinkFactory({
|
||||||
|
tags: [
|
||||||
|
{ key: 'service.name', value: 'service' },
|
||||||
|
{ key: 'k8s.pod.name', value: 'pod' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(createLink).toBeDefined();
|
||||||
|
const links = createLink!(
|
||||||
|
createTraceSpan({
|
||||||
|
process: {
|
||||||
|
serviceName: 'service',
|
||||||
|
tags: [
|
||||||
|
{ key: 'service.name', value: 'serviceName' },
|
||||||
|
{ key: 'k8s.pod.name', value: 'podName' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const linkDef = links?.logLinks?.[0];
|
||||||
|
expect(linkDef).toBeDefined();
|
||||||
|
expect(linkDef!.href).toBe(
|
||||||
|
`/explore?left=${encodeURIComponent(
|
||||||
|
'{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"falconLogScaleUID","queries":[{"lsql":"service=\\"serviceName\\" OR pod=\\"podName\\"","refId":""}]}'
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupSpanLinkFactory(options: Partial<TraceToLogsOptionsV2> = {}, datasourceUid = 'lokiUid') {
|
function setupSpanLinkFactory(options: Partial<TraceToLogsOptionsV2> = {}, datasourceUid = 'lokiUid') {
|
||||||
|
@ -164,6 +164,9 @@ function legacyCreateSpanLinkFactory(
|
|||||||
tags = getFormattedTags(span, tagsToUse, { labelValueSign: ':', joinBy: ' AND ' });
|
tags = getFormattedTags(span, tagsToUse, { labelValueSign: ':', joinBy: ' AND ' });
|
||||||
query = getQueryForElasticsearchOrOpensearch(span, traceToLogsOptions, tags, customQuery);
|
query = getQueryForElasticsearchOrOpensearch(span, traceToLogsOptions, tags, customQuery);
|
||||||
break;
|
break;
|
||||||
|
case 'grafana-falconlogscale-datasource':
|
||||||
|
tags = getFormattedTags(span, tagsToUse, { joinBy: ' OR ' });
|
||||||
|
query = getQueryForFalconLogScale(span, traceToLogsOptions, tags, customQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
// query can be false in case the simple UI tag mapping is used but none of them are present in the span.
|
// query can be false in case the simple UI tag mapping is used but none of them are present in the span.
|
||||||
@ -405,6 +408,35 @@ function getQueryForSplunk(span: TraceSpan, options: TraceToLogsOptionsV2, tags:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getQueryForFalconLogScale(span: TraceSpan, options: TraceToLogsOptionsV2, tags: string, customQuery?: string) {
|
||||||
|
const { filterByTraceID, filterBySpanID } = options;
|
||||||
|
|
||||||
|
if (customQuery) {
|
||||||
|
return {
|
||||||
|
lsql: customQuery,
|
||||||
|
refId: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tags) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lsql = '${__tags}';
|
||||||
|
if (filterByTraceID && span.traceID) {
|
||||||
|
lsql += ' or "${__span.traceId}"';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterBySpanID && span.spanID) {
|
||||||
|
lsql += ' or "${__span.spanId}"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
lsql,
|
||||||
|
refId: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a string representing all the tags already formatted for use in the query. The tags are filtered so that
|
* Creates a string representing all the tags already formatted for use in the query. The tags are filtered so that
|
||||||
* only intersection of tags that exist in a span and tags that you want are serialized into the string.
|
* only intersection of tags that exist in a span and tags that you want are serialized into the string.
|
||||||
|
Loading…
Reference in New Issue
Block a user