Skip to content

Commit

Permalink
[7.x] [Code] initial code telemetry integration (elastic#45467) (elas…
Browse files Browse the repository at this point in the history
…tic#46161)

* [Code] initial code telemetry integration (elastic#45467)

* [Code] initial code telemetry backend integration

* frontend metric code

* Add lang server and repositories

* adjustments

* fix test

* update test
  • Loading branch information
mw-ding authored Sep 19, 2019
1 parent e666447 commit 412e077
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 8 deletions.
1 change: 1 addition & 0 deletions x-pack/legacy/plugins/code/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*/

export const APP_TITLE = 'Code (Beta)';
export const APP_USAGE_TYPE = 'code';
1 change: 0 additions & 1 deletion x-pack/legacy/plugins/code/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ export * from './repository';
export * from './task';
export * from './lsp';
export * from './workspace';
export * from './socket';
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

export enum SocketKind {
CLONE_PROGRESS = 'clone-progress',
DELETE_PROGRESS = 'delete-progress',
INDEX_PROGRESS = 'index-progress',
INSTALL_PROGRESS = 'install-progress',
export enum CodeUsageMetrics {
ENABLED = 'enabled',
REPOSITORIES = 'repositories',
LANGUAGE_SERVERS = 'langserver',
}
4 changes: 2 additions & 2 deletions x-pack/legacy/plugins/code/public/components/shared/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export const CtagsIcon = () => (
<svg width="32" height="32" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path
className="codeIcon__language"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M9.38147 22.4545L1.49428 14.5673C1.02148 14.0945 0.899259 13.8738 0.818851 13.6085C0.738443 13.3433 0.738443 13.072 0.818851 12.8067C0.899259 12.5414 1.02148 12.3207 1.49428 11.8479L11.1446 2.19753C11.4185 1.92366 11.5232 1.83884 11.6524 1.75804C11.7816 1.67724 11.913 1.62282 12.0615 1.58859C12.21 1.55437 12.3439 1.54034 12.7312 1.54034H20.4903C21.1579 1.54034 21.3999 1.60967 21.6441 1.73994C21.8883 1.87022 22.0801 2.06144 22.2111 2.30524C22.342 2.54903 22.4121 2.79091 22.414 3.45844L22.4365 11.1838C22.4376 11.5721 22.4239 11.7065 22.3898 11.8556C22.3558 12.0046 22.3014 12.1365 22.2205 12.2662C22.1395 12.3958 22.0545 12.5009 21.7799 12.7754L12.1009 22.4545C11.6281 22.9273 11.4074 23.0495 11.1421 23.1299C10.8768 23.2103 10.6055 23.2103 10.3402 23.1299C10.0749 23.0495 9.85427 22.9273 9.38147 22.4545ZM11.0402 21.3938L20.7193 11.7148C20.8576 11.5765 20.9085 11.5228 20.9317 11.4943C20.9353 11.4577 20.9371 11.3837 20.9365 11.1882L20.914 3.4628C20.9132 3.1916 20.9096 3.09541 20.9017 3.05144C20.8577 3.04366 20.7615 3.04035 20.4903 3.04035H12.7312C12.5359 3.04035 12.4621 3.0423 12.4255 3.04601C12.397 3.06924 12.3434 3.12009 12.2053 3.2582L2.55494 12.9086C2.36296 13.1005 2.29722 13.171 2.2716 13.2076C2.29722 13.2442 2.36296 13.3147 2.55494 13.5067L10.4421 21.3938C10.6341 21.5858 10.7045 21.6516 10.7412 21.6772C10.7778 21.6516 10.8482 21.5858 11.0402 21.3938ZM17.4379 6.54402C16.8521 5.95824 15.9023 5.95824 15.3166 6.54402C14.7308 7.12981 14.7308 8.07956 15.3166 8.66534C15.9023 9.25113 16.8521 9.25113 17.4379 8.66534C18.0237 8.07956 18.0237 7.12981 17.4379 6.54402ZM10.1443 16.8534L7.10054 13.8096C7.07478 13.7898 7.05001 13.7681 7.02642 13.7445C6.81172 13.5298 6.7544 13.2173 6.85448 12.9504C6.89078 12.8508 6.94891 12.7572 7.02886 12.6773C7.04481 12.6613 7.0613 12.6462 7.07828 12.632L10.6477 9.06256C10.9406 8.76967 11.4155 8.76967 11.7084 9.06256C12.0013 9.35546 12.0013 9.83033 11.7084 10.1232L8.62194 13.2097L10.7433 15.331L13.8299 12.2444C14.1228 11.9516 14.5976 11.9516 14.8905 12.2444C15.1834 12.5373 15.1834 13.0122 14.8905 13.3051L11.2692 16.9264C10.9763 17.2193 10.5014 17.2193 10.2085 16.9264C10.1853 16.9032 10.1639 16.8787 10.1443 16.8534Z"
/>
</svg>
Expand Down
14 changes: 14 additions & 0 deletions x-pack/legacy/plugins/code/public/lib/usage_collector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import {
createUiStatsReporter,
METRIC_TYPE,
} from '../../../../../../src/legacy/core_plugins/ui_metric/public';
import { APP_USAGE_TYPE } from '../../common/constants';

export const trackUiAction = createUiStatsReporter(APP_USAGE_TYPE);
export { METRIC_TYPE };
5 changes: 5 additions & 0 deletions x-pack/legacy/plugins/code/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { initQueue } from './init_queue';
import { initWorkers } from './init_workers';
import { ClusterNodeAdapter } from './distributed/cluster/cluster_node_adapter';
import { NodeRepositoriesService } from './distributed/cluster/node_repositories_service';
import { initCodeUsageCollector } from './usage_collector';

export class CodePlugin {
private isCodeNode = false;
Expand Down Expand Up @@ -241,6 +242,10 @@ export class CodePlugin {
await tryMigrateIndices(esClient, this.log);

this.initRoutes(server, codeServices, repoIndexInitializerFactory, repoConfigController);

// TODO: extend the usage collection to cluster mode.
initCodeUsageCollector(server, esClient, lspService);

return codeServices;
}

Expand Down
127 changes: 127 additions & 0 deletions x-pack/legacy/plugins/code/server/usage_collector.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import sinon from 'sinon';

import { LanguageServerStatus } from '../common/language_server';
import { RepositoryReservedField } from './indexer/schema';
import { EsClient } from './lib/esqueue';
import { LspService } from './lsp/lsp_service';
import { emptyAsyncFunc } from './test_utils';
import * as usageCollector from './usage_collector';

const esClient = {
search: emptyAsyncFunc,
};

const lspService = {
languageServerStatus: emptyAsyncFunc,
};

const createSearchSpy = (): sinon.SinonSpy => {
return sinon.fake.returns(
Promise.resolve({
hits: {
hits: [
{
_source: {
[RepositoryReservedField]: {
uri: 'github.com/elastic/code1',
},
},
},
{
_source: {
[RepositoryReservedField]: {
uri: 'github.com/elastic/code2',
},
},
},
],
},
})
);
};

describe('Code Usage Collector', () => {
let makeUsageCollectorStub: any;
let registerStub: any;
let serverStub: any;
let callClusterStub: any;
let languageServerStatusStub: any;
let searchStub: any;

beforeEach(() => {
makeUsageCollectorStub = sinon.spy();
registerStub = sinon.stub();
serverStub = {
usage: {
collectorSet: { makeUsageCollector: makeUsageCollectorStub, register: registerStub },
register: {},
},
};
callClusterStub = sinon.stub();

searchStub = createSearchSpy();
esClient.search = searchStub;

languageServerStatusStub = sinon.stub();
languageServerStatusStub.withArgs('TypeScript').returns(LanguageServerStatus.READY);
languageServerStatusStub.withArgs('Java').returns(LanguageServerStatus.READY);
languageServerStatusStub.withArgs('Ctags').returns(LanguageServerStatus.READY);
languageServerStatusStub.withArgs('Go').returns(LanguageServerStatus.NOT_INSTALLED);
lspService.languageServerStatus = languageServerStatusStub;
});

describe('initCodeUsageCollector', () => {
it('should call collectorSet.register', () => {
usageCollector.initCodeUsageCollector(
serverStub,
esClient as EsClient,
(lspService as any) as LspService
);
expect(registerStub.calledOnce).toBeTruthy();
});

it('should call makeUsageCollector with type = code', () => {
usageCollector.initCodeUsageCollector(
serverStub,
esClient as EsClient,
(lspService as any) as LspService
);
expect(makeUsageCollectorStub.calledOnce).toBeTruthy();
expect(makeUsageCollectorStub.getCall(0).args[0].type).toBe('code');
});

it('should return correct stats', async () => {
usageCollector.initCodeUsageCollector(
serverStub,
esClient as EsClient,
(lspService as any) as LspService
);
const codeStats = await makeUsageCollectorStub.getCall(0).args[0].fetch(callClusterStub);
expect(callClusterStub.notCalled).toBeTruthy();
expect(codeStats).toEqual({
enabled: 1,
repositories: 2,
langserver: [
{
enabled: 1,
key: 'TypeScript',
},
{
enabled: 1,
key: 'Java',
},
{
enabled: 0,
key: 'Go',
},
],
});
});
});
});
52 changes: 52 additions & 0 deletions x-pack/legacy/plugins/code/server/usage_collector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ServerFacade } from '../';
import { APP_USAGE_TYPE } from '../common/constants';
import { LanguageServerStatus } from '../common/language_server';
import { CodeUsageMetrics } from '../model/usage_telemetry_metrics';
import { EsClient } from './lib/esqueue';
import { RepositoryObjectClient } from './search';
import { LspService } from './lsp/lsp_service';
import { LanguageServers, LanguageServerDefinition } from './lsp/language_servers';

export async function fetchCodeUsageMetrics(client: EsClient, lspService: LspService) {
const repositoryObjectClient: RepositoryObjectClient = new RepositoryObjectClient(client);
const allRepos = await repositoryObjectClient.getAllRepositories();
const langServerEnabled = async (name: string) => {
const status = await lspService.languageServerStatus(name);
return status !== LanguageServerStatus.NOT_INSTALLED ? 1 : 0;
};

const langServersEnabled = await Promise.all(
LanguageServers.map(async (langServer: LanguageServerDefinition) => {
return {
key: langServer.name,
enabled: await langServerEnabled(langServer.name),
};
})
);

return {
[CodeUsageMetrics.ENABLED]: 1,
[CodeUsageMetrics.REPOSITORIES]: allRepos.length,
[CodeUsageMetrics.LANGUAGE_SERVERS]: langServersEnabled,
};
}

export function initCodeUsageCollector(
server: ServerFacade,
client: EsClient,
lspService: LspService
) {
const codeUsageCollector = server.usage.collectorSet.makeUsageCollector({
type: APP_USAGE_TYPE,
isReady: () => true,
fetch: async () => fetchCodeUsageMetrics(client, lspService),
});

server.usage.collectorSet.register(codeUsageCollector);
}

0 comments on commit 412e077

Please sign in to comment.