[APM] Add new agent name 'rum-js' (#33212) (#33458)

* [APM] Closes #32643 by adding new agent name 'rum-js' for telemetry and docs links

* [APM] replaced enum with union type + set, and consolidated util functions operating on agent names

* [APM] code cleanup and fixing comments

* [APM] move AgentName type def to es_schemas, and the agent name functions to
common, leverage object hash to reference names

* [APM] code cleanup and improve type assertion between AgentName type and object mapping
This commit is contained in:
Oliver Gupte 2019-03-18 22:58:21 -07:00 committed by GitHub
parent aa23acbaa9
commit 666e6b5718
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 76 additions and 52 deletions

View file

@ -0,0 +1,34 @@
/*
* 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.
*/
/*
* Agent names can be any string. This list only defines the official agents
* that we might want to target specifically eg. linking to their documentation
* & telemetry reporting. Support additional agent types by appending
* definitions in mappings.json (for telemetry), the AgentName type, and the
* agentNames object.
*/
import { AgentName } from '../typings/es_schemas/ui/fields/Agent';
const agentNames: { [agentName in AgentName]: agentName } = {
python: 'python',
java: 'java',
nodejs: 'nodejs',
'js-base': 'js-base',
'rum-js': 'rum-js',
ruby: 'ruby',
go: 'go'
};
export function isAgentName(agentName: string): boolean {
return Object.values(agentNames).includes(agentName as AgentName);
}
export function isRumAgentName(agentName: string): boolean {
return ([agentNames['js-base'], agentNames['rum-js']] as string[]).includes(
agentName
);
}

View file

@ -22,6 +22,10 @@
"type": "long",
"null_value": 0
},
"rum-js": {
"type": "long",
"null_value": 0
},
"ruby": {
"type": "long",
"null_value": 0

View file

@ -10,6 +10,7 @@ import styled from 'styled-components';
import { EuiIcon, EuiText, EuiTitle } from '@elastic/eui';
import theme from '@elastic/eui/dist/eui_theme_light.json';
import { asTime } from 'x-pack/plugins/apm/public/utils/formatters';
import { isRumAgentName } from '../../../../../../../common/agent_name';
import { px, unit, units } from '../../../../../../style/variables';
import { IWaterfallItem } from './waterfall_helpers/waterfall_helpers';
@ -96,8 +97,7 @@ function PrefixIcon({ item }: { item: IWaterfallItem }) {
}
// icon for RUM agent transactions
const isRumAgent = item.transaction.agent.name === 'js-base';
if (isRumAgent) {
if (isRumAgentName(item.transaction.agent.name)) {
return <EuiIcon type="globe" />;
}

View file

@ -15,32 +15,32 @@ type DocUrls = {
const customUrls = {
'js-base': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-custom-context`,
'js-react': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-custom-context`,
go: undefined,
'rum-js': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-custom-context`,
java: undefined,
nodejs: `${AGENT_URL_ROOT}/nodejs/1.x/agent-api.html#apm-set-custom-context`,
python: `${AGENT_URL_ROOT}/python/2.x/api.html#api-set-custom-context`,
ruby: `${AGENT_URL_ROOT}/ruby/1.x/advanced.html#_adding_custom_context`
ruby: `${AGENT_URL_ROOT}/ruby/1.x/advanced.html#_adding_custom_context`,
go: undefined
};
const AGENT_DOC_URLS: DocUrls = {
user: {
'js-base': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-user-context`,
'js-react': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-user-context`,
go: undefined,
'rum-js': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-user-context`,
java: `${AGENT_URL_ROOT}/java/0.7/public-api.html#api-transaction-set-user`,
nodejs: `${AGENT_URL_ROOT}/nodejs/1.x/agent-api.html#apm-set-user-context`,
python: `${AGENT_URL_ROOT}/python/2.x/api.html#api-set-user-context`,
ruby: `${AGENT_URL_ROOT}/ruby/1.x/advanced.html#_providing_info_about_the_user`
ruby: `${AGENT_URL_ROOT}/ruby/1.x/advanced.html#_providing_info_about_the_user`,
go: undefined
},
labels: {
'js-base': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-tags`,
'js-react': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-tags`,
go: undefined,
'rum-js': `${AGENT_URL_ROOT}/js-base/0.x/api.html#apm-set-tags`,
java: `${AGENT_URL_ROOT}/java/0.7/public-api.html#api-transaction-add-tag`,
nodejs: `${AGENT_URL_ROOT}/nodejs/1.x/agent-api.html#apm-set-tag`,
python: `${AGENT_URL_ROOT}/python/2.x/api.html#api-tag`,
ruby: `${AGENT_URL_ROOT}/ruby/1.x/advanced.html#_adding_tags`
ruby: `${AGENT_URL_ROOT}/ruby/1.x/advanced.html#_adding_tags`,
go: undefined
},
'transaction.custom': customUrls,
'error.custom': customUrls

View file

@ -6,7 +6,6 @@
import { SavedObjectAttributes } from 'src/legacy/server/saved_objects/service/saved_objects_client';
import {
AgentName,
APM_TELEMETRY_DOC_ID,
createApmTelementry,
getSavedObjectsClient,
@ -17,31 +16,31 @@ describe('apm_telemetry', () => {
describe('createApmTelementry', () => {
it('should create a ApmTelemetry object with boolean flag and frequency map of the given list of AgentNames', () => {
const apmTelemetry = createApmTelementry([
AgentName.GoLang,
AgentName.NodeJs,
AgentName.GoLang,
AgentName.JsBase
'go',
'nodejs',
'go',
'js-base'
]);
expect(apmTelemetry.has_any_services).toBe(true);
expect(apmTelemetry.services_per_agent).toMatchObject({
[AgentName.GoLang]: 2,
[AgentName.NodeJs]: 1,
[AgentName.JsBase]: 1
go: 2,
nodejs: 1,
'js-base': 1
});
});
it('should ignore undefined or unknown AgentName values', () => {
const apmTelemetry = createApmTelementry([
AgentName.GoLang,
AgentName.NodeJs,
AgentName.GoLang,
AgentName.JsBase,
'go',
'nodejs',
'go',
'js-base',
'example-platform' as any,
undefined as any
]);
expect(apmTelemetry.services_per_agent).toMatchObject({
[AgentName.GoLang]: 2,
[AgentName.NodeJs]: 1,
[AgentName.JsBase]: 1
go: 2,
nodejs: 1,
'js-base': 1
});
});
});
@ -69,9 +68,9 @@ describe('apm_telemetry', () => {
apmTelemetry = {
has_any_services: true,
services_per_agent: {
[AgentName.GoLang]: 2,
[AgentName.NodeJs]: 1,
[AgentName.JsBase]: 1
go: 2,
nodejs: 1,
'js-base': 1
}
};
});

View file

@ -7,27 +7,14 @@
import { Server } from 'hapi';
import { countBy } from 'lodash';
import { SavedObjectAttributes } from 'src/legacy/server/saved_objects/service/saved_objects_client';
// Support telemetry for additional agent types by appending definitions in
// mappings.json and the AgentName enum.
export enum AgentName {
Python = 'python',
Java = 'java',
NodeJs = 'nodejs',
JsBase = 'js-base',
Ruby = 'ruby',
GoLang = 'go'
}
import { isAgentName } from '../../../common/agent_name';
export const APM_TELEMETRY_DOC_ID = 'apm-telemetry';
export function createApmTelementry(
agentNames: AgentName[] = []
agentNames: string[] = []
): SavedObjectAttributes {
const validAgentNames = agentNames.filter(agentName =>
Object.values(AgentName).includes(agentName)
);
const validAgentNames = agentNames.filter(isAgentName);
return {
has_any_services: validAgentNames.length > 0,
services_per_agent: countBy(validAgentNames)

View file

@ -5,7 +5,6 @@
*/
export {
AgentName,
storeApmTelemetry,
createApmTelementry,
APM_TELEMETRY_DOC_ID

View file

@ -6,11 +6,8 @@
import Boom from 'boom';
import { Server } from 'hapi';
import {
AgentName,
createApmTelementry,
storeApmTelemetry
} from '../lib/apm_telemetry';
import { AgentName } from '../../typings/es_schemas/ui/fields/Agent';
import { createApmTelementry, storeApmTelemetry } from '../lib/apm_telemetry';
import { withDefaultValidators } from '../lib/helpers/input_validation';
import { setupRequest } from '../lib/helpers/setup_request';
import { getService } from '../lib/services/get_service';

View file

@ -4,11 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
/*
* Support additional agent types by appending definitions in mappings.json
* (for telemetry) and the AgentName type.
*/
export type AgentName =
| 'go'
| 'java'
| 'js-base'
| 'js-react'
| 'rum-js'
| 'nodejs'
| 'python'
| 'ruby';