Skip to content

Commit

Permalink
feat(@cubejs-client/playground): display slow query warning (#1649)
Browse files Browse the repository at this point in the history
* feat(@cubejs-client/playground): display slow query warning

* minor fixes, angular build

* babelrc fix

* merge fix
  • Loading branch information
vasilev-alex committed Jan 11, 2021
1 parent 118232f commit ce33f88
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 29 deletions.
9 changes: 7 additions & 2 deletions packages/cubejs-api-gateway/src/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ export class ApiGateway {
))
);

let slowQuery = false;
const results = await Promise.all(normalizedQueries.map(async (normalizedQuery, index) => {
const sqlQuery = sqlQueries[index];
const annotation = prepareAnnotation(metaConfigResult, normalizedQuery);
Expand All @@ -495,6 +496,8 @@ export class ApiGateway {
...annotation.timeDimensions
};

slowQuery = slowQuery || Boolean(response.slowQuery);

return {
query: normalizedQuery,
data: transformData(
Expand All @@ -509,7 +512,8 @@ export class ApiGateway {
refreshKeyValues: response.refreshKeyValues,
usedPreAggregations: response.usedPreAggregations
}),
annotation
annotation,
slowQuery: Boolean(response.slowQuery)
};
}));

Expand All @@ -527,7 +531,8 @@ export class ApiGateway {
res({
queryType,
results,
pivotQuery: getPivotQuery(queryType, normalizedQueries)
pivotQuery: getPivotQuery(queryType, normalizedQueries),
slowQuery
});
} else {
res(results[0]);
Expand Down
3 changes: 2 additions & 1 deletion packages/cubejs-playground/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-optional-chaining"
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-class-properties"
]
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><base href="/"/><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><link href="/chart-renderers/react/static/css/2.efb9cb5d.chunk.css" rel="stylesheet"><link href="/chart-renderers/react/static/css/main.85b3ce99.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,a,i=r[0],c=r[1],l=r[2],s=0,p=[];s<i.length;s++)a=i[s],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&p.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(f&&f(r);p.length;)p.shift()();return u.push.apply(u,l||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+"static/js/"+({}[e]||e)+"."+{3:"e67f4d17"}[e]+".chunk.js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(l);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var l=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/",a.oe=function(e){throw console.error(e),e};var i=this["webpackJsonpreact-charts"]=this["webpackJsonpreact-charts"]||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var l=0;l<i.length;l++)r(i[l]);var f=c;t()}([])</script><script src="/chart-renderers/react/static/js/2.fa50db8e.chunk.js"></script><script src="/chart-renderers/react/static/js/main.896e020f.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><base href="/"/><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><link href="/chart-renderers/react/static/css/2.efb9cb5d.chunk.css" rel="stylesheet"><link href="/chart-renderers/react/static/css/main.85b3ce99.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,a,i=r[0],c=r[1],l=r[2],s=0,p=[];s<i.length;s++)a=i[s],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&p.push(o[a][0]),o[a]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(f&&f(r);p.length;)p.shift()();return u.push.apply(u,l||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var c=t[i];0!==o[c]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,i=document.createElement("script");i.charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.src=function(e){return a.p+"static/js/"+({}[e]||e)+"."+{3:"e67f4d17"}[e]+".chunk.js"}(e);var c=new Error;u=function(r){i.onerror=i.onload=null,clearTimeout(l);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var l=setTimeout((function(){u({type:"timeout",target:i})}),12e4);i.onerror=i.onload=u,document.head.appendChild(i)}return Promise.all(r)},a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/",a.oe=function(e){throw console.error(e),e};var i=this["webpackJsonpreact-charts"]=this["webpackJsonpreact-charts"]||[],c=i.push.bind(i);i.push=r,i=i.slice();for(var l=0;l<i.length;l++)r(i[l]);var f=c;t()}([])</script><script src="/chart-renderers/react/static/js/2.9467ee4a.chunk.js"></script><script src="/chart-renderers/react/static/js/main.0400d951.chunk.js"></script></body></html>

Large diffs are not rendered by default.

Large diffs are not rendered by default.

