Skip to content

Commit ae6e1e6

Browse files
authored
Fix Google Analytics tracking (jaegertracing#81)
* Fix Google Analytics tracking * Google Analytics tracking moved to a higher level component * Misc css tweak Signed-off-by: vvvprabhakar <vvvprabhakar@gmail.com>
1 parent bfdc08d commit ae6e1e6

File tree

8 files changed

+211
-63
lines changed

8 files changed

+211
-63
lines changed

.flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[include]
99

1010
[libs]
11+
./flow-typed/npm
1112

1213
[options]
1314

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// flow-typed signature: 4d8e947f2e396ef2f26ecbd1ed7f04ab
2+
// flow-typed version: 97d98ab83e/react-router-dom_v4.x.x/flow_>=v0.53.x
3+
4+
declare module 'react-router-dom' {
5+
declare export class BrowserRouter extends React$Component<{
6+
basename?: string,
7+
forceRefresh?: boolean,
8+
getUserConfirmation?: GetUserConfirmation,
9+
keyLength?: number,
10+
children?: React$Node,
11+
}> {}
12+
13+
declare export class HashRouter extends React$Component<{
14+
basename?: string,
15+
getUserConfirmation?: GetUserConfirmation,
16+
hashType?: 'slash' | 'noslash' | 'hashbang',
17+
children?: React$Node,
18+
}> {}
19+
20+
declare export class Link extends React$Component<{
21+
to: string | LocationShape,
22+
replace?: boolean,
23+
children?: React$Node,
24+
}> {}
25+
26+
declare export class NavLink extends React$Component<{
27+
to: string | LocationShape,
28+
activeClassName?: string,
29+
className?: string,
30+
activeStyle?: Object,
31+
style?: Object,
32+
isActive?: (match: Match, location: Location) => boolean,
33+
children?: React$Node,
34+
exact?: boolean,
35+
strict?: boolean,
36+
}> {}
37+
38+
// NOTE: Below are duplicated from react-router. If updating these, please
39+
// update the react-router and react-router-native types as well.
40+
declare export type Location = {
41+
pathname: string,
42+
search: string,
43+
hash: string,
44+
state?: any,
45+
key?: string,
46+
};
47+
48+
declare export type LocationShape = {
49+
pathname?: string,
50+
search?: string,
51+
hash?: string,
52+
state?: any,
53+
};
54+
55+
declare export type HistoryAction = 'PUSH' | 'REPLACE' | 'POP';
56+
57+
declare export type RouterHistory = {
58+
length: number,
59+
location: Location,
60+
action: HistoryAction,
61+
listen(callback: (location: Location, action: HistoryAction) => void): () => void,
62+
push(path: string | LocationShape, state?: any): void,
63+
replace(path: string | LocationShape, state?: any): void,
64+
go(n: number): void,
65+
goBack(): void,
66+
goForward(): void,
67+
canGo?: (n: number) => boolean,
68+
block(callback: (location: Location, action: HistoryAction) => boolean): void,
69+
// createMemoryHistory
70+
index?: number,
71+
entries?: Array<Location>,
72+
};
73+
74+
declare export type Match = {
75+
params: { [key: string]: ?string },
76+
isExact: boolean,
77+
path: string,
78+
url: string,
79+
};
80+
81+
declare export type ContextRouter = {|
82+
history: RouterHistory,
83+
location: Location,
84+
match: Match,
85+
|};
86+
87+
declare export type GetUserConfirmation = (message: string, callback: (confirmed: boolean) => void) => void;
88+
89+
declare type StaticRouterContext = {
90+
url?: string,
91+
};
92+
93+
declare export class StaticRouter extends React$Component<{
94+
basename?: string,
95+
location?: string | Location,
96+
context: StaticRouterContext,
97+
children?: React$Node,
98+
}> {}
99+
100+
declare export class MemoryRouter extends React$Component<{
101+
initialEntries?: Array<LocationShape | string>,
102+
initialIndex?: number,
103+
getUserConfirmation?: GetUserConfirmation,
104+
keyLength?: number,
105+
children?: React$Node,
106+
}> {}
107+
108+
declare export class Router extends React$Component<{
109+
history: RouterHistory,
110+
children?: React$Node,
111+
}> {}
112+
113+
declare export class Prompt extends React$Component<{
114+
message: string | ((location: Location) => string | true),
115+
when?: boolean,
116+
}> {}
117+
118+
declare export class Redirect extends React$Component<{
119+
to: string | LocationShape,
120+
push?: boolean,
121+
}> {}
122+
123+
declare export class Route extends React$Component<{
124+
component?: React$ComponentType<*>,
125+
render?: (router: ContextRouter) => React$Node,
126+
children?: React$ComponentType<ContextRouter> | React$Node,
127+
path?: string,
128+
exact?: boolean,
129+
strict?: boolean,
130+
}> {}
131+
132+
declare export class Switch extends React$Component<{
133+
children?: React$Node,
134+
}> {}
135+
136+
declare export function withRouter<P>(
137+
Component: React$ComponentType<{| ...ContextRouter, ...P |}>
138+
): React$ComponentType<P>;
139+
140+
declare type MatchPathOptions = {
141+
path?: string,
142+
exact?: boolean,
143+
sensitive?: boolean,
144+
strict?: boolean,
145+
};
146+
147+
declare export function matchPath(pathname: string, options?: MatchPathOptions | string): null | Match;
148+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"test": "react-scripts test --env=jsdom",
7777
"coverage": "npm run test -- --coverage",
7878
"lint": "npm run eslint && npm run prettier && npm run flow",
79-
"eslint": "eslint .",
79+
"eslint": "eslint src",
8080
"prettier": "prettier --single-quote --trailing-comma es5 --print-width 110 --write \"src/**/*.js\"",
8181
"flow": "flow; test $? -eq 0 -o $? -eq 2",
8282
"set-homepage": "json -I -f package.json -e 'this.homepage=process.env.HOMEPAGE'",

src/components/App/Page.js

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// @flow
2+
13
// Copyright (c) 2017 Uber Technologies, Inc.
24
//
35
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -18,26 +20,54 @@
1820
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1921
// THE SOFTWARE.
2022

21-
import PropTypes from 'prop-types';
22-
import React from 'react';
23+
import * as React from 'react';
2324
import Helmet from 'react-helmet';
25+
import { connect } from 'react-redux';
26+
import type { Location } from 'react-router-dom';
2427

2528
import TopNav from './TopNav';
29+
import { trackPageView } from '../../utils/metrics';
2630

2731
import './Page.css';
2832

29-
export default function JaegerUIPage({ children }) {
30-
return (
31-
<section className="jaeger-ui-page" id="jaeger-ui">
32-
<Helmet title="Jaeger UI" />
33-
<TopNav />
34-
<div className="jaeger-ui--content">
35-
{children}
36-
</div>
37-
</section>
38-
);
33+
type PageProps = {
34+
location: Location,
35+
children: React.Node,
36+
};
37+
38+
class Page extends React.Component<PageProps> {
39+
props: PageProps;
40+
41+
componentDidMount() {
42+
const { pathname, search } = this.props.location;
43+
trackPageView(pathname, search);
44+
}
45+
46+
componentWillReceiveProps(nextProps: PageProps) {
47+
const { pathname, search } = this.props.location;
48+
const { pathname: nextPathname, search: nextSearch } = nextProps.location;
49+
if (pathname !== nextPathname || search !== nextSearch) {
50+
trackPageView(nextPathname, nextSearch);
51+
}
52+
}
53+
54+
render() {
55+
const { children } = this.props;
56+
return (
57+
<section className="jaeger-ui-page" id="jaeger-ui">
58+
<Helmet title="Jaeger UI" />
59+
<TopNav />
60+
<div className="jaeger-ui--content">
61+
{children}
62+
</div>
63+
</section>
64+
);
65+
}
3966
}
4067

41-
JaegerUIPage.propTypes = {
42-
children: PropTypes.node,
43-
};
68+
function mapStateToProps(state, ownProps) {
69+
const { location } = state.routing;
70+
return { ...ownProps, location };
71+
}
72+
73+
export default connect(mapStateToProps)(Page);

src/components/App/index.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import React, { Component } from 'react';
2222
import createHistory from 'history/createBrowserHistory';
2323
import PropTypes from 'prop-types';
24-
import { metrics } from 'react-metrics';
2524
import { Provider } from 'react-redux';
2625
import { Route, Redirect, Switch } from 'react-router-dom';
2726
import { ConnectedRouter } from 'react-router-redux';
@@ -35,13 +34,10 @@ import { ConnectedSearchTracePage } from '../SearchTracePage';
3534
import { ConnectedTracePage } from '../TracePage';
3635
import JaegerAPI, { DEFAULT_API_ROOT } from '../../api/jaeger';
3736
import configureStore from '../../utils/configure-store';
38-
import metricConfig from '../../utils/metrics';
3937
import prefixUrl from '../../utils/prefix-url';
4038

4139
import './App.css';
4240

43-
const PageWithMetrics = metrics(metricConfig)(Page);
44-
4541
const defaultHistory = createHistory();
4642

4743
export default class JaegerUIApp extends Component {
@@ -70,7 +66,7 @@ export default class JaegerUIApp extends Component {
7066
return (
7167
<Provider store={store}>
7268
<ConnectedRouter history={history}>
73-
<PageWithMetrics>
69+
<Page>
7470
<Switch>
7571
<Route path={prefixUrl('/search')} component={ConnectedSearchTracePage} />
7672
<Route path={prefixUrl('/trace/:id')} component={ConnectedTracePage} />
@@ -80,7 +76,7 @@ export default class JaegerUIApp extends Component {
8076
<Redirect exact path={prefixUrl('/')} to={prefixUrl('/search')} />
8177
<Route component={NotFound} />
8278
</Switch>
83-
</PageWithMetrics>
79+
</Page>
8480
</ConnectedRouter>
8581
</Provider>
8682
);

src/components/TracePage/TraceTimelineViewer/SpanBarRow.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ THE SOFTWARE.
3838
width: 6px;
3939
background-image: linear-gradient(to right, rgba(25, 25, 25, 0.25), rgba(32, 32, 32, 0.0));
4040
left: 100%;
41-
z-index: 1;
41+
z-index: -1;
4242
}
4343

4444
.span-name-wrapper {

src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@ import { document } from 'global';
2525
import 'basscss/css/basscss.css';
2626

2727
import JaegerUIApp from './components/App';
28+
import { init as initTracking } from './utils/metrics';
2829

2930
/* istanbul ignore if */
3031
if (process.env.NODE_ENV === 'development') {
3132
require.ensure(['global/window', 'react-addons-perf'], require => {
3233
const window = require('global/window');
33-
/* eslint-disable import/no-extraneous-dependencies */
34+
// eslint-disable-next-line import/no-extraneous-dependencies
3435
window.Perf = require('react-addons-perf');
35-
/* eslint-enable import/no-extraneous-dependencies */
3636
});
3737
}
3838

39+
initTracking();
40+
3941
const UI_ROOT_ID = 'jaeger-ui-root';
4042

4143
/* istanbul ignore if */

src/utils/metrics.js

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,43 +20,14 @@
2020

2121
import ReactGA from 'react-ga';
2222

23-
if (process.env.NODE_ENV === 'production' && process.env.REACT_APP_GA_TRACKING_ID) {
24-
const GA_CODE = process.env.REACT_APP_GA_TRACKING_ID;
25-
ReactGA.initialize(GA_CODE);
23+
export function init() {
24+
if (process.env.NODE_ENV === 'production' && process.env.REACT_APP_GA_TRACKING_ID) {
25+
const GA_CODE = process.env.REACT_APP_GA_TRACKING_ID;
26+
ReactGA.initialize(GA_CODE);
27+
}
2628
}
2729

28-
const GoogleAnalytics = {
29-
pageView(event, fields) {
30-
ReactGA.set({
31-
page: fields.page,
32-
});
33-
ReactGA.pageview(fields.pathname);
34-
},
35-
track(eventName, params) {
36-
ReactGA.event({
37-
category: params.page,
38-
action: eventName,
39-
label: params.label,
40-
value: params.value,
41-
});
42-
},
43-
};
44-
45-
export default {
46-
enabled: process.env.NODE_ENV === 'production',
47-
debug: process.env.NODE_ENV === 'development',
48-
vendors: [
49-
{
50-
name: 'Google Analytics',
51-
api: GoogleAnalytics,
52-
},
53-
],
54-
pageDefaults(routeState) {
55-
const paths = routeState.pathname.substr(1).split('/');
56-
return {
57-
pathname: routeState.pathname,
58-
query: routeState.query,
59-
page: !paths[0] ? 'landing' : paths[0],
60-
};
61-
},
62-
};
30+
export function trackPageView(pathname, search) {
31+
const pagePath = search ? `${pathname}?${search}` : pathname;
32+
ReactGA.pageview(pagePath);
33+
}

0 commit comments

Comments
 (0)