[7.x] [Usage Collection] Supports field descriptions as meta data (#92701) (#93295)

* [Usage Collection] Supports field descriptions as meta data (#92701)

Co-authored-by: Alejandro Fernández Haro <afharo@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
# Conflicts:
#	src/plugins/kibana_usage_collection/server/collectors/management/schema.ts

* Updates schema
This commit is contained in:
Christiane (Tina) Heiligers 2021-03-02 15:33:50 -07:00 committed by GitHub
parent 04cb7d9c68
commit 765b08368a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 7068 additions and 1641 deletions

View file

@ -13,6 +13,7 @@ import { parsedIndexedInterfaceWithNoMatchingSchema } from './parsed_indexed_int
import { parsedNestedCollector } from './parsed_nested_collector';
import { parsedSchemaDefinedWithSpreadsCollector } from './parsed_schema_defined_with_spreads_collector';
import { parsedWorkingCollector } from './parsed_working_collector';
import { parsedCollectorWithDescription } from './parsed_working_collector_with_description';
import { ParsedUsageCollection } from '../ts_parser';
export const allExtractedCollectors: ParsedUsageCollection[] = [
@ -22,5 +23,6 @@ export const allExtractedCollectors: ParsedUsageCollection[] = [
parsedIndexedInterfaceWithNoMatchingSchema,
parsedNestedCollector,
parsedSchemaDefinedWithSpreadsCollector,
parsedCollectorWithDescription,
parsedWorkingCollector,
];

View file

@ -0,0 +1,57 @@
{
"properties": {
"my_working_collector_with_description": {
"properties": {
"flat": {
"type": "keyword",
"_meta": {
"description": "A flat keyword string"
}
},
"my_index_signature_prop": {
"properties": {
"avg": {
"type": "float"
},
"count": {
"type": "long"
},
"max": {
"type": "long"
},
"min": {
"type": "long"
}
}
},
"my_str": {
"type": "text"
},
"my_objects": {
"properties": {
"total": {
"type": "long"
},
"type": {
"type": "boolean"
}
}
},
"my_array": {
"type": "array",
"items": {
"properties": {
"total": {
"type": "long"
},
"type": {
"type": "boolean"
}
}
}
},
"my_str_array": { "type": "array", "items": { "type": "keyword" } }
}
}
}
}

View file

@ -0,0 +1,109 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { SyntaxKind } from 'typescript';
import { ParsedUsageCollection } from '../ts_parser';
export const parsedCollectorWithDescription: ParsedUsageCollection = [
'src/fixtures/telemetry_collectors/working_collector_with_description.ts',
{
collectorName: 'my_working_collector_with_description',
schema: {
value: {
flat: {
type: 'keyword',
_meta: {
description: 'A flat keyword string',
},
},
my_str: {
type: 'text',
},
my_index_signature_prop: {
avg: {
type: 'float',
},
count: {
type: 'long',
},
max: {
type: 'long',
},
min: {
type: 'long',
},
},
my_objects: {
total: {
type: 'long',
},
type: {
type: 'boolean',
},
},
my_array: {
type: 'array',
items: {
total: {
type: 'long',
},
type: { type: 'boolean' },
},
},
my_str_array: { type: 'array', items: { type: 'keyword' } },
},
},
fetch: {
typeName: 'Usage',
typeDescriptor: {
flat: {
kind: SyntaxKind.StringKeyword,
type: 'StringKeyword',
},
my_str: {
kind: SyntaxKind.StringKeyword,
type: 'StringKeyword',
},
my_index_signature_prop: {
'@@INDEX@@': {
kind: SyntaxKind.NumberKeyword,
type: 'NumberKeyword',
},
},
my_objects: {
total: {
kind: SyntaxKind.NumberKeyword,
type: 'NumberKeyword',
},
type: {
kind: SyntaxKind.BooleanKeyword,
type: 'BooleanKeyword',
},
},
my_array: {
items: {
total: {
kind: SyntaxKind.NumberKeyword,
type: 'NumberKeyword',
},
type: {
kind: SyntaxKind.BooleanKeyword,
type: 'BooleanKeyword',
},
},
},
my_str_array: {
items: {
kind: SyntaxKind.StringKeyword,
type: 'StringKeyword',
},
},
},
},
},
];

View file

@ -24,7 +24,7 @@ describe('extractCollectors', () => {
const programPaths = await getProgramPaths(configs[0]);
const results = [...extractCollectors(programPaths, tsConfig)];
expect(results).toHaveLength(8);
expect(results).toHaveLength(9);
expect(results).toStrictEqual(allExtractedCollectors);
});
});

View file

@ -8,6 +8,7 @@
import { generateMapping } from './manage_schema';
import { parsedWorkingCollector } from './__fixture__/parsed_working_collector';
import { parsedCollectorWithDescription } from './__fixture__/parsed_working_collector_with_description';
import * as path from 'path';
import { readFile } from 'fs';
import { promisify } from 'util';
@ -25,4 +26,9 @@ describe('generateMapping', () => {
const result = generateMapping([parsedWorkingCollector]);
expect(result).toEqual(mockSchema);
});
it('generates a mapping file that includes _meta.description fields', async () => {
const mockSchema = await parseJsonFile('mock_schema_with_descriptions.json');
const result = generateMapping([parsedCollectorWithDescription]);
expect(result).toEqual(mockSchema);
});
});

View file

