Skip to content

Commit

Permalink
Integrate Google Analytics into Search Page (jaegertracing#220)
Browse files Browse the repository at this point in the history
* Integrate GA into search page

Signed-off-by: Davit Yeghshatyan <[email protected]>

* Review changes

Signed-off-by: Davit Yeghshatyan <[email protected]>

* Remove tracking of actual values

Signed-off-by: Davit Yeghshatyan <[email protected]>

Signed-off-by: vvvprabhakar <[email protected]>
  • Loading branch information
davit-y authored and tiffon committed Jun 25, 2018
1 parent 4d29533 commit df73678
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ coverage
.DS_Store
npm-debug.log
.vscode
.idea
yarn-error.log

lerna-debug\.log
12 changes: 8 additions & 4 deletions packages/jaeger-ui/src/components/SearchTracePage/SearchForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ import { Field, reduxForm, formValueSelector } from 'redux-form';
import store from 'store';

import * as markers from './SearchForm.markers';
import { trackFormInput } from './SearchForm.track';
import VirtSelect from '../common/VirtSelect';
import * as jaegerApiActions from '../../actions/jaeger-api';
import { formatDate, formatTime } from '../../utils/date';
import reduxFormFieldAdapter from '../../utils/redux-form-field-adapter';
import { DEFAULT_OPERATION, DEFAULT_LIMIT, DEFAULT_LOOKBACK } from '../../constants/search-form';

import './SearchForm.css';

Expand Down Expand Up @@ -134,9 +136,11 @@ export function submitForm(fields, searchTraces) {
end = times.end;
}

trackFormInput(resultsLimit, operation, tags, minDuration, maxDuration, lookback);

searchTraces({
service,
operation: operation !== 'all' ? operation : undefined,
operation: operation !== DEFAULT_OPERATION ? operation : undefined,
limit: resultsLimit,
lookback,
start,
Expand Down Expand Up @@ -459,13 +463,13 @@ export function mapStateToProps(state) {
destroyOnUnmount: false,
initialValues: {
service: service || lastSearchService || '-',
resultsLimit: limit || 20,
lookback: lookback || '1h',
resultsLimit: limit || DEFAULT_LIMIT,
lookback: lookback || DEFAULT_LOOKBACK,
startDate: queryStartDate || today,
startDateTime: queryStartDateTime || '00:00',
endDate: queryEndDate || today,
endDateTime: queryEndDateTime || currentTime,
operation: operation || lastSearchOperation || 'all',
operation: operation || lastSearchOperation || DEFAULT_OPERATION,
tags,
minDuration: minDuration || null,
maxDuration: maxDuration || null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// @flow

// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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 type { Store } from 'redux';

import * as constants from '../../constants/search-form';
import { trackEvent } from '../../utils/tracking';

export const ACTION_SET = 'set';
export const ACTION_CLEAR = 'clear';
export const ACTION_DEFAULT = 'default';

export const CATEGORY_SORTBY = `jaeger/ux/search/results/sortby`;
export const FORM_CATEGORY_BASE = 'jaeger/ux/search/form';
export const CATEGORY_OPERATION = `${FORM_CATEGORY_BASE}/operation`;
export const CATEGORY_LOOKBACK = `${FORM_CATEGORY_BASE}/lookback`;
export const CATEGORY_TAGS = `${FORM_CATEGORY_BASE}/tags`;
export const CATEGORY_MIN_DURATION = `${FORM_CATEGORY_BASE}/min_duration`;
export const CATEGORY_MAX_DURATION = `${FORM_CATEGORY_BASE}/max_duration`;
export const CATEGORY_LIMIT = `${FORM_CATEGORY_BASE}/limit`;

export function trackFormInput(
resultsLimit: number,
operation: string,
tags: any,
minDuration: number,
maxDuration: number,
lookback: string
) {
trackEvent(CATEGORY_OPERATION, operation === constants.DEFAULT_OPERATION ? ACTION_DEFAULT : ACTION_SET);
trackEvent(CATEGORY_LIMIT, resultsLimit === constants.DEFAULT_LIMIT ? ACTION_DEFAULT : ACTION_SET);
trackEvent(CATEGORY_MAX_DURATION, maxDuration ? ACTION_SET : ACTION_CLEAR);
trackEvent(CATEGORY_MIN_DURATION, minDuration ? ACTION_SET : ACTION_CLEAR);
trackEvent(CATEGORY_TAGS, tags ? ACTION_SET : ACTION_CLEAR);
trackEvent(CATEGORY_LOOKBACK, lookback);
}

export const middlewareHooks = {
[constants.FORM_CHANGE_ACTION_TYPE]: (store: Store, action: any) => {
if (action.meta.form === 'sortBy') {
trackEvent(CATEGORY_SORTBY, action.payload);
}
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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.

/* eslint-disable import/first */
jest.mock('../../utils/tracking');

import {
middlewareHooks,
trackFormInput,
CATEGORY_LIMIT,
CATEGORY_LOOKBACK,
CATEGORY_MAX_DURATION,
CATEGORY_MIN_DURATION,
CATEGORY_OPERATION,
CATEGORY_SORTBY,
CATEGORY_TAGS,
} from './SearchForm.track';
import { FORM_CHANGE_ACTION_TYPE } from '../../constants/search-form';
import { trackEvent } from '../../utils/tracking';

describe('GA tracking', () => {
it('tracks changing sort criteria', () => {
const action = { meta: { form: 'sortBy' }, payload: 'MOST_RECENT' };
middlewareHooks[FORM_CHANGE_ACTION_TYPE]({}, action);
expect(trackEvent.mock.calls.length).toBe(1);
expect(trackEvent.mock.calls[0]).toEqual([CATEGORY_SORTBY, expect.any(String)]);
});

it('sends form input to GA', () => {
trackEvent.mockClear();
trackFormInput(0, '', {}, 0, 0, '');
expect(trackEvent.mock.calls.length).toBe(6);
const categoriesTracked = trackEvent.mock.calls.map(call => call[0]).sort();
expect(categoriesTracked).toEqual(
[
CATEGORY_OPERATION,
CATEGORY_LIMIT,
CATEGORY_TAGS,
CATEGORY_MAX_DURATION,
CATEGORY_MIN_DURATION,
CATEGORY_LOOKBACK,
].sort()
);
});
});
19 changes: 19 additions & 0 deletions packages/jaeger-ui/src/constants/search-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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.

export const DEFAULT_OPERATION = 'all';
export const DEFAULT_LOOKBACK = '1h';
export const DEFAULT_LIMIT = 20;

export const FORM_CHANGE_ACTION_TYPE = '@@redux-form/CHANGE';
5 changes: 4 additions & 1 deletion packages/jaeger-ui/src/middlewares/track.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { middlewareHooks } from '../components/TracePage/TraceTimelineViewer/duck.track';
import { middlewareHooks as searchHooks } from '../components/SearchTracePage/SearchForm.track';
import { middlewareHooks as timelineHooks } from '../components/TracePage/TraceTimelineViewer/duck.track';
import { isGaEnabled } from '../utils/tracking';

const middlewareHooks = { ...timelineHooks, ...searchHooks };

function trackingMiddleware(store: { getState: () => any }) {
return function inner(next: any => void) {
return function core(action: any) {
Expand Down

0 comments on commit df73678

Please sign in to comment.