60 changes: 43 additions & 17 deletions packages/cubejs-playground/src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-undef,react/jsx-no-target-blank */
import React, { Component } from 'react';
import React, { Component, createContext } from 'react';
import * as PropTypes from 'prop-types';
import '@ant-design/compatible/assets/index.css';
import './index.less';
Expand All @@ -19,12 +19,32 @@ const selectedTab = (pathname) => {
}
};

export const AppContext = createContext({
slowQuery: false,
});

class App extends Component {
static getDerivedStateFromError(error) {
return { fatalError: error };
}

state = {
fatalError: null,
slowQuery: false,
};

async componentDidMount() {
window['__cubejsPlayground'] = {
...window['__cubejsPlayground'],
onQueryLoad: (resultSet) => {
if (resultSet) {
const { loadResponse } = resultSet.serialize();

this.setState({ slowQuery: Boolean(loadResponse.slowQuery) });
}
},
};

window.addEventListener('unhandledrejection', (promiseRejectionEvent) => {
const error = promiseRejectionEvent.reason;
console.log(error);
Expand Down Expand Up @@ -70,24 +90,30 @@ class App extends Component {
}

render() {
const { fatalError } = this.state || {};
const { fatalError, slowQuery } = this.state || {};
const { location, children } = this.props;
return (
<Layout style={{ height: '100%' }}>
<GlobalStyles/>
<Header selectedKeys={selectedTab(location.pathname)} />
<Layout.Content style={{ height: '100%' }}>
{fatalError ? (
<Alert
message="Error occured while rendering"
description={fatalError.stack}
type="error"
/>
) : (
children
)}
</Layout.Content>
</Layout>
<AppContext.Provider
value={{
slowQuery,
}}
>
<Layout style={{ height: '100%' }}>
<GlobalStyles />
<Header selectedKeys={selectedTab(location.pathname)} />
<Layout.Content style={{ height: '100%' }}>
{fatalError ? (
<Alert
message="Error occured while rendering"
description={fatalError.stack}
type="error"
/>
) : (
children
)}
</Layout.Content>
</Layout>
</AppContext.Provider>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { useEffect } from 'react';
import { Spin } from 'antd';
import { Alert, Spin } from 'antd';

import { dispatchChartEvent } from '../../utils';
import useDeepCompareMemoize from '../../hooks/deep-compare-memoize';
import useSlowQuery from '../../hooks/slow-query';

export default function ChartRenderer({
iframeRef,
Expand All @@ -14,6 +15,8 @@ export default function ChartRenderer({
pivotConfig,
onChartRendererReadyChange,
}) {
const slowQuery = useSlowQuery();

useEffect(() => {
return () => {
onChartRendererReadyChange(false);
Expand All @@ -34,7 +37,15 @@ export default function ChartRenderer({
}, useDeepCompareMemoize([iframeRef, isChartRendererReady, pivotConfig, query, chartType]));

return (
<div>
<>
{slowQuery ? (
<Alert
style={{ marginBottom: 24 }}
message="Query is too slow to be renewed during the user request and was served from the cache. Please consider using low latency pre-aggregations."
type="warning"
/>
) : null}

{!isChartRendererReady ? <Spin /> : null}

<iframe
Expand All @@ -48,6 +59,6 @@ export default function ChartRenderer({
title="Chart renderer"
src={`/chart-renderers/${framework}/index.html`}
/>
</div>
</>
);
}
8 changes: 8 additions & 0 deletions packages/cubejs-playground/src/hooks/slow-query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useContext } from 'react';
import { AppContext } from '../App';

export default function useSlowQuery() {
const { slowQuery } = useContext(AppContext);

return slowQuery;
}
6 changes: 5 additions & 1 deletion packages/cubejs-server-core/src/core/OrchestratorApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ export class OrchestratorApi {
requestId: query.requestId,
warning: 'Query is too slow to be renewed during the user request and was served from the cache. Please consider using low latency pre-aggregations.'
});
return fromCache;

return {
...fromCache,
slowQuery: true
};
}

throw { error: 'Continue wait', stage: await this.orchestrator.queryStage(query) };
Expand Down

0 comments on commit ce33f88

Please sign in to comment.