@ -0,0 +1,102 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { CollectorSet } from '../../plugins/usage_collection/server/collector';
import { loggerMock } from '../../core/server/logging/logger.mock';
const { makeUsageCollector } = new CollectorSet({
logger: loggerMock.create(),
maximumWaitTimeForAllCollectorsInS: 0,
});
interface MyObject {
total: number;
type: boolean;
}
interface Usage {
flat?: string;
my_str?: string;
my_objects: MyObject;
my_array?: MyObject[];
my_str_array?: string[];
my_index_signature_prop?: {
[key: string]: number;
};
}
const SOME_NUMBER: number = 123;
export const myCollector = makeUsageCollector<Usage>({
type: 'my_working_collector_with_description',
isReady: () => true,
fetch() {
const testString = '123';
// query ES and get some data
// summarize the data into a model
// return the modeled object that includes whatever you want to track
try {
return {
flat: 'hello',
my_str: testString,
my_objects: {
total: SOME_NUMBER,
type: true,
},
my_array: [
{
total: SOME_NUMBER,
type: true,
},
],
my_str_array: ['hello', 'world'],
};
} catch (err) {
return {
my_objects: {
total: 0,
type: true,
},
};
}
},
schema: {
flat: {
type: 'keyword',
_meta: {
description: 'A flat keyword string',
},
},
my_str: {
type: 'text',
},
my_objects: {
total: {
type: 'long',
},
type: { type: 'boolean' },
},
my_array: {
type: 'array',
items: {
total: {
type: 'long',
},
type: { type: 'boolean' },
},
},
my_str_array: { type: 'array', items: { type: 'keyword' } },
my_index_signature_prop: {
count: { type: 'long' },
avg: { type: 'float' },
max: { type: 'long' },
min: { type: 'long' },
},
},
});

View file

@ -3,9 +3,16 @@
This plugin registers the basic usage collectors from Kibana:
- [Application Usage](./server/collectors/application_usage/README.md)
- UI Metrics
- Ops stats
- Number of Saved Objects per type
- [User-changed UI Settings](./server/collectors/management/README.md)
- CSP configuration
- Core Metrics
- CSP configuration
- Kibana: Number of Saved Objects per type
- Localization data
- [User-changed UI Settings](./server/collectors/management/README.md)
- Ops stats
- UI Counts
- UI Metrics

View file

@ -10,7 +10,7 @@ To track a sub view inside your application (ie a flyout, a tab, form step, etc)
#### For a React Component
For tracking an application view rendered using react the simplest way is to wrap your component with the `TrackApplicationView` Higher order component:
For tracking an application view rendered using react the simplest way is to wrap your component with the `TrackApplicationView` Higher order component exposed from the `usageCollection` plugin. You will need to add the plugin to plugin's `kibana.json` file as an item in the `optionalPlugins` and `requiredBundles` declarations:
kibana.json
```json
@ -26,6 +26,7 @@ kibana.json
At the application level, the application must be wrapped by the `ApplicationUsageTrackingProvider` provided in the `usageCollection`'s setup contract.
For example:
```typescript jsx
class MyPlugin implements Plugin {
...
@ -69,7 +70,6 @@ const MyTrackedComponent = () => {
Application Usage will automatically track the active minutes on screen and clicks for both the application and the `MyComponent` component whenever it is mounted on the screen. Application Usage pauses counting screen minutes whenever the user is tabbed to another browser window.
The prop `viewId` is used as a unique identifier for your plugin. The Application Id is automatically attached to the tracked usage, based on the ID used when registering your app via `core.application.register`.
## Application Usage Telemetry Data
This collector reports the number of general clicks and minutes on screen for each registered application in Kibana.
@ -126,4 +126,4 @@ In order to keep the count of the events, this collector uses 3 Saved Objects:
All the types use the shared fields `appId: 'keyword'`, `viewId: 'keyword'`, `numberOfClicks: 'long'` and `minutesOnScreen: 'float'`, but they are currently not added in the mappings because we don't use them for search purposes, and we need to be thoughtful with the number of mapped fields in the SavedObjects index ([#43673](https://github.com/elastic/kibana/issues/43673)). `application_usage_transactional` and `application_usage_daily` also store `timestamp: { type: 'date' }`.
Rollups uses `appId` in the savedObject id for the default view. For other views `viewId` is concatenated. This keeps backwards compatiblity with previously stored documents on the clusters without requiring any form of migration.
Rollups uses `appId` in the savedObject id for the default view. For other views `viewId` is concatenated. This keeps backwards compatiblity with previously stored documents on the clusters without requiring any form of migration.

View file

@ -10,29 +10,106 @@ import { MakeSchemaFrom } from 'src/plugins/usage_collection/server';
import { ApplicationUsageTelemetryReport } from './telemetry_application_usage_collector';
const commonSchema: MakeSchemaFrom<ApplicationUsageTelemetryReport[string]> = {
appId: { type: 'keyword' },
viewId: { type: 'keyword' },
clicks_total: { type: 'long' },
clicks_7_days: { type: 'long' },
clicks_30_days: { type: 'long' },
clicks_90_days: { type: 'long' },
minutes_on_screen_total: { type: 'float' },
minutes_on_screen_7_days: { type: 'float' },
minutes_on_screen_30_days: { type: 'float' },
minutes_on_screen_90_days: { type: 'float' },
appId: { type: 'keyword', _meta: { description: 'The application being tracked' } },
viewId: { type: 'keyword', _meta: { description: 'Always `main`' } },
clicks_total: {
type: 'long',
_meta: {
description: 'General number of clicks in the application since we started counting them',
},
},
clicks_7_days: {
type: 'long',
_meta: { description: 'General number of clicks in the application over the last 7 days' },
},
clicks_30_days: {
type: 'long',
_meta: { description: 'General number of clicks in the application over the last 30 days' },
},
clicks_90_days: {
type: 'long',
_meta: { description: 'General number of clicks in the application over the last 90 days' },
},
minutes_on_screen_total: {
type: 'float',
_meta: {
description:
'Minutes the application is active and on-screen since we started counting them.',
},
},
minutes_on_screen_7_days: {
type: 'float',
_meta: { description: 'Minutes the application is active and on-screen over the last 7 days' },
},
minutes_on_screen_30_days: {
type: 'float',
_meta: { description: 'Minutes the application is active and on-screen over the last 30 days' },
},
minutes_on_screen_90_days: {
type: 'float',
_meta: { description: 'Minutes the application is active and on-screen over the last 90 days' },
},
views: {
type: 'array',
items: {
appId: { type: 'keyword' },
viewId: { type: 'keyword' },
clicks_total: { type: 'long' },
clicks_7_days: { type: 'long' },
clicks_30_days: { type: 'long' },
clicks_90_days: { type: 'long' },
minutes_on_screen_total: { type: 'float' },
minutes_on_screen_7_days: { type: 'float' },
minutes_on_screen_30_days: { type: 'float' },
minutes_on_screen_90_days: { type: 'float' },
appId: { type: 'keyword', _meta: { description: 'The application being tracked' } },
viewId: { type: 'keyword', _meta: { description: 'The application view being tracked' } },
clicks_total: {
type: 'long',
_meta: {
description:
'General number of clicks in the application sub view since we started counting them',
},
},
clicks_7_days: {
type: 'long',
_meta: {
description:
'General number of clicks in the active application sub view over the last 7 days',
},
},
clicks_30_days: {
type: 'long',
_meta: {
description:
'General number of clicks in the active application sub view over the last 30 days',
},
},
clicks_90_days: {
type: 'long',
_meta: {
description:
'General number of clicks in the active application sub view over the last 90 days',
},
},
minutes_on_screen_total: {
type: 'float',
_meta: {
description:
'Minutes the application sub view is active and on-screen since we started counting them.',
},
},
minutes_on_screen_7_days: {
type: 'float',
_meta: {
description:
'Minutes the application is active and on-screen active application sub view over the last 7 days',
},
},
minutes_on_screen_30_days: {
type: 'float',
_meta: {
description:
'Minutes the application is active and on-screen active application sub view over the last 30 days',
},
},
minutes_on_screen_90_days: {
type: 'float',
_meta: {
description:
'Minutes the application is active and on-screen active application sub view over the last 90 days',
},
},
},
},
};

View file

@ -19,76 +19,276 @@ export function getCoreUsageCollector(
schema: {
config: {
elasticsearch: {
sniffOnStart: { type: 'boolean' },
sniffIntervalMs: { type: 'long' },
sniffOnConnectionFault: { type: 'boolean' },
numberOfHostsConfigured: { type: 'long' },
requestHeadersWhitelistConfigured: { type: 'boolean' },
customHeadersConfigured: { type: 'boolean' },
shardTimeoutMs: { type: 'long' },
requestTimeoutMs: { type: 'long' },
pingTimeoutMs: { type: 'long' },
logQueries: { type: 'boolean' },
ssl: {
verificationMode: { type: 'keyword' },
certificateAuthoritiesConfigured: { type: 'boolean' },
certificateConfigured: { type: 'boolean' },
keyConfigured: { type: 'boolean' },
keystoreConfigured: { type: 'boolean' },
truststoreConfigured: { type: 'boolean' },
alwaysPresentCertificate: { type: 'boolean' },
sniffOnStart: {
type: 'boolean',
_meta: {
description:
'Indicates if an attempt should be made to find other Elasticsearch nodes on startup.',
},
},
sniffIntervalMs: {
type: 'long',
_meta: {
description:
'Time in milliseconds between requests to check Elasticsearch for an updated list of nodes.',
},
},
sniffOnConnectionFault: {
type: 'boolean',
_meta: {
description:
'Indicates if the list of Elasticsearch nodes should be updated immediately following a connection fault.',
},
},
numberOfHostsConfigured: {
type: 'long',
_meta: {
description: 'Number of Elasticsearch instances configured to use for queries.',
},
},
requestHeadersWhitelistConfigured: {
type: 'boolean',
_meta: {
description:
'Indicates if Kibana client-side headers to send to Elasticsearch is different to the default value.',
},
},
customHeadersConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if any custom headers have been configured.' },
},
shardTimeoutMs: {
type: 'long',
_meta: {
description:
'Time in milliseconds for Elasticsearch to wait for responses from shards.',
},
},
requestTimeoutMs: {
type: 'long',
_meta: {
description:
'Time in milliseconds to wait for responses from the back end or Elasticsearch.',
},
},
pingTimeoutMs: {
type: 'long',
_meta: {
description: 'Time in milliseconds to wait for Elasticsearch to respond to pings.',
},
},
logQueries: {
type: 'boolean',
_meta: { description: 'Indicates if queries sent to Elasticsearch should be logged.' },
},
ssl: {
verificationMode: {
type: 'keyword',
_meta: {
description:
'The verification of the server certificate that Kibana receives when making an outbound SSL or TLS connection to Elasticsearch',
},
},
certificateAuthoritiesConfigured: {
type: 'boolean',
_meta: {
description:
'Indicates if any PEM-encoded X.509 certificate authority certificates are configured.',
},
},
certificateConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a certificate authority is configured.' },
},
keyConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a certificate key is configured.' },
},
keystoreConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a keystore is configured.' },
},
truststoreConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a path to a PKCS#12 trust store is configured.' },
},
alwaysPresentCertificate: {
type: 'boolean',
_meta: {
description:
'Indicates if a client certificate is presented when requested by Elasticsearch.',
},
},
},
apiVersion: {
type: 'keyword',
_meta: { description: 'Version of the Elasticsearch API used.' },
},
healthCheckDelayMs: {
type: 'long',
_meta: {
description:
'The interval in miliseconds between health check requests Kibana sends to the Elasticsearch.',
},
},
apiVersion: { type: 'keyword' },
healthCheckDelayMs: { type: 'long' },
},
http: {
basePathConfigured: { type: 'boolean' },
maxPayloadInBytes: { type: 'long' },
rewriteBasePath: { type: 'boolean' },
keepaliveTimeout: { type: 'long' },
socketTimeout: { type: 'long' },
basePathConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a base path has been configured.' },
},
maxPayloadInBytes: {
type: 'long',
_meta: { description: 'Maximum payload size in bytes that is allowed.' },
},
rewriteBasePath: {
type: 'boolean',
_meta: { description: 'Indicates if the base path should be rewritten.' },
},
keepaliveTimeout: {
type: 'long',
_meta: { description: 'How long to keep sockets alive globally in milliseconds.' },
},
socketTimeout: {
type: 'long',
_meta: {
description: 'How long to wait before closing inactive sockets in milliseconds.',
},
},
compression: {
enabled: { type: 'boolean' },
referrerWhitelistConfigured: { type: 'boolean' },
enabled: {
type: 'boolean',
_meta: { description: 'Indicates if HTTP response compression is enabled.' },
},
referrerWhitelistConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if any responses should be compressed.' },
},
},
xsrf: {
disableProtection: { type: 'boolean' },
allowlistConfigured: { type: 'boolean' },
disableProtection: {
type: 'boolean',
_meta: { description: 'Indicates if protection against xsrf should be disabled.' },
},
allowlistConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if any http headers have been whitelisted.' },
},
},
requestId: {
allowFromAnyIp: { type: 'boolean' },
ipAllowlistConfigured: { type: 'boolean' },
allowFromAnyIp: {
type: 'boolean',
_meta: { description: 'Indicates if any http headers have been whitelisted.' },
},
ipAllowlistConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a list of specific IPs has been configured.' },
},
},
ssl: {
certificateAuthoritiesConfigured: { type: 'boolean' },
certificateConfigured: { type: 'boolean' },
cipherSuites: { type: 'array', items: { type: 'keyword' } },
keyConfigured: { type: 'boolean' },
keystoreConfigured: { type: 'boolean' },
truststoreConfigured: { type: 'boolean' },
redirectHttpFromPortConfigured: { type: 'boolean' },
supportedProtocols: { type: 'array', items: { type: 'keyword' } },
clientAuthentication: { type: 'keyword' },
certificateAuthoritiesConfigured: {
type: 'boolean',
_meta: {
description: 'Indicates if ssl certificate authorities have been configured.',
},
},
certificateConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if an ssl certificate is configured.' },
},
cipherSuites: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'The keyword of the cipher suite used.' },
},
},
keyConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if an ssl key has been configured.' },
},
keystoreConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if an ssl keystore has been configured.' },
},
truststoreConfigured: {
type: 'boolean',
_meta: { description: 'Indicates if a path to a PKCS#12 trust store is configured.' },
},
redirectHttpFromPortConfigured: {
type: 'boolean',
_meta: {
description:
'Indicates if a port to redirect all http requests has been configured.',
},
},
supportedProtocols: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'The version of a supported protocol used.' },
},
},
clientAuthentication: {
type: 'keyword',
_meta: {
description:
'The behavior in Kibana for requesting a certificate from client connections.',
},
},
},
},
logging: {
appendersTypesUsed: { type: 'array', items: { type: 'keyword' } },
loggersConfiguredCount: { type: 'long' },
appendersTypesUsed: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'The type of logging appender confgured.' },
},
},
loggersConfiguredCount: {
type: 'long',
_meta: { description: 'The total number of logging appenders configured.' },
},
},
savedObjects: {
customIndex: { type: 'boolean' },
maxImportPayloadBytes: { type: 'long' },
maxImportExportSizeBytes: { type: 'long' },
customIndex: {
type: 'boolean',
_meta: {
description:
'Indicates if the saved objects index is different to the standard internal .kibana index.',
},
},
maxImportPayloadBytes: {
type: 'long',
_meta: {
description:
'Maximum size of the payload in bytes of saved objects that can be imported.',
},
},
maxImportExportSizeBytes: {
type: 'long',
_meta: {
description:
'Maximum size in bytes of saved object that can be imported or exported.',
},
},
},
},
environment: {
memory: {
heapSizeLimit: { type: 'long' },
heapTotalBytes: { type: 'long' },
heapUsedBytes: { type: 'long' },
heapSizeLimit: { type: 'long', _meta: { description: 'Host memory heap size limit.' } },
heapTotalBytes: {
type: 'long',
_meta: { description: 'Total memory heap size of host that is available in bytes.' },
},
heapUsedBytes: {
type: 'long',
_meta: { description: 'Total memory heap size of host that is used in bytes.' },
},
},
},
services: {
@ -96,117 +296,576 @@ export function getCoreUsageCollector(
indices: {
type: 'array',
items: {
docsCount: { type: 'long' },
docsDeleted: { type: 'long' },
alias: { type: 'keyword' },
primaryStoreSizeBytes: { type: 'long' },
storeSizeBytes: { type: 'long' },
docsCount: {
type: 'long',
_meta: {
description:
'The number of documents in the index, including hidden nested documents.',
},
},
docsDeleted: {
type: 'long',
_meta: {
description:
'The number of deleted documents in the index, including hidden nested documents.',
},
},
alias: {
type: 'keyword',
_meta: {
description:
'The alias used to map customized saved object index names to standard index names (.kibana or .kibana_task_manager).',
},
},
primaryStoreSizeBytes: {
type: 'long',
_meta: { description: 'The size in bytes of the index, for primaries only.' },
},
storeSizeBytes: {
type: 'long',
_meta: {
description: 'The size in bytes of the index, for primaries and replicas.',
},
},
},
},
},
},
// Saved Objects Client APIs
'apiCalls.savedObjectsBulkCreate.total': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsBulkGet.total': { type: 'long' },
'apiCalls.savedObjectsBulkGet.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsBulkGet.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.total': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsCreate.total': { type: 'long' },
'apiCalls.savedObjectsCreate.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsCreate.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsDelete.total': { type: 'long' },
'apiCalls.savedObjectsDelete.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsDelete.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsFind.total': { type: 'long' },
'apiCalls.savedObjectsFind.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsFind.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsGet.total': { type: 'long' },
'apiCalls.savedObjectsGet.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsGet.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsResolve.total': { type: 'long' },
'apiCalls.savedObjectsResolve.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsResolve.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsUpdate.total': { type: 'long' },
'apiCalls.savedObjectsUpdate.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsUpdate.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsBulkCreate.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsBulkCreate.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsBulkCreate.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsBulkGet.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsBulkGet.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsBulkGet.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsBulkUpdate.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsBulkUpdate.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsBulkUpdate.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsCreate.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsCreate.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsCreate.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsDelete.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsDelete.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsDelete.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsFind.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsFind.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsFind.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsGet.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsGet.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsGet.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsResolve.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsResolve.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsResolve.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsUpdate.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsUpdate.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsUpdate.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
// Saved Objects Management APIs
'apiCalls.savedObjectsImport.total': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsImport.createNewCopiesEnabled.yes': { type: 'long' },
'apiCalls.savedObjectsImport.createNewCopiesEnabled.no': { type: 'long' },
'apiCalls.savedObjectsImport.overwriteEnabled.yes': { type: 'long' },
'apiCalls.savedObjectsImport.overwriteEnabled.no': { type: 'long' },
'apiCalls.savedObjectsResolveImportErrors.total': { type: 'long' },
'apiCalls.savedObjectsResolveImportErrors.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsImport.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsImport.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsImport.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsImport.createNewCopiesEnabled.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called with the `createNewCopiesEnabled` option.',
},
},
'apiCalls.savedObjectsImport.createNewCopiesEnabled.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called without the `createNewCopiesEnabled` option.',
},
},
'apiCalls.savedObjectsImport.overwriteEnabled.yes': {
type: 'long',
_meta: {
description: 'How many times this API has been called with the `overwrite` option.',
},
},
'apiCalls.savedObjectsImport.overwriteEnabled.no': {
type: 'long',
_meta: {
description: 'How many times this API has been called without the `overwrite` option.',
},
},
'apiCalls.savedObjectsResolveImportErrors.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsResolveImportErrors.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsResolveImportErrors.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsResolveImportErrors.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsResolveImportErrors.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsResolveImportErrors.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsResolveImportErrors.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsResolveImportErrors.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called with the `createNewCopiesEnabled` option.',
},
},
'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called without the `createNewCopiesEnabled` option.',
},
},
'apiCalls.savedObjectsExport.total': {
type: 'long',
_meta: { description: 'How many times this API has been called.' },
},
'apiCalls.savedObjectsExport.namespace.default.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in the Default space.' },
},
'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in the Default space.',
},
},
'apiCalls.savedObjectsExport.namespace.custom.total': {
type: 'long',
_meta: { description: 'How many times this API has been called in a custom space.' },
},
'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called by the Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.no': {
type: 'long',
_meta: {
description:
'How many times this API has been called by a non-Kibana client in a custom space.',
},
},
'apiCalls.savedObjectsExport.allTypesSelected.yes': {
type: 'long',
_meta: {
description:
'How many times this API has been called with the `createNewCopiesEnabled` option.',
},
},
'apiCalls.savedObjectsExport.allTypesSelected.no': {
type: 'long',
_meta: {
description: 'How many times this API has been called without all types selected.',
},
},
'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.yes': { type: 'long' },
'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.no': { type: 'long' },
'apiCalls.savedObjectsExport.total': { type: 'long' },
'apiCalls.savedObjectsExport.namespace.default.total': { type: 'long' },
'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsExport.namespace.custom.total': { type: 'long' },
'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.yes': { type: 'long' },
'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.no': { type: 'long' },
'apiCalls.savedObjectsExport.allTypesSelected.yes': { type: 'long' },
'apiCalls.savedObjectsExport.allTypesSelected.no': { type: 'long' },
},
fetch() {
return getCoreUsageDataService().getCoreUsageData();

View file

@ -34,12 +34,15 @@ export function createCspCollector(http: HttpServiceSetup): UsageCollectorOption
schema: {
strict: {
type: 'boolean',
_meta: { description: 'Indicates if strict mode should be used.' },
},
warnLegacyBrowsers: {
type: 'boolean',
_meta: { description: 'Indicates if legacy browser versions should be warned.' },
},
rulesChangedFromDefault: {
type: 'boolean',
_meta: { description: 'Indicates if the rules have been changed from the default.' },
},
},
};

View file

@ -24,13 +24,37 @@ export function getKibanaUsageCollector(
type: 'kibana',
isReady: () => true,
schema: {
index: { type: 'keyword' },
dashboard: { total: { type: 'long' } },
visualization: { total: { type: 'long' } },
search: { total: { type: 'long' } },
index_pattern: { total: { type: 'long' } },
graph_workspace: { total: { type: 'long' } },
timelion_sheet: { total: { type: 'long' } },
index: { type: 'keyword', _meta: { description: 'The index storing the saved objects' } },
dashboard: {
total: { type: 'long', _meta: { description: 'Total number of dashboard saved objects' } },
},
visualization: {
total: {
type: 'long',
_meta: { description: 'Total number of visualization saved objects' },
},
},
search: {
total: { type: 'long', _meta: { description: 'Total number of search saved objects' } },
},
index_pattern: {
total: {
type: 'long',
_meta: { description: 'Total number of index_pattern saved objects' },
},
},
graph_workspace: {
total: {
type: 'long',
_meta: { description: 'Total number of graph_workspace saved objects' },
},
},
timelion_sheet: {
total: {
type: 'long',
_meta: { description: 'Total number of timelion_sheet saved objects' },
},
},
},
async fetch({ esClient }) {
const {

View file

@ -53,9 +53,27 @@ export function registerLocalizationUsageCollector(
isReady: () => true,
fetch: createCollectorFetch(i18n),
schema: {
locale: { type: 'keyword' },
integrities: { DYNAMIC_KEY: { type: 'text' } },
labelsCount: { type: 'long' },
locale: {
type: 'keyword',
_meta: {
description: 'The default locale set on the Kibana system',
},
},
integrities: {
DYNAMIC_KEY: {
type: 'text',
_meta: {
description:
'Translation file hash. If the hash is different it indicates that a custom translation file is used',
},
},
},
labelsCount: {
type: 'long',
_meta: {
description: 'The number of translated labels',
},
},
},
});

View file

@ -11,121 +11,409 @@ import { UsageStats } from './types';
export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
// sensitive
'timelion:quandl.key': { type: 'keyword' },
'securitySolution:defaultIndex': { type: 'keyword' },
'securitySolution:newsFeedUrl': { type: 'keyword' },
'xpackReporting:customPdfLogo': { type: 'keyword' },
'notifications:banner': { type: 'keyword' },
'timelion:graphite.url': { type: 'keyword' },
'xpackDashboardMode:roles': { type: 'keyword' },
'securitySolution:ipReputationLinks': { type: 'keyword' },
'xPack:defaultAdminEmail': { type: 'keyword' },
'timelion:quandl.key': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'securitySolution:defaultIndex': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'securitySolution:newsFeedUrl': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'xpackReporting:customPdfLogo': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'notifications:banner': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'timelion:graphite.url': {
type: 'keyword',
_meta: { description: 'Default value of the setting changed.' },
},
'xpackDashboardMode:roles': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'securitySolution:ipReputationLinks': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
'xPack:defaultAdminEmail': {
type: 'keyword',
_meta: { description: 'Default value of the setting was changed.' },
},
// non-sensitive
'visualize:enableLabs': { type: 'boolean' },
'visualization:heatmap:maxBuckets': { type: 'long' },
'visualization:colorMapping': { type: 'text' },
'visualization:regionmap:showWarnings': { type: 'boolean' },
'visualization:dimmingOpacity': { type: 'float' },
'visualization:tileMap:maxPrecision': { type: 'long' },
'csv:separator': { type: 'keyword' },
'visualization:tileMap:WMSdefaults': { type: 'text' },
'timelion:target_buckets': { type: 'long' },
'timelion:max_buckets': { type: 'long' },
'timelion:es.timefield': { type: 'keyword' },
'timelion:min_interval': { type: 'keyword' },
'timelion:default_rows': { type: 'long' },
'timelion:default_columns': { type: 'long' },
'timelion:es.default_index': { type: 'keyword' },
'timelion:showTutorial': { type: 'boolean' },
'securitySolution:timeDefaults': { type: 'keyword' },
'securitySolution:defaultAnomalyScore': { type: 'long' },
'securitySolution:refreshIntervalDefaults': { type: 'keyword' },
'securitySolution:enableNewsFeed': { type: 'boolean' },
'search:includeFrozen': { type: 'boolean' },
'courier:maxConcurrentShardRequests': { type: 'long' },
'courier:batchSearches': { type: 'boolean' },
'courier:setRequestPreference': { type: 'keyword' },
'courier:customRequestPreference': { type: 'keyword' },
'courier:ignoreFilterIfFieldNotInIndex': { type: 'boolean' },
'rollups:enableIndexPatterns': { type: 'boolean' },
'notifications:lifetime:warning': { type: 'long' },
'notifications:lifetime:banner': { type: 'long' },
'notifications:lifetime:info': { type: 'long' },
'notifications:lifetime:error': { type: 'long' },
'doc_table:highlight': { type: 'boolean' },
'discover:searchOnPageLoad': { type: 'boolean' },
'visualize:enableLabs': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:heatmap:maxBuckets': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:colorMapping': {
type: 'text',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:regionmap:showWarnings': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:dimmingOpacity': {
type: 'float',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:tileMap:maxPrecision': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'csv:separator': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:tileMap:WMSdefaults': {
type: 'text',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:target_buckets': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:max_buckets': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:es.timefield': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:min_interval': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:default_rows': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:default_columns': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:es.default_index': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'timelion:showTutorial': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:timeDefaults': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:defaultAnomalyScore': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:refreshIntervalDefaults': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:enableNewsFeed': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'search:includeFrozen': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'courier:maxConcurrentShardRequests': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'courier:batchSearches': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'courier:setRequestPreference': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'courier:customRequestPreference': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'courier:ignoreFilterIfFieldNotInIndex': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'rollups:enableIndexPatterns': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'notifications:lifetime:warning': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'notifications:lifetime:banner': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'notifications:lifetime:info': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'notifications:lifetime:error': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'doc_table:highlight': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'discover:searchOnPageLoad': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
// eslint-disable-next-line @typescript-eslint/naming-convention
'doc_table:hideTimeColumn': { type: 'boolean' },
'discover:sampleSize': { type: 'long' },
'doc_table:hideTimeColumn': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'discover:sampleSize': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
defaultColumns: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
},
'context:defaultSize': { type: 'long' },
'discover:aggs:terms:size': { type: 'long' },
'context:defaultSize': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'discover:aggs:terms:size': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'context:tieBreakerFields': {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
},
'discover:sort:defaultOrder': { type: 'keyword' },
'context:step': { type: 'long' },
'accessibility:disableAnimations': { type: 'boolean' },
'ml:fileDataVisualizerMaxFileSize': { type: 'keyword' },
'ml:anomalyDetection:results:enableTimeDefaults': { type: 'boolean' },
'ml:anomalyDetection:results:timeDefaults': { type: 'keyword' },
'truncate:maxHeight': { type: 'long' },
'timepicker:timeDefaults': { type: 'keyword' },
'timepicker:refreshIntervalDefaults': { type: 'keyword' },
'timepicker:quickRanges': { type: 'keyword' },
'theme:version': { type: 'keyword' },
'theme:darkMode': { type: 'boolean' },
'state:storeInSessionStorage': { type: 'boolean' },
'savedObjects:perPage': { type: 'long' },
'search:queryLanguage': { type: 'keyword' },
'shortDots:enable': { type: 'boolean' },
'sort:options': { type: 'keyword' },
'savedObjects:listingLimit': { type: 'long' },
'query:queryString:options': { type: 'keyword' },
'metrics:max_buckets': { type: 'long' },
'query:allowLeadingWildcards': { type: 'boolean' },
'discover:sort:defaultOrder': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'context:step': { type: 'long', _meta: { description: 'Non-default value of setting.' } },
'accessibility:disableAnimations': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'ml:fileDataVisualizerMaxFileSize': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'ml:anomalyDetection:results:enableTimeDefaults': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'ml:anomalyDetection:results:timeDefaults': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'truncate:maxHeight': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'timepicker:timeDefaults': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'timepicker:refreshIntervalDefaults': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'timepicker:quickRanges': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'theme:version': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'theme:darkMode': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'state:storeInSessionStorage': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'savedObjects:perPage': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'search:queryLanguage': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'shortDots:enable': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'sort:options': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'savedObjects:listingLimit': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'query:queryString:options': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'metrics:max_buckets': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'query:allowLeadingWildcards': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
metaFields: {
type: 'array',
items: {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
},
'indexPattern:placeholder': { type: 'keyword' },
'histogram:barTarget': { type: 'long' },
'histogram:maxBars': { type: 'long' },
'format:number:defaultLocale': { type: 'keyword' },
'format:percent:defaultPattern': { type: 'keyword' },
'format:number:defaultPattern': { type: 'keyword' },
'history:limit': { type: 'long' },
'format:defaultTypeMap': { type: 'keyword' },
'format:currency:defaultPattern': { type: 'keyword' },
defaultIndex: { type: 'keyword' },
'format:bytes:defaultPattern': { type: 'keyword' },
'filters:pinnedByDefault': { type: 'boolean' },
'filterEditor:suggestValues': { type: 'boolean' },
'fields:popularLimit': { type: 'long' },
dateNanosFormat: { type: 'keyword' },
defaultRoute: { type: 'keyword' },
'dateFormat:tz': { type: 'keyword' },
'dateFormat:scaled': { type: 'keyword' },
'csv:quoteValues': { type: 'boolean' },
'dateFormat:dow': { type: 'keyword' },
dateFormat: { type: 'keyword' },
'autocomplete:useTimeRange': { type: 'boolean' },
'search:timeout': { type: 'long' },
'visualization:visualize:legacyChartsLibrary': { type: 'boolean' },
'doc_table:legacy': { type: 'boolean' },
'discover:modifyColumnsOnSwitch': { type: 'boolean' },
'discover:searchFieldsFromSource': { type: 'boolean' },
'securitySolution:rulesTableRefresh': { type: 'text' },
'apm:enableSignificantTerms': { type: 'boolean' },
'apm:enableServiceOverview': { type: 'boolean' },
'indexPattern:placeholder': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'histogram:barTarget': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'histogram:maxBars': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'format:number:defaultLocale': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'format:percent:defaultPattern': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'format:number:defaultPattern': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'history:limit': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'format:defaultTypeMap': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'format:currency:defaultPattern': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
defaultIndex: {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'format:bytes:defaultPattern': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'filters:pinnedByDefault': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'filterEditor:suggestValues': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'fields:popularLimit': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
dateNanosFormat: {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
defaultRoute: {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'dateFormat:tz': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'dateFormat:scaled': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
'csv:quoteValues': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'dateFormat:dow': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
dateFormat: { type: 'keyword', _meta: { description: 'Non-default value of setting.' } },
'autocomplete:useTimeRange': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'search:timeout': {
type: 'long',
_meta: { description: 'Non-default value of setting.' },
},
'visualization:visualize:legacyChartsLibrary': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'doc_table:legacy': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'discover:modifyColumnsOnSwitch': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'discover:searchFieldsFromSource': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:rulesTableRefresh': {
type: 'text',
_meta: { description: 'Non-default value of setting.' },
},
'apm:enableSignificantTerms': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'apm:enableServiceOverview': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
};

View file

@ -8,9 +8,9 @@
import { IUiSettingsClient } from 'kibana/server';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { stackManagementSchema } from './schema';
import { UsageStats } from './types';
import { REDACTED_KEYWORD } from '../../../common/constants';
import { stackManagementSchema } from './schema';
export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClient | undefined) {
return async function fetchUsageStats(): Promise<UsageStats | undefined> {
@ -27,7 +27,6 @@ export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClien
obj[key] = sensitive ? REDACTED_KEYWORD : userValue;
return obj;
}, {});
return modifiedEntries;
};
}

View file

@ -12,7 +12,6 @@ import moment from 'moment';
import { OpsMetrics } from 'kibana/server';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { KIBANA_STATS_TYPE } from '../../../common/constants';
interface OpsStatsMetrics extends Omit<OpsMetrics, 'response_times' | 'collected_at'> {
timestamp: string;
response_times: {

View file

@ -52,12 +52,27 @@ export function registerUiCountersUsageCollector(usageCollection: UsageCollectio
dailyEvents: {
type: 'array',
items: {
appName: { type: 'keyword' },
eventName: { type: 'keyword' },
lastUpdatedAt: { type: 'date' },
fromTimestamp: { type: 'date' },
counterType: { type: 'keyword' },
total: { type: 'integer' },
appName: {
type: 'keyword',
_meta: { description: 'Name of the app reporting ui counts.' },
},
eventName: {
type: 'keyword',
_meta: { description: 'Name of the event that happened.' },
},
lastUpdatedAt: {
type: 'date',
_meta: { description: 'Time at which the metric was last updated.' },
},
fromTimestamp: {
type: 'date',
_meta: { description: 'Time at which the metric was captured.' },
},
counterType: { type: 'keyword', _meta: { description: 'The type of counter used.' } },
total: {
type: 'integer',
_meta: { description: 'The total number of times the event happened.' },
},
},
},
},

View file

@ -12,8 +12,8 @@ import { UIMetricUsage } from './telemetry_ui_metric_collector';
const commonSchema: MakeSchemaFrom<UIMetricUsage>[string] = {
type: 'array',
items: {
key: { type: 'keyword' },
value: { type: 'long' },
key: { type: 'keyword', _meta: { description: 'The event that is tracked' } },
value: { type: 'long', _meta: { description: 'The value of the event' } },
},
};

File diff suppressed because it is too large Load diff

View file

@ -205,11 +205,23 @@ In the case of using a custom ES or SavedObjects client, it is up to the plugin
##### Schema Field
The `schema` field is a proscribed data model assists with detecting changes in usage collector payloads. To define the collector schema add a schema field that specifies every possible field reported (including optional fields) when registering the collector. Whenever the `schema` field is set or changed please run `node scripts/telemetry_check.js --fix` to update the stored schema json files.
The `schema` field is a proscribed data model assists with detecting changes in usage collector payloads. To define the collector schema add a schema field that specifies every possible field reported (including optional fields) when registering the collector. The schema supports descriptions as simple strings that allow developers to document what the data represents. The `_meta` field only supports a description property.
```
schema: {
my_greeting: {
type: 'keyword',
_meta: {
description: 'The greeting keyword',
}
}
}
```
Whenever the `schema` field is set or changed please run `node scripts/telemetry_check.js --fix` to update the stored schema json files.
###### Allowed Schema Types
The `AllowedSchemaTypes` is the list of allowed schema types for the usage fields getting reported:
The `AllowedSchemaTypes` is the list of allowed schema types for the usage fields getting reported by the `fetch` method:
```
'long', 'integer', 'short', 'byte', 'double', 'float', 'keyword', 'text', 'boolean', 'date'

View file

@ -167,5 +167,44 @@ describe('collector', () => {
});
expect(collector).toBeDefined();
});
test('TS allows _meta.descriptions in schema', () => {
const collector = new Collector(logger, {
type: 'my_test_collector_with_description',
isReady: () => false,
fetch: () => ({ testPass: 100 }),
schema: {
testPass: { type: 'long' },
_meta: { description: 'Count of testPass as number' },
},
});
expect(collector).toBeDefined();
});
test('schema allows _meta as a data field', () => {
const collector = new Collector(logger, {
type: 'my_test_collector_with_meta_field',
isReady: () => false,
fetch: () => ({ testPass: 100, _meta: 'metaData' }),
schema: {
testPass: { type: 'long' },
_meta: { type: 'keyword' },
},
});
expect(collector).toBeDefined();
});
test('schema allows _meta as a data field that has a description', () => {
const collector = new Collector(logger, {
type: 'my_test_collector_with_meta_field',
isReady: () => false,
fetch: () => ({ testPass: 100, _meta: 'metaData' }),
schema: {
testPass: { type: 'long' },
_meta: { type: 'keyword', _meta: { description: '_meta data as a keyword' } },
},
});
expect(collector).toBeDefined();
});
});
});

View file

@ -45,7 +45,7 @@ export type PossibleSchemaTypes<U> = U extends string
export type RecursiveMakeSchemaFrom<U> = U extends object
? MakeSchemaFrom<U>
: { type: PossibleSchemaTypes<U> };
: { type: PossibleSchemaTypes<U>; _meta?: { description: string } };
// Using Required to enforce all optional keys in the object
export type MakeSchemaFrom<Base> = {

View file

@ -1667,6 +1667,19 @@
}
}
},
"search-session": {
"properties": {
"transientCount": {
"type": "long"
},
"persistedCount": {
"type": "long"
},
"totalCount": {
"type": "long"
}
}
},
"discoverEnhanced": {
"properties": {
"exploreDataInChartActionEnabled": {
@ -3194,19 +3207,6 @@
}
}
},
"search-session": {
"properties": {
"transientCount": {
"type": "long"
},
"persistedCount": {
"type": "long"
},
"totalCount": {
"type": "long"
}
}
},
"security_solution": {
"properties": {
"detections": {