TraceToLogs: Enable trace-to-log feature for cloud-logging-data-source-plugin (#65614)

* TraceToLogs: Enable trace-to-log feature for cloud-logging-data-source-plugin

* TraceToLogs: Add tests for googlecloud-logging-datasource
This commit is contained in:
Aleksandr Mikhailov 2023-05-04 14:23:13 +02:00 committed by GitHub
parent 8ca9a89cf1
commit 111118dd68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 219 additions and 0 deletions

View File

@ -78,6 +78,7 @@ export function TraceToLogsSettings({ options, onOptionsChange }: Props) {
'grafana-splunk-datasource', // external 'grafana-splunk-datasource', // external
'grafana-opensearch-datasource', // external 'grafana-opensearch-datasource', // external
'grafana-falconlogscale-datasource', // external 'grafana-falconlogscale-datasource', // external
'googlecloud-logging-datasource', // external
]; ];
const traceToLogs = useMemo( const traceToLogs = useMemo(

View File

@ -810,6 +810,189 @@ describe('createSpanLinkFactory', () => {
}); });
}); });
describe('google cloud link', () => {
const searchUID = 'searchUID';
beforeAll(() => {
setDataSourceSrv({
getInstanceSettings() {
return {
uid: searchUID,
name: 'Google Cloud Logging',
type: 'googlecloud-logging-datasource',
} as unknown as DataSourceInstanceSettings;
},
} as unknown as DataSourceSrv);
setLinkSrv(new LinkSrv());
setTemplateSrv(new TemplateSrv());
});
it('creates link with correct simple query', () => {
const createLink = setupSpanLinkFactory({
datasourceUid: searchUID,
});
const links = createLink!(createTraceSpan());
const linkDef = links?.logLinks?.[0];
expect(linkDef).toBeDefined();
expect(decodeURIComponent(linkDef!.href)).toContain(
`datasource":"${searchUID}","queries":[{"query":"cluster=\\"cluster1\\" AND hostname=\\"hostname1\\"","refId":""}]`
);
});
it('automatically timeshifts the time range by one second in a query', () => {
const createLink = setupSpanLinkFactory({
datasourceUid: searchUID,
});
const links = createLink!(createTraceSpan());
const linkDef = links?.logLinks?.[0];
expect(linkDef).toBeDefined();
expect(linkDef!.href).toContain(
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"}')}`
);
expect(linkDef!.href).not.toContain(
`${encodeURIComponent('{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:00.000Z"}')}`
);
});
it('formats query correctly if filterByTraceID and or filterBySpanID is true', () => {
const createLink = setupSpanLinkFactory(
{
datasourceUid: searchUID,
filterByTraceID: true,
filterBySpanID: true,
},
searchUID
);
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":"${searchUID}","queries":[{"query":"\\"6605c7b08e715d6c\\" AND \\"7946b05c2e2e4e5a\\" AND cluster=\\"cluster1\\" AND hostname=\\"hostname1\\"","refId":""}]}`
)}`
);
});
it('formats query correctly if only filterByTraceID is true', () => {
const createLink = setupSpanLinkFactory(
{
datasourceUid: searchUID,
filterByTraceID: true,
},
searchUID
);
expect(createLink).toBeDefined();
const links = createLink!(
createTraceSpan({
process: {
serviceName: 'service',
tags: [],
},
})
);
const linkDef = links?.logLinks?.[0];
expect(linkDef).toBeDefined();
expect(decodeURIComponent(linkDef!.href)).toBe(
`/explore?left={"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"searchUID","queries":[{"query":"\\"7946b05c2e2e4e5a\\"","refId":""}]}`
);
});
it('should format one tag correctly', () => {
const createLink = setupSpanLinkFactory(
{
tags: [{ key: 'ip' }],
},
searchUID
);
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":"${searchUID}","queries":[{"query":"ip=\\"192.168.0.1\\"","refId":""}]}`
)}`
);
});
it('should format multiple tags correctly', () => {
const createLink = setupSpanLinkFactory(
{
tags: [{ key: 'ip' }, { key: 'hostname' }],
},
searchUID
);
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":"${searchUID}","queries":[{"query":"hostname=\\"hostname1\\" AND 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' },
],
},
searchUID
);
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":"${searchUID}","queries":[{"query":"service=\\"serviceName\\" AND pod=\\"podName\\"","refId":""}]}`
)}`
);
});
});
describe('custom query', () => { describe('custom query', () => {
beforeAll(() => { beforeAll(() => {
setDataSourceSrv({ setDataSourceSrv({

View File

@ -165,6 +165,10 @@ function legacyCreateSpanLinkFactory(
case 'grafana-falconlogscale-datasource': case 'grafana-falconlogscale-datasource':
tags = getFormattedTags(span, tagsToUse, { joinBy: ' OR ' }); tags = getFormattedTags(span, tagsToUse, { joinBy: ' OR ' });
query = getQueryForFalconLogScale(span, traceToLogsOptions, tags, customQuery); query = getQueryForFalconLogScale(span, traceToLogsOptions, tags, customQuery);
break;
case 'googlecloud-logging-datasource':
tags = getFormattedTags(span, tagsToUse, { joinBy: ' AND ' });
query = getQueryForGoogleCloudLogging(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.
@ -406,6 +410,37 @@ function getQueryForSplunk(span: TraceSpan, options: TraceToLogsOptionsV2, tags:
}; };
} }
function getQueryForGoogleCloudLogging(
span: TraceSpan,
options: TraceToLogsOptionsV2,
tags: string,
customQuery?: string
) {
const { filterByTraceID, filterBySpanID } = options;
if (customQuery) {
return { query: customQuery, refId: '' };
}
let queryArr = [];
if (filterBySpanID && span.spanID) {
queryArr.push('"${__span.spanId}"');
}
if (filterByTraceID && span.traceID) {
queryArr.push('"${__span.traceId}"');
}
if (tags) {
queryArr.push('${__tags}');
}
return {
query: queryArr.join(' AND '),
refId: '',
};
}
function getQueryForFalconLogScale(span: TraceSpan, options: TraceToLogsOptionsV2, tags: string, customQuery?: string) { function getQueryForFalconLogScale(span: TraceSpan, options: TraceToLogsOptionsV2, tags: string, customQuery?: string) {
const { filterByTraceID, filterBySpanID } = options; const { filterByTraceID, filterBySpanID } = options;