Skip to content

Commit

Permalink
use timestamp in the api
Browse files Browse the repository at this point in the history
  • Loading branch information
Bamieh committed Oct 25, 2020
1 parent 26cfda6 commit 9be8020
Show file tree
Hide file tree
Showing 15 changed files with 62 additions and 128 deletions.
30 changes: 9 additions & 21 deletions src/plugins/telemetry/public/services/telemetry_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,30 @@
*/

/* eslint-disable dot-notation */
import { mockTelemetryService } from '../mocks';

const mockSubtract = jest.fn().mockImplementation(() => {
return {
toISOString: jest.fn(),
};
});

const mockClone = jest.fn().mockImplementation(() => {
return {
clone: mockClone,
subtract: mockSubtract,
toISOString: jest.fn(),
};
});
const mockMomentValueOf = jest.fn();

jest.mock('moment', () => {
return jest.fn().mockImplementation(() => {
return {
clone: mockClone,
subtract: mockSubtract,
toISOString: jest.fn(),
valueOf: mockMomentValueOf,
};
});
});

import { mockTelemetryService } from '../mocks';

describe('TelemetryService', () => {
describe('fetchTelemetry', () => {
it('calls expected URL with 20 minutes - now', async () => {
const timestamp = Date.now();
mockMomentValueOf.mockReturnValueOnce(timestamp);
const telemetryService = mockTelemetryService();

await telemetryService.fetchTelemetry();
expect(telemetryService['http'].post).toBeCalledWith('/api/telemetry/v2/clusters/_stats', {
body: JSON.stringify({ unencrypted: false, timeRange: {} }),
body: JSON.stringify({ unencrypted: false, timestamp }),
});
expect(mockClone).toBeCalled();
expect(mockSubtract).toBeCalledWith(20, 'minutes');
expect(mockMomentValueOf).toBeCalled();
});
});

Expand Down
9 changes: 1 addition & 8 deletions src/plugins/telemetry/public/services/telemetry_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,10 @@ export class TelemetryService {
};

public fetchTelemetry = async ({ unencrypted = false } = {}) => {
const now = moment();
return this.http.post('/api/telemetry/v2/clusters/_stats', {
body: JSON.stringify({
unencrypted,
timeRange: {
min: now
.clone() // Need to clone it to avoid mutation (and max being the same value)
.subtract(20, 'minutes')
.toISOString(),
max: now.toISOString(),
},
timestamp: moment().valueOf(),
}),
});
};
Expand Down
3 changes: 1 addition & 2 deletions src/plugins/telemetry/server/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ export class FetcherTask {
private async fetchTelemetry() {
return await this.telemetryCollectionManager!.getStats({
unencrypted: false,
start: moment().subtract(20, 'minutes').toISOString(),
end: moment().toISOString(),
timestamp: moment().valueOf(),
});
}

Expand Down
17 changes: 5 additions & 12 deletions src/plugins/telemetry/server/routes/telemetry_usage_stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ const validate: TypeOptions<string | number>['validate'] = (value) => {
}
};

const dateSchema = schema.oneOf([schema.string({ validate }), schema.number({ validate })]);

export function registerTelemetryUsageStatsRoutes(
router: IRouter,
telemetryCollectionManager: TelemetryCollectionManagerPluginSetup,
Expand All @@ -45,25 +43,20 @@ export function registerTelemetryUsageStatsRoutes(
validate: {
body: schema.object({
unencrypted: schema.boolean({ defaultValue: false }),
timeRange: schema.object({
min: dateSchema,
max: dateSchema,
}),
timestamp: schema.oneOf([schema.string({ validate }), schema.number({ validate })]),
}),
},
},
async (context, req, res) => {
const start = moment(req.body.timeRange.min).toISOString();
const end = moment(req.body.timeRange.max).toISOString();
const unencrypted = req.body.unencrypted;
const { unencrypted, timestamp } = req.body;

try {
const statsConfig: StatsGetterConfig = {
unencrypted,
start,
end,
timestamp: moment(timestamp).valueOf(),
request: req,
unencrypted,
};

const stats = await telemetryCollectionManager.getStats(statsConfig);
return res.ok({ body: stats });
} catch (err) {
Expand Down
7 changes: 2 additions & 5 deletions src/plugins/telemetry_collection_manager/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ export interface TelemetryOptInStats {

export interface BaseStatsGetterConfig {
unencrypted: boolean;
start: string;
end: string;
request?: KibanaRequest;
timestamp: number;
}

export interface EncryptedStatsGetterConfig extends BaseStatsGetterConfig {
Expand All @@ -77,8 +75,7 @@ export interface ClusterDetails {
export interface StatsCollectionConfig {
usageCollection: UsageCollectionSetup;
callCluster: LegacyAPICaller;
start: string | number;
end: string | number;
timestamp: number;
esClient: ElasticsearchClient;
soClient: SavedObjectsClientContract | ISavedObjectsRepository;
}
Expand Down
23 changes: 7 additions & 16 deletions test/api_integration/apis/telemetry/telemetry_local.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,12 @@ export default function ({ getService }) {
});

it('should pull local stats and validate data types', async () => {
const timeRange = {
min: '2018-07-23T22:07:00Z',
max: '2018-07-23T22:13:00Z',
};
const timestamp = '2018-07-23T22:13:00Z';

const { body } = await supertest
.post('/api/telemetry/v2/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.send({ timeRange, unencrypted: true })
.send({ timestamp, unencrypted: true })
.expect(200);

expect(body.length).to.be(1);
Expand Down Expand Up @@ -98,15 +95,12 @@ export default function ({ getService }) {
});

it('should pull local stats and validate fields', async () => {
const timeRange = {
min: '2018-07-23T22:07:00Z',
max: '2018-07-23T22:13:00Z',
};
const timestamp = '2018-07-23T22:13:00Z';

const { body } = await supertest
.post('/api/telemetry/v2/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.send({ timeRange, unencrypted: true })
.send({ timestamp, unencrypted: true })
.expect(200);

const stats = body[0];
Expand Down Expand Up @@ -156,10 +150,7 @@ export default function ({ getService }) {
});

describe('application usage limits', () => {
const timeRange = {
min: '2018-07-23T22:07:00Z',
max: '2018-07-23T22:13:00Z',
};
const timestamp = '2018-07-23T22:13:00Z';

function createSavedObject() {
return supertest
Expand Down Expand Up @@ -191,7 +182,7 @@ export default function ({ getService }) {
const { body } = await supertest
.post('/api/telemetry/v2/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.send({ timeRange, unencrypted: true })
.send({ timestamp, unencrypted: true })
.expect(200);

expect(body.length).to.be(1);
Expand Down Expand Up @@ -242,7 +233,7 @@ export default function ({ getService }) {
const { body } = await supertest
.post('/api/telemetry/v2/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.send({ timeRange, unencrypted: true })
.send({ timestamp, unencrypted: true })
.expect(200);

expect(body.length).to.be(1);
Expand Down
12 changes: 1 addition & 11 deletions x-pack/dev-tools/api_debug/apis/telemetry/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,4 @@ export const description = 'Get the clusters stats for the last 1 hour from the
export const method = 'POST';
export const path = '/api/telemetry/v2/clusters/_stats';

// Get an object with start and end times for the last 1 hour, ISO format, in UTC
function getTimeRange() {
const end = moment();
const start = moment(end).subtract(1, 'hour');
return {
min: moment.utc(start).format(),
max: moment.utc(end).format(),
};
}

export const body = { timeRange: getTimeRange(), unencrypted: true };
export const body = { timeRange: moment.now(), unencrypted: true };
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import { set } from '@elastic/safer-lodash-set';
import { get, merge } from 'lodash';

import { StatsGetter } from 'src/plugins/telemetry_collection_manager/server';
import moment from 'moment';
import { LOGSTASH_SYSTEM_ID, KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID } from '../../common/constants';
import { getElasticsearchStats, ESClusterStats } from './get_es_stats';
import { getKibanaStats, KibanaStats } from './get_kibana_stats';
import { getBeatsStats } from './get_beats_stats';
import { getHighLevelStats } from './get_high_level_stats';

type PromiseReturnType<T extends (...args: any[]) => any> = ReturnType<T> extends Promise<infer R>
? R
: T;
import { getBeatsStats, BeatsStatsByClusterUuid } from './get_beats_stats';
import { getHighLevelStats, ClustersHighLevelStats } from './get_high_level_stats';

export interface CustomContext {
maxBucketSize: number;
Expand All @@ -28,9 +25,12 @@ export interface CustomContext {
*/
export const getAllStats: StatsGetter<CustomContext> = async (
clustersDetails,
{ callCluster, start, end, esClient, soClient },
{ callCluster, timestamp },
{ maxBucketSize }
) => {
const start = moment(timestamp).subtract(20, 'minutes').toISOString();
const end = moment(timestamp).toISOString();

const clusterUuids = clustersDetails.map((clusterDetails) => clusterDetails.clusterUuid);

const [esClusters, kibana, logstash, beats] = await Promise.all([
Expand Down Expand Up @@ -61,8 +61,8 @@ export function handleAllStats(
beats,
}: {
kibana: KibanaStats;
logstash: PromiseReturnType<typeof getHighLevelStats>;
beats: PromiseReturnType<typeof getBeatsStats>;
logstash: ClustersHighLevelStats;
beats: BeatsStatsByClusterUuid;
}
) {
return clusters.map((cluster) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,8 @@ export function processResults(
async function fetchBeatsByType(
callCluster: StatsCollectionConfig['callCluster'],
clusterUuids: string[],
start: StatsCollectionConfig['start'],
end: StatsCollectionConfig['end'],
start: string,
end: string,
{ page = 0, ...options }: { page?: number } & BeatsProcessOptions,
type: string
): Promise<void> {
Expand Down Expand Up @@ -384,8 +384,8 @@ async function fetchBeatsByType(
export async function fetchBeatsStats(
callCluster: StatsCollectionConfig['callCluster'],
clusterUuids: string[],
start: StatsCollectionConfig['start'],
end: StatsCollectionConfig['end'],
start: string,
end: string,
options: { page?: number } & BeatsProcessOptions
) {
return fetchBeatsByType(callCluster, clusterUuids, start, end, options, 'beats_stats');
Expand All @@ -394,23 +394,27 @@ export async function fetchBeatsStats(
export async function fetchBeatsStates(
callCluster: StatsCollectionConfig['callCluster'],
clusterUuids: string[],
start: StatsCollectionConfig['start'],
end: StatsCollectionConfig['end'],
start: string,
end: string,
options: { page?: number } & BeatsProcessOptions
) {
return fetchBeatsByType(callCluster, clusterUuids, start, end, options, 'beats_state');
}

export interface BeatsStatsByClusterUuid {
[clusterUuid: string]: BeatsBaseStats;
}

/*
* Call the function for fetching and summarizing beats stats
* @return {Object} - Beats stats in an object keyed by the cluster UUIDs
*/
export async function getBeatsStats(
callCluster: StatsCollectionConfig['callCluster'],
clusterUuids: string[],
start: StatsCollectionConfig['start'],
end: StatsCollectionConfig['end']
) {
start: string,
end: string
): BeatsStatsByClusterUuid {
const options: BeatsProcessOptions = {
clusters: {}, // the result object to be built up
clusterHostSets: {}, // passed to processResults for tracking state in the results generation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ export function ensureTimeSpan(
export async function getKibanaStats(
callCluster: StatsCollectionConfig['callCluster'],
clusterUuids: string[],
start: StatsCollectionConfig['start'],
end: StatsCollectionConfig['end'],
start: string,
end: string,
maxBucketSize: number
) {
const { start: safeStart, end: safeEnd } = ensureTimeSpan(start, end);
Expand Down
14 changes: 4 additions & 10 deletions x-pack/test/api_integration/apis/telemetry/telemetry.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@ export default function ({ getService }) {
describe('/api/telemetry/v2/clusters/_stats', () => {
it('should load multiple trial-license clusters', async () => {
const archive = 'monitoring/multicluster';
const timeRange = {
min: '2017-08-15T21:00:00Z',
max: '2017-08-16T00:00:00Z',
};
const timestamp = '2017-08-16T00:00:00Z';

await esArchiver.load(archive);

const { body } = await supertest
.post('/api/telemetry/v2/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.send({ timeRange, unencrypted: true })
.send({ timestamp, unencrypted: true })
.expect(200);
expect(body).to.eql(multiClusterFixture);

Expand All @@ -35,17 +32,14 @@ export default function ({ getService }) {
describe('with basic cluster and reporting and canvas usage info', () => {
it('should load non-expiring basic cluster', async () => {
const archive = 'monitoring/basic_6.3.x';
const timeRange = {
min: '2018-07-23T22:07:00Z',
max: '2018-07-23T22:13:00Z',
};
const timestamp = '2018-07-23T22:13:00Z';

await esArchiver.load(archive);

const { body } = await supertest
.post('/api/telemetry/v2/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.send({ timeRange, unencrypted: true })
.send({ timestamp, unencrypted: true })
.expect(200);
expect(body).to.eql(basicClusterFixture);

Expand Down
Loading

0 comments on commit 9be8020

Please sign in to comment.