-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Backports the following commits to 6.7: - [Telemetry] Localization Stats (#29213)
- Loading branch information
Showing
10 changed files
with
210 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
x-pack/plugins/xpack_main/server/lib/file_integrity.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* 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 { Readable } from 'stream'; | ||
|
||
jest.mock('fs', () => ({ | ||
createReadStream(filepath: string): Readable { | ||
if (filepath === 'ERROR') { | ||
throw new Error('MOCK ERROR - Invalid Path'); | ||
} | ||
const readableStream = new Readable(); | ||
const streamData = filepath.split(''); | ||
let cursor = 0; | ||
|
||
readableStream._read = function(size) { | ||
const current = streamData[cursor++]; | ||
if (typeof current === 'undefined') { | ||
return this.push(null); | ||
} | ||
this.push(current); | ||
}; | ||
|
||
return readableStream; | ||
}, | ||
})); | ||
|
||
import { getIntegrityHash, getIntegrityHashes } from './file_integrity'; | ||
|
||
describe('Integrity Hash', () => { | ||
it('creates a hash from a file given a file path', async () => { | ||
const filePath = 'somepath.json'; | ||
const expectedHash = '3295d40d2f35ac27145d37fcd5cdc80b'; | ||
const integrityHash = await getIntegrityHash(filePath); | ||
expect(integrityHash).toEqual(expectedHash); | ||
}); | ||
|
||
it('returns null on error', async () => { | ||
const filePath = 'ERROR'; | ||
const integrityHash = await getIntegrityHash(filePath); | ||
expect(integrityHash).toEqual(null); | ||
}); | ||
}); | ||
|
||
describe('Integrity Hashes', () => { | ||
it('returns an object with each filename and its hash', async () => { | ||
const filePaths = ['somepath1.json', 'somepath2.json']; | ||
const integrityHashes = await getIntegrityHashes(filePaths); | ||
expect(integrityHashes).toEqual({ | ||
'somepath1.json': '8cbfe6a9f8174b2d7e77c2111a84f0e6', | ||
'somepath2.json': '4177c075ade448d6e69fd94b39d0be15', | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* 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 { createHash } from 'crypto'; | ||
import * as fs from 'fs'; | ||
import { zipObject } from 'lodash'; | ||
import * as stream from 'stream'; | ||
import * as util from 'util'; | ||
|
||
const pipeline = util.promisify(stream.pipeline); | ||
|
||
export type Hash = string; | ||
|
||
export interface Integrities { | ||
[filePath: string]: Hash; | ||
} | ||
|
||
export async function getIntegrityHashes(filepaths: string[]): Promise<Integrities> { | ||
const hashes = await Promise.all(filepaths.map(getIntegrityHash)); | ||
return zipObject(filepaths, hashes); | ||
} | ||
|
||
export async function getIntegrityHash(filepath: string): Promise<Hash | null> { | ||
try { | ||
const output = createHash('md5'); | ||
|
||
await pipeline(fs.createReadStream(filepath), output); | ||
const data = output.read(); | ||
if (data instanceof Buffer) { | ||
return data.toString('hex'); | ||
} | ||
return data; | ||
} catch (err) { | ||
return null; | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
x-pack/plugins/xpack_main/server/lib/get_localization_usage_collector.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
interface TranslationsMock { | ||
[title: string]: string; | ||
} | ||
|
||
const createI18nLoaderMock = (translations: TranslationsMock) => { | ||
return { | ||
getTranslationsByLocale() { | ||
return { | ||
messages: translations, | ||
}; | ||
}, | ||
}; | ||
}; | ||
|
||
import { getTranslationCount } from './get_localization_usage_collector'; | ||
|
||
describe('getTranslationCount', () => { | ||
it('returns 0 if no translations registered', async () => { | ||
const i18nLoaderMock = createI18nLoaderMock({}); | ||
const count = await getTranslationCount(i18nLoaderMock, 'en'); | ||
expect(count).toEqual(0); | ||
}); | ||
|
||
it('returns number of translations', async () => { | ||
const i18nLoaderMock = createI18nLoaderMock({ | ||
a: '1', | ||
b: '2', | ||
'b.a': '3', | ||
}); | ||
const count = await getTranslationCount(i18nLoaderMock, 'en'); | ||
expect(count).toEqual(3); | ||
}); | ||
}); |
53 changes: 53 additions & 0 deletions
53
x-pack/plugins/xpack_main/server/lib/get_localization_usage_collector.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* 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 { i18nLoader } from '@kbn/i18n'; | ||
import { size } from 'lodash'; | ||
// @ts-ignore | ||
import { KIBANA_LOCALIZATION_STATS_TYPE } from '../../common/constants'; | ||
import { getIntegrityHashes, Integrities } from './file_integrity'; | ||
|
||
export interface UsageStats { | ||
locale: string; | ||
integrities: Integrities; | ||
labelsCount?: number; | ||
} | ||
|
||
export async function getTranslationCount(loader: any, locale: string): Promise<number> { | ||
const translations = await loader.getTranslationsByLocale(locale); | ||
return size(translations.messages); | ||
} | ||
|
||
export function createCollectorFetch(server: any) { | ||
return async function fetchUsageStats(): Promise<UsageStats> { | ||
const config = server.config(); | ||
const locale: string = config.get('i18n.locale'); | ||
const translationFilePaths: string[] = server.getTranslationsFilePaths(); | ||
|
||
const [labelsCount, integrities] = await Promise.all([ | ||
getTranslationCount(i18nLoader, locale), | ||
getIntegrityHashes(translationFilePaths), | ||
]); | ||
|
||
return { | ||
locale, | ||
integrities, | ||
labelsCount, | ||
}; | ||
}; | ||
} | ||
|
||
/* | ||
* @param {Object} server | ||
* @return {Object} kibana usage stats type collection object | ||
*/ | ||
export function getLocalizationUsageCollector(server: any) { | ||
const { collectorSet } = server.usage; | ||
return collectorSet.makeUsageCollector({ | ||
type: KIBANA_LOCALIZATION_STATS_TYPE, | ||
fetch: createCollectorFetch(server), | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters