Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into np/fix-uuid-on-op…
Browse files Browse the repository at this point in the history
…timize
  • Loading branch information
joshdover committed Feb 28, 2020
2 parents 7bc0225 + 6c6bc1f commit d0bc4d1
Show file tree
Hide file tree
Showing 622 changed files with 9,156 additions and 8,531 deletions.
4 changes: 4 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,7 @@
/x-pack/test/detection_engine_api_integration @elastic/siem
/x-pack/test/api_integration/apis/siem @elastic/siem
/x-pack/plugins/case @elastic/siem

# Security Intelligence And Analytics
/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules @elastic/security-intelligence-analytics
/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules @elastic/security-intelligence-analytics
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface SavedObjectsServiceSetup

When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`<!-- -->.

All the setup APIs will throw if called after the service has started, and therefor cannot be used from legacy plugin code. Legacy plugins should use the legacy savedObject service until migrated.

## Example 1


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SavedObjectsTypeMappingDefinition](./kibana-plugin-server.savedobjectstypemappingdefinition.md) &gt; [dynamic](./kibana-plugin-server.savedobjectstypemappingdefinition.dynamic.md)

## SavedObjectsTypeMappingDefinition.dynamic property

The dynamic property of the mapping. either `false` or 'strict'. Defaults to strict

<b>Signature:</b>

```typescript
dynamic?: false | 'strict';
```
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ const typeDefinition: SavedObjectsTypeMappingDefinition = {

| Property | Type | Description |
| --- | --- | --- |
| [properties](./kibana-plugin-server.savedobjectstypemappingdefinition.properties.md) | <code>SavedObjectsMappingProperties</code> | |
| [dynamic](./kibana-plugin-server.savedobjectstypemappingdefinition.dynamic.md) | <code>false &#124; 'strict'</code> | The dynamic property of the mapping. either <code>false</code> or 'strict'. Defaults to strict |
| [properties](./kibana-plugin-server.savedobjectstypemappingdefinition.properties.md) | <code>SavedObjectsMappingProperties</code> | The underlying properties of the type mapping |

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

## SavedObjectsTypeMappingDefinition.properties property

The underlying properties of the type mapping

<b>Signature:</b>

```typescript
Expand Down
9 changes: 7 additions & 2 deletions examples/ui_action_examples/public/hello_world_action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ import { toMountPoint } from '../../../src/plugins/kibana_react/public';

export const HELLO_WORLD_ACTION_TYPE = 'HELLO_WORLD_ACTION_TYPE';

export const createHelloWorldAction = (openModal: OverlayStart['openModal']) =>
createAction<{}>({
interface StartServices {
openModal: OverlayStart['openModal'];
}

export const createHelloWorldAction = (getStartServices: () => Promise<StartServices>) =>
createAction({
type: HELLO_WORLD_ACTION_TYPE,
getDisplayName: () => 'Hello World!',
execute: async () => {
const { openModal } = await getStartServices();
const overlay = openModal(
toMountPoint(
<EuiModalBody>
Expand Down
28 changes: 16 additions & 12 deletions examples/ui_action_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,34 @@
* under the License.
*/

import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public';
import { UiActionsSetup, UiActionsStart } from '../../../src/plugins/ui_actions/public';
import { createHelloWorldAction, HELLO_WORLD_ACTION_TYPE } from './hello_world_action';
import { helloWorldTrigger } from './hello_world_trigger';
import { Plugin, CoreSetup } from '../../../src/core/public';
import { UiActionsSetup } from '../../../src/plugins/ui_actions/public';
import { createHelloWorldAction } from './hello_world_action';
import { helloWorldTrigger, HELLO_WORLD_TRIGGER_ID } from './hello_world_trigger';

interface UiActionExamplesSetupDependencies {
uiActions: UiActionsSetup;
}

interface UiActionExamplesStartDependencies {
uiActions: UiActionsStart;
declare module '../../../src/plugins/ui_actions/public' {
export interface TriggerContextMapping {
[HELLO_WORLD_TRIGGER_ID]: undefined;
}
}

export class UiActionExamplesPlugin
implements
Plugin<void, void, UiActionExamplesSetupDependencies, UiActionExamplesStartDependencies> {
implements Plugin<void, void, UiActionExamplesSetupDependencies> {
public setup(core: CoreSetup, { uiActions }: UiActionExamplesSetupDependencies) {
uiActions.registerTrigger(helloWorldTrigger);
uiActions.attachAction(helloWorldTrigger.id, HELLO_WORLD_ACTION_TYPE);
}

public start(coreStart: CoreStart, deps: UiActionExamplesStartDependencies) {
deps.uiActions.registerAction(createHelloWorldAction(coreStart.overlays.openModal));
const helloWorldAction = createHelloWorldAction(async () => ({
openModal: (await core.getStartServices())[0].overlays.openModal,
}));

uiActions.registerAction(helloWorldAction);
uiActions.attachAction(helloWorldTrigger.id, helloWorldAction.id);
}

public start() {}
public stop() {}
}
30 changes: 19 additions & 11 deletions examples/ui_actions_explorer/public/actions/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@ export const EDIT_USER_ACTION = 'EDIT_USER_ACTION';
export const PHONE_USER_ACTION = 'PHONE_USER_ACTION';
export const SHOWCASE_PLUGGABILITY_ACTION = 'SHOWCASE_PLUGGABILITY_ACTION';

export const showcasePluggability = createAction<{}>({
export const showcasePluggability = createAction({
type: SHOWCASE_PLUGGABILITY_ACTION,
getDisplayName: () => 'This is pluggable! Any plugin can inject their actions here.',
execute: async ({}) => alert("Isn't that cool?!"),
execute: async () => alert("Isn't that cool?!"),
});

export const makePhoneCallAction = createAction<{ phone: string }>({
export type PhoneContext = string;

export const makePhoneCallAction = createAction<PhoneContext>({
type: CALL_PHONE_NUMBER_ACTION,
getDisplayName: () => 'Call phone number',
execute: async ({ phone }) => alert(`Pretend calling ${phone}...`),
execute: async phone => alert(`Pretend calling ${phone}...`),
});

export const lookUpWeatherAction = createAction<{ country: string }>({
Expand All @@ -55,11 +57,13 @@ export const lookUpWeatherAction = createAction<{ country: string }>({
},
});

export const viewInMapsAction = createAction<{ country: string }>({
export type CountryContext = string;

export const viewInMapsAction = createAction<CountryContext>({
type: VIEW_IN_MAPS_ACTION,
getIconType: () => 'popout',
getDisplayName: () => 'View in maps',
execute: async ({ country }) => {
execute: async country => {
window.open(`https://www.google.com/maps/place/${country}`, '_blank');
},
});
Expand Down Expand Up @@ -110,11 +114,13 @@ export const createEditUserAction = (getOpenModal: () => Promise<OverlayStart['o
},
});

export interface UserContext {
user: User;
update: (user: User) => void;
}

export const createPhoneUserAction = (getUiActionsApi: () => Promise<UiActionsStart>) =>
createAction<{
user: User;
update: (user: User) => void;
}>({
createAction<UserContext>({
type: PHONE_USER_ACTION,
getDisplayName: () => 'Call phone number',
isCompatible: async ({ user }) => user.phone !== undefined,
Expand All @@ -126,6 +132,8 @@ export const createPhoneUserAction = (getUiActionsApi: () => Promise<UiActionsSt
// to the phone number trigger.
// TODO: we need to figure out the best way to handle these nested actions however, since
// we don't want multiple context menu's to pop up.
(await getUiActionsApi()).executeTriggerActions(PHONE_TRIGGER, { phone: user.phone });
if (user.phone !== undefined) {
(await getUiActionsApi()).executeTriggerActions(PHONE_TRIGGER, user.phone);
}
},
});
2 changes: 1 addition & 1 deletion examples/ui_actions_explorer/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => {
</EuiText>
<EuiButton
data-test-subj="emitHelloWorldTrigger"
onClick={() => uiActionsApi.executeTriggerActions(HELLO_WORLD_TRIGGER_ID, {})}
onClick={() => uiActionsApi.executeTriggerActions(HELLO_WORLD_TRIGGER_ID, undefined)}
>
Say hello world!
</EuiButton>
Expand Down
11 changes: 11 additions & 0 deletions examples/ui_actions_explorer/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import {
makePhoneCallAction,
showcasePluggability,
SHOWCASE_PLUGGABILITY_ACTION,
UserContext,
CountryContext,
PhoneContext,
} from './actions/actions';

interface StartDeps {
Expand All @@ -45,6 +48,14 @@ interface SetupDeps {
uiActions: UiActionsSetup;
}

declare module '../../../src/plugins/ui_actions/public' {
export interface TriggerContextMapping {
[USER_TRIGGER]: UserContext;
[COUNTRY_TRIGGER]: CountryContext;
[PHONE_TRIGGER]: PhoneContext;
}
}

export class UiActionsExplorerPlugin implements Plugin<void, void, {}, StartDeps> {
public setup(core: CoreSetup<{ uiActions: UiActionsStart }>, deps: SetupDeps) {
deps.uiActions.registerTrigger({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ const createRowData = (
<Fragment>
<EuiButtonEmpty
onClick={() => {
uiActionsApi.executeTriggerActions(COUNTRY_TRIGGER, {
country: user.countryOfResidence,
});
uiActionsApi.executeTriggerActions(COUNTRY_TRIGGER, user.countryOfResidence);
}}
>
{user.countryOfResidence}
Expand All @@ -59,10 +57,9 @@ const createRowData = (
phone: (
<Fragment>
<EuiButtonEmpty
disabled={user.phone === undefined}
onClick={() => {
uiActionsApi.executeTriggerActions(PHONE_TRIGGER, {
phone: user.phone,
});
uiActionsApi.executeTriggerActions(PHONE_TRIGGER, user.phone!);
}}
>
{user.phone}
Expand Down
56 changes: 56 additions & 0 deletions packages/kbn-analytics/src/metrics/application_usage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import moment, { Moment } from 'moment-timezone';
import { METRIC_TYPE } from './';

export interface ApplicationUsageCurrent {
type: METRIC_TYPE.APPLICATION_USAGE;
appId: string;
startTime: Moment;
numberOfClicks: number;
}

export class ApplicationUsage {
private currentUsage?: ApplicationUsageCurrent;

public start() {
// Count any clicks and assign it to the current app
if (window)
window.addEventListener(
'click',
() => this.currentUsage && this.currentUsage.numberOfClicks++
);
}

public appChanged(appId?: string) {
const currentUsage = this.currentUsage;

if (appId) {
this.currentUsage = {
type: METRIC_TYPE.APPLICATION_USAGE,
appId,
startTime: moment(),
numberOfClicks: 0,
};
} else {
this.currentUsage = void 0;
}
return currentUsage;
}
}
5 changes: 4 additions & 1 deletion packages/kbn-analytics/src/metrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@

import { UiStatsMetric } from './ui_stats';
import { UserAgentMetric } from './user_agent';
import { ApplicationUsageCurrent } from './application_usage';

export { UiStatsMetric, createUiStatsMetric, UiStatsMetricType } from './ui_stats';
export { Stats } from './stats';
export { trackUsageAgent } from './user_agent';
export { ApplicationUsage, ApplicationUsageCurrent } from './application_usage';

export type Metric = UiStatsMetric | UserAgentMetric;
export type Metric = UiStatsMetric | UserAgentMetric | ApplicationUsageCurrent;
export enum METRIC_TYPE {
COUNT = 'count',
LOADED = 'loaded',
CLICK = 'click',
USER_AGENT = 'user_agent',
APPLICATION_USAGE = 'application_usage',
}
29 changes: 27 additions & 2 deletions packages/kbn-analytics/src/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

import moment from 'moment-timezone';
import { UnreachableCaseError, wrapArray } from './util';
import { Metric, Stats, UiStatsMetricType, METRIC_TYPE } from './metrics';
const REPORT_VERSION = 1;
Expand All @@ -42,6 +43,13 @@ export interface Report {
appName: string;
}
>;
application_usage?: Record<
string,
{
minutesOnScreen: number;
numberOfClicks: number;
}
>;
}

export class ReportManager {
Expand All @@ -57,10 +65,11 @@ export class ReportManager {
this.report = ReportManager.createReport();
}
public isReportEmpty(): boolean {
const { uiStatsMetrics, userAgent } = this.report;
const { uiStatsMetrics, userAgent, application_usage: appUsage } = this.report;
const noUiStats = !uiStatsMetrics || Object.keys(uiStatsMetrics).length === 0;
const noUserAgent = !userAgent || Object.keys(userAgent).length === 0;
return noUiStats && noUserAgent;
const noAppUsage = !appUsage || Object.keys(appUsage).length === 0;
return noUiStats && noUserAgent && noAppUsage;
}
private incrementStats(count: number, stats?: Stats): Stats {
const { min = 0, max = 0, sum = 0 } = stats || {};
Expand Down Expand Up @@ -92,6 +101,8 @@ export class ReportManager {
const { appName, eventName, type } = metric;
return `${appName}-${type}-${eventName}`;
}
case METRIC_TYPE.APPLICATION_USAGE:
return metric.appId;
default:
throw new UnreachableCaseError(metric);
}
Expand Down Expand Up @@ -129,6 +140,20 @@ export class ReportManager {
};
return;
}
case METRIC_TYPE.APPLICATION_USAGE:
const { numberOfClicks, startTime } = metric;
const minutesOnScreen = moment().diff(startTime, 'minutes', true);

report.application_usage = report.application_usage || {};
const appExistingData = report.application_usage[key] || {
minutesOnScreen: 0,
numberOfClicks: 0,
};
report.application_usage[key] = {
minutesOnScreen: appExistingData.minutesOnScreen + minutesOnScreen,
numberOfClicks: appExistingData.numberOfClicks + numberOfClicks,
};
break;
default:
throw new UnreachableCaseError(metric);
}
Expand Down
Loading

0 comments on commit d0bc4d1

Please sign in to comment.