mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-10 03:09:02 +08:00
Fix(FE): Eslint Prettier are configured (#269)
* fix(FE): eslint * chore: run eslint on frontend folder * chore: run eslint on src * chore: eslint fixing is updated * chore: linting errors are updated Co-authored-by: Nidhi Tandon <nidhitandon08@gmail.com>
This commit is contained in:
parent
e1fbe265d8
commit
4143e313da
2
frontend/.eslintignore
Normal file
2
frontend/.eslintignore
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
build
|
41
frontend/.eslintrc.js
Normal file
41
frontend/.eslintrc.js
Normal file
@ -0,0 +1,41 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 12,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['react', '@typescript-eslint', 'simple-import-sort'],
|
||||
rules: {
|
||||
'react/jsx-filename-extension': [
|
||||
'error',
|
||||
{
|
||||
extensions: ['.tsx', '.js', '.jsx'],
|
||||
},
|
||||
],
|
||||
'react/prop-types': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'error',
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
indent: ['error', 'tab'],
|
||||
quotes: ['error', 'single'],
|
||||
semi: ['error', 'always'],
|
||||
|
||||
// simple sort error
|
||||
'simple-import-sort/imports': 'error',
|
||||
'simple-import-sort/exports': 'error',
|
||||
},
|
||||
};
|
@ -2,6 +2,6 @@
|
||||
"trailingComma": "all",
|
||||
"useTabs": true,
|
||||
"tabWidth": 1,
|
||||
"singleQuote": false,
|
||||
"singleQuote": true,
|
||||
"jsxSingleQuote": false
|
||||
}
|
||||
|
@ -11,32 +11,32 @@
|
||||
// please read our getting started guide:
|
||||
// https://on.cypress.io/introduction-to-cypress
|
||||
|
||||
describe("example to-do app", () => {
|
||||
describe('example to-do app', () => {
|
||||
beforeEach(() => {
|
||||
// Cypress starts out with a blank slate for each test
|
||||
// so we must tell it to visit our website with the `cy.visit()` command.
|
||||
// Since we want to visit the same URL at the start of all our tests,
|
||||
// we include it in our beforeEach function so that it runs before each test
|
||||
cy.visit("https://example.cypress.io/todo");
|
||||
cy.visit('https://example.cypress.io/todo');
|
||||
});
|
||||
|
||||
it("displays two todo items by default", () => {
|
||||
it('displays two todo items by default', () => {
|
||||
// We use the `cy.get()` command to get all elements that match the selector.
|
||||
// Then, we use `should` to assert that there are two matched items,
|
||||
// which are the two default items.
|
||||
cy.get(".todo-list li").should("have.length", 2);
|
||||
cy.get('.todo-list li').should('have.length', 2);
|
||||
|
||||
// We can go even further and check that the default todos each contain
|
||||
// the correct text. We use the `first` and `last` functions
|
||||
// to get just the first and last matched elements individually,
|
||||
// and then perform an assertion with `should`.
|
||||
cy.get(".todo-list li").first().should("have.text", "Pay electric bill");
|
||||
cy.get(".todo-list li").last().should("have.text", "Walk the dog");
|
||||
cy.get('.todo-list li').first().should('have.text', 'Pay electric bill');
|
||||
cy.get('.todo-list li').last().should('have.text', 'Walk the dog');
|
||||
});
|
||||
|
||||
it("can add new todo items", () => {
|
||||
it('can add new todo items', () => {
|
||||
// We'll store our item text in a variable so we can reuse it
|
||||
const newItem = "Feed the cat";
|
||||
const newItem = 'Feed the cat';
|
||||
|
||||
// Let's get the input element and use the `type` command to
|
||||
// input our new list item. After typing the content of our item,
|
||||
@ -44,7 +44,7 @@ describe("example to-do app", () => {
|
||||
// This input has a data-test attribute so we'll use that to select the
|
||||
// element in accordance with best practices:
|
||||
// https://on.cypress.io/selecting-elements
|
||||
cy.get("[data-test=new-todo]").type(`${newItem}{enter}`);
|
||||
cy.get('[data-test=new-todo]').type(`${newItem}{enter}`);
|
||||
|
||||
// Now that we've typed our new item, let's check that it actually was added to the list.
|
||||
// Since it's the newest item, it should exist as the last element in the list.
|
||||
@ -52,13 +52,13 @@ describe("example to-do app", () => {
|
||||
// Since assertions yield the element that was asserted on,
|
||||
// we can chain both of these assertions together into a single statement.
|
||||
cy
|
||||
.get(".todo-list li")
|
||||
.should("have.length", 3)
|
||||
.get('.todo-list li')
|
||||
.should('have.length', 3)
|
||||
.last()
|
||||
.should("have.text", newItem);
|
||||
.should('have.text', newItem);
|
||||
});
|
||||
|
||||
it("can check off an item as completed", () => {
|
||||
it('can check off an item as completed', () => {
|
||||
// In addition to using the `get` command to get an element by selector,
|
||||
// we can also use the `contains` command to get an element by its contents.
|
||||
// However, this will yield the <label>, which is lowest-level element that contains the text.
|
||||
@ -66,9 +66,9 @@ describe("example to-do app", () => {
|
||||
// by traversing up the dom to the parent element. From there, we can `find`
|
||||
// the child checkbox <input> element and use the `check` command to check it.
|
||||
cy
|
||||
.contains("Pay electric bill")
|
||||
.contains('Pay electric bill')
|
||||
.parent()
|
||||
.find("input[type=checkbox]")
|
||||
.find('input[type=checkbox]')
|
||||
.check();
|
||||
|
||||
// Now that we've checked the button, we can go ahead and make sure
|
||||
@ -77,74 +77,74 @@ describe("example to-do app", () => {
|
||||
// to traverse multiple levels up the dom until we find the corresponding <li> element.
|
||||
// Once we get that element, we can assert that it has the completed class.
|
||||
cy
|
||||
.contains("Pay electric bill")
|
||||
.parents("li")
|
||||
.should("have.class", "completed");
|
||||
.contains('Pay electric bill')
|
||||
.parents('li')
|
||||
.should('have.class', 'completed');
|
||||
});
|
||||
|
||||
context("with a checked task", () => {
|
||||
context('with a checked task', () => {
|
||||
beforeEach(() => {
|
||||
// We'll take the command we used above to check off an element
|
||||
// Since we want to perform multiple tests that start with checking
|
||||
// one element, we put it in the beforeEach hook
|
||||
// so that it runs at the start of every test.
|
||||
cy
|
||||
.contains("Pay electric bill")
|
||||
.contains('Pay electric bill')
|
||||
.parent()
|
||||
.find("input[type=checkbox]")
|
||||
.find('input[type=checkbox]')
|
||||
.check();
|
||||
});
|
||||
|
||||
it("can filter for uncompleted tasks", () => {
|
||||
it('can filter for uncompleted tasks', () => {
|
||||
// We'll click on the "active" button in order to
|
||||
// display only incomplete items
|
||||
cy.contains("Active").click();
|
||||
cy.contains('Active').click();
|
||||
|
||||
// After filtering, we can assert that there is only the one
|
||||
// incomplete item in the list.
|
||||
cy
|
||||
.get(".todo-list li")
|
||||
.should("have.length", 1)
|
||||
.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.first()
|
||||
.should("have.text", "Walk the dog");
|
||||
.should('have.text', 'Walk the dog');
|
||||
|
||||
// For good measure, let's also assert that the task we checked off
|
||||
// does not exist on the page.
|
||||
cy.contains("Pay electric bill").should("not.exist");
|
||||
cy.contains('Pay electric bill').should('not.exist');
|
||||
});
|
||||
|
||||
it("can filter for completed tasks", () => {
|
||||
it('can filter for completed tasks', () => {
|
||||
// We can perform similar steps as the test above to ensure
|
||||
// that only completed tasks are shown
|
||||
cy.contains("Completed").click();
|
||||
cy.contains('Completed').click();
|
||||
|
||||
cy
|
||||
.get(".todo-list li")
|
||||
.should("have.length", 1)
|
||||
.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.first()
|
||||
.should("have.text", "Pay electric bill");
|
||||
.should('have.text', 'Pay electric bill');
|
||||
|
||||
cy.contains("Walk the dog").should("not.exist");
|
||||
cy.contains('Walk the dog').should('not.exist');
|
||||
});
|
||||
|
||||
it("can delete all completed tasks", () => {
|
||||
it('can delete all completed tasks', () => {
|
||||
// First, let's click the "Clear completed" button
|
||||
// `contains` is actually serving two purposes here.
|
||||
// First, it's ensuring that the button exists within the dom.
|
||||
// This button only appears when at least one task is checked
|
||||
// so this command is implicitly verifying that it does exist.
|
||||
// Second, it selects the button so we can click it.
|
||||
cy.contains("Clear completed").click();
|
||||
cy.contains('Clear completed').click();
|
||||
|
||||
// Then we can make sure that there is only one element
|
||||
// in the list and our element does not exist
|
||||
cy
|
||||
.get(".todo-list li")
|
||||
.should("have.length", 1)
|
||||
.should("not.have.text", "Pay electric bill");
|
||||
.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.should('not.have.text', 'Pay electric bill');
|
||||
|
||||
// Finally, make sure that the clear button no longer exists.
|
||||
cy.contains("Clear completed").should("not.exist");
|
||||
cy.contains('Clear completed').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -23,4 +23,4 @@
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
import "@testing-library/cypress/add-commands";
|
||||
import '@testing-library/cypress/add-commands';
|
||||
|
@ -14,7 +14,7 @@
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import "./commands";
|
||||
import './commands';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
@ -1,24 +0,0 @@
|
||||
module.exports = {
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint/eslint-plugin"],
|
||||
rules: {
|
||||
"react/jsx-filename-extension": [
|
||||
"error",
|
||||
{
|
||||
extensions: [".tsx"],
|
||||
},
|
||||
],
|
||||
"react/prop-types": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "error",
|
||||
},
|
||||
extends: [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"prettier/@typescript-eslint",
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
jest: true,
|
||||
},
|
||||
};
|
@ -1,21 +1,21 @@
|
||||
const gulp = require("gulp");
|
||||
const gulpless = require("gulp-less");
|
||||
const postcss = require("gulp-postcss");
|
||||
const debug = require("gulp-debug");
|
||||
var csso = require("gulp-csso");
|
||||
const autteoprefixer = require("autoprefixer");
|
||||
const NpmImportPlugin = require("less-plugin-npm-import");
|
||||
const gulp = require('gulp');
|
||||
const gulpless = require('gulp-less');
|
||||
const postcss = require('gulp-postcss');
|
||||
const debug = require('gulp-debug');
|
||||
var csso = require('gulp-csso');
|
||||
const autteoprefixer = require('autoprefixer');
|
||||
const NpmImportPlugin = require('less-plugin-npm-import');
|
||||
|
||||
gulp.task("less", function () {
|
||||
const plugins = [autoprefixer()];
|
||||
gulp.task('less', function () {
|
||||
const plugins = [autteoprefixer()];
|
||||
|
||||
return gulp
|
||||
.src("src/themes/*-theme.less")
|
||||
.pipe(debug({ title: "Less files:" }))
|
||||
.src('src/themes/*-theme.less')
|
||||
.pipe(debug({ title: 'Less files:' }))
|
||||
.pipe(
|
||||
gulpless({
|
||||
javascriptEnabled: true,
|
||||
plugins: [new NpmImportPlugin({ prefix: "~" })],
|
||||
plugins: [new NpmImportPlugin({ prefix: '~' })],
|
||||
}),
|
||||
)
|
||||
.pipe(postcss(plugins))
|
||||
@ -24,5 +24,5 @@ gulp.task("less", function () {
|
||||
debug: true,
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest("./public"));
|
||||
.pipe(gulp.dest('./public'));
|
||||
});
|
||||
|
21590
frontend/package-lock.json
generated
21590
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,8 @@
|
||||
"dev": "NODE_ENV=development webpack serve --progress",
|
||||
"build": "webpack --config=webpack.config.prod.js --progress",
|
||||
"prettify": "prettier --write .",
|
||||
"lint": "eslint src",
|
||||
"lint": "eslint . --debug",
|
||||
"lint:fix": "eslint . --fix --debug",
|
||||
"cypress:open": "cypress open",
|
||||
"cypress:run": "cypress run"
|
||||
},
|
||||
@ -36,8 +37,6 @@
|
||||
"@types/redux": "^3.6.0",
|
||||
"@types/styled-components": "^5.1.4",
|
||||
"@types/vis": "^4.21.21",
|
||||
"@typescript-eslint/eslint-plugin": "^4.5.0",
|
||||
"@typescript-eslint/parser": "^4.5.0",
|
||||
"antd": "^4.8.0",
|
||||
"axios": "^0.21.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
@ -55,13 +54,11 @@
|
||||
"d3-flame-graph": "^3.1.1",
|
||||
"d3-tip": "^0.9.1",
|
||||
"dotenv": "8.2.0",
|
||||
"eslint": "^7.29.0",
|
||||
"dotenv-expand": "5.1.0",
|
||||
"eslint-config-react-app": "^6.0.0",
|
||||
"eslint-plugin-flowtype": "^5.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jest": "^24.1.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-testing-library": "^3.9.2",
|
||||
"eslint-webpack-plugin": "^2.1.0",
|
||||
@ -133,11 +130,20 @@
|
||||
"@babel/preset-typescript": "^7.12.17",
|
||||
"@testing-library/cypress": "^8.0.0",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
||||
"@typescript-eslint/parser": "^4.28.2",
|
||||
"autoprefixer": "^9.0.0",
|
||||
"babel-plugin-styled-components": "^1.12.0",
|
||||
"compression-webpack-plugin": "^8.0.0",
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
"cypress": "^8.3.0",
|
||||
"eslint": "^7.30.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-plugin-import": "^2.23.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-csso": "^4.0.1",
|
||||
"gulp-debug": "^4.0.0",
|
||||
|
@ -1,14 +1,13 @@
|
||||
import React, { Suspense } from "react";
|
||||
import ROUTES from "constants/routes";
|
||||
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
|
||||
import Spinner from "components/Spinner";
|
||||
import NotFound from "components/NotFound";
|
||||
import NotFound from 'components/NotFound';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { IS_LOGGED_IN } from 'constants/auth';
|
||||
import ROUTES from 'constants/routes';
|
||||
import AppLayout from 'modules/AppLayout';
|
||||
import { RouteProvider } from 'modules/RouteProvider';
|
||||
import React, { Suspense } from 'react';
|
||||
import { BrowserRouter, Redirect,Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { IS_LOGGED_IN } from "constants/auth";
|
||||
|
||||
import AppLayout from "modules/AppLayout";
|
||||
import { RouteProvider } from "modules/RouteProvider";
|
||||
import routes from "./routes";
|
||||
import routes from './routes';
|
||||
|
||||
const App = () => (
|
||||
<BrowserRouter basename="/">
|
||||
@ -25,7 +24,7 @@ const App = () => (
|
||||
path="/"
|
||||
exact
|
||||
render={() => {
|
||||
return localStorage.getItem(IS_LOGGED_IN) === "yes" ? (
|
||||
return localStorage.getItem(IS_LOGGED_IN) === 'yes' ? (
|
||||
<Redirect to={ROUTES.APPLICATION} />
|
||||
) : (
|
||||
<Redirect to={ROUTES.SIGN_UP} />
|
||||
|
@ -1,16 +1,16 @@
|
||||
import ROUTES from 'constants/routes';
|
||||
import {
|
||||
ServiceMetricsPage,
|
||||
InstrumentationPage,
|
||||
ServiceMapPage,
|
||||
ServiceMetricsPage,
|
||||
ServicesTablePage,
|
||||
SettingsPage,
|
||||
SignupPage,
|
||||
TraceDetailPage,
|
||||
TraceGraphPage,
|
||||
UsageExplorerPage,
|
||||
ServicesTablePage,
|
||||
SignupPage,
|
||||
SettingsPage,
|
||||
InstrumentationPage,
|
||||
} from "pages";
|
||||
import ROUTES from "constants/routes";
|
||||
import { RouteProps } from "react-router-dom";
|
||||
} from 'pages';
|
||||
import { RouteProps } from 'react-router-dom';
|
||||
|
||||
const routes: AppRoutes[] = [
|
||||
{
|
||||
@ -61,9 +61,9 @@ const routes: AppRoutes[] = [
|
||||
];
|
||||
|
||||
interface AppRoutes {
|
||||
component: RouteProps["component"];
|
||||
path: RouteProps["path"];
|
||||
exact: RouteProps["exact"];
|
||||
component: RouteProps['component'];
|
||||
path: RouteProps['path'];
|
||||
exact: RouteProps['exact'];
|
||||
isPrivate?: boolean;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
const apiV1 = "/api/v1/";
|
||||
const apiV1 = '/api/v1/';
|
||||
|
||||
export default apiV1;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import axios, { AxiosRequestConfig } from "axios";
|
||||
import { ENVIRONMENT } from "constants/env";
|
||||
import apiV1 from "./apiV1";
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import { ENVIRONMENT } from 'constants/env';
|
||||
|
||||
import apiV1 from './apiV1';
|
||||
|
||||
export default axios.create({
|
||||
baseURL: `${ENVIRONMENT.baseURL}`,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
const NotFound = (): JSX.Element => {
|
||||
return (
|
||||
@ -9,7 +9,7 @@ const NotFound = (): JSX.Element => {
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clip-path="url(#clip0)">
|
||||
<g clipPath="url(#clip0)">
|
||||
<path
|
||||
d="M181.155 195.76C278.772 195.76 357.906 190.521 357.906 184.059C357.906 177.596 278.772 172.358 181.155 172.358C83.5382 172.358 4.40404 177.596 4.40404 184.059C4.40404 190.521 83.5382 195.76 181.155 195.76Z"
|
||||
fill="#F2F2F2"
|
||||
@ -29,17 +29,17 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M110.947 141.154H99.0408V106.092C99.0408 105.17 98.8592 104.257 98.5063 103.405C98.1535 102.553 97.6362 101.779 96.9842 101.127C96.3322 100.475 95.5581 99.9579 94.7062 99.605C93.8543 99.2522 92.9412 99.0705 92.0191 99.0705H89.2291C87.3668 99.0705 85.5808 99.8103 84.264 101.127C82.9472 102.444 82.2074 104.23 82.2074 106.092V141.154H48.623C47.9321 141.154 47.2529 140.976 46.6513 140.636C46.0498 140.296 45.5463 139.806 45.1896 139.215C44.833 138.623 44.6354 137.949 44.616 137.258C44.5965 136.568 44.7559 135.884 45.0787 135.273L80.6241 67.9968C81.0672 67.1581 81.3358 66.2382 81.4137 65.2927C81.4915 64.3473 81.377 63.3959 81.077 62.4959C80.777 61.596 80.2977 60.7662 79.6681 60.0566C79.0386 59.3469 78.2717 58.7722 77.4139 58.3672L75.3156 57.3763C73.6863 56.6069 71.8235 56.4933 70.1128 57.059C68.402 57.6247 66.9742 58.8263 66.1248 60.4154L22.7725 141.514C22.0343 142.895 21.648 144.437 21.648 146.003V146.003C21.648 148.528 22.6512 150.95 24.4368 152.735C26.2224 154.521 28.6442 155.524 31.1694 155.524H82.2074V177.695C82.2074 178.8 82.4251 179.895 82.8481 180.916C83.271 181.937 83.891 182.865 84.6726 183.647C85.4541 184.428 86.382 185.048 87.4032 185.471C88.4243 185.894 89.5188 186.112 90.6241 186.112H90.6241C92.8564 186.112 94.9972 185.225 96.5756 183.647C98.1541 182.068 99.0408 179.927 99.0408 177.695V155.524H110.947C111.891 155.524 112.825 155.338 113.697 154.977C114.569 154.616 115.361 154.087 116.028 153.42C116.695 152.753 117.224 151.96 117.585 151.089C117.947 150.217 118.132 149.283 118.132 148.339V148.339C118.132 147.396 117.947 146.461 117.585 145.59C117.224 144.718 116.695 143.926 116.028 143.259C115.361 142.591 114.569 142.062 113.697 141.701C112.825 141.34 111.891 141.154 110.947 141.154V141.154Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M334.298 141.154H322.392V106.092C322.392 104.23 321.652 102.444 320.335 101.127C319.018 99.8103 317.232 99.0705 315.37 99.0705H312.58C311.658 99.0705 310.745 99.2522 309.893 99.605C309.041 99.9579 308.267 100.475 307.615 101.127C306.963 101.779 306.446 102.553 306.093 103.405C305.74 104.257 305.558 105.17 305.558 106.092V141.154H271.974C271.283 141.154 270.604 140.976 270.002 140.636C269.401 140.296 268.897 139.806 268.541 139.215C268.184 138.623 267.986 137.949 267.967 137.258C267.948 136.568 268.107 135.884 268.43 135.273L303.975 67.9968C304.418 67.1581 304.687 66.2382 304.765 65.2927C304.843 64.3473 304.728 63.3959 304.428 62.4959C304.128 61.596 303.649 60.7662 303.019 60.0566C302.39 59.3469 301.623 58.7722 300.765 58.3672L298.667 57.3763C297.037 56.6069 295.175 56.4933 293.464 57.059C291.753 57.6247 290.325 58.8263 289.476 60.4154L246.124 141.514C245.385 142.895 244.999 144.437 244.999 146.003C244.999 148.528 246.002 150.95 247.788 152.735C249.573 154.521 251.995 155.524 254.52 155.524H305.558V177.695C305.558 179.927 306.445 182.068 308.024 183.647C309.602 185.225 311.743 186.112 313.975 186.112V186.112C316.207 186.112 318.348 185.225 319.927 183.647C321.505 182.068 322.392 179.927 322.392 177.695V155.524H334.298C335.242 155.524 336.176 155.338 337.048 154.977C337.92 154.616 338.712 154.087 339.379 153.42C340.046 152.753 340.575 151.96 340.936 151.089C341.298 150.217 341.483 149.283 341.483 148.339V148.339C341.483 146.434 340.726 144.606 339.379 143.259C338.032 141.911 336.204 141.154 334.298 141.154V141.154Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M180.95 52.2653C152.152 52.2653 131.476 70.741 131.476 113.851C131.476 162.709 152.152 175.642 180.95 175.642C209.747 175.642 231.656 161.477 231.656 113.851C231.656 62.9402 209.747 52.2653 180.95 52.2653ZM181.139 159.425C161.193 159.425 150.773 147.723 150.773 113.883C150.773 84.0236 161.62 68.2776 181.566 68.2776C201.512 68.2776 212.359 78.6206 212.359 113.883C212.359 146.87 201.085 159.425 181.139 159.425V159.425Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M157.867 10.4381C160.254 10.4381 162.19 8.5027 162.19 6.11526C162.19 3.72782 160.254 1.79242 157.867 1.79242C155.479 1.79242 153.544 3.72782 153.544 6.11526C153.544 8.5027 155.479 10.4381 157.867 10.4381Z"
|
||||
@ -129,12 +129,12 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M345.776 182.211C345.176 179.158 347.774 176.452 350.34 174.693C352.906 172.934 355.904 171.205 356.779 168.22C358.037 163.93 354.29 160.001 351.373 156.613C349.208 154.098 347.35 151.336 345.836 148.384C345.229 147.2 344.671 145.963 344.512 144.643C344.282 142.741 344.893 140.848 345.508 139.034C347.559 132.992 349.751 126.999 352.085 121.058"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M337.66 139.656C338.675 140.025 339.762 140.153 340.835 140.03C341.908 139.908 342.938 139.537 343.844 138.949C344.749 138.36 345.506 137.569 346.053 136.638C346.601 135.708 346.925 134.662 347 133.585C347.075 132.507 346.898 131.427 346.484 130.43C346.071 129.432 345.431 128.544 344.615 127.836C343.8 127.128 342.831 126.619 341.785 126.349C340.739 126.079 339.645 126.056 338.589 126.281L338.764 129.871L337.065 126.794C335.399 127.578 334.111 128.99 333.486 130.722C333.263 131.329 333.128 131.964 333.084 132.609C332.977 134.121 333.366 135.627 334.192 136.899C335.017 138.171 336.235 139.138 337.66 139.656V139.656Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M344.924 119.818C345.322 118.719 345.99 117.738 346.868 116.965C347.745 116.192 348.802 115.653 349.943 115.396L350.517 118.808L351.582 115.225C353.06 115.246 354.493 115.738 355.673 116.627C356.854 117.516 357.722 118.758 358.151 120.172C358.58 121.587 358.548 123.101 358.061 124.497C357.573 125.892 356.655 127.097 355.438 127.936C354.221 128.776 352.769 129.207 351.292 129.167C349.814 129.127 348.387 128.619 347.217 127.716C346.047 126.813 345.194 125.561 344.782 124.141C344.37 122.722 344.419 121.208 344.924 119.818H344.924Z"
|
||||
@ -143,7 +143,7 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M345.306 118.586C345.705 117.487 346.373 116.506 347.251 115.733C348.128 114.96 349.185 114.421 350.326 114.164L350.9 117.576L351.965 113.992C353.443 114.014 354.875 114.505 356.056 115.395C357.237 116.284 358.105 117.526 358.534 118.94C358.963 120.355 358.931 121.869 358.444 123.265C357.956 124.66 357.038 125.864 355.821 126.704C354.604 127.543 353.152 127.974 351.675 127.935C350.197 127.895 348.77 127.387 347.6 126.484C346.43 125.58 345.577 124.329 345.165 122.909C344.753 121.489 344.802 119.976 345.306 118.586H345.306Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M350.148 156.682C351.758 157.266 353.527 157.237 355.116 156.601C356.706 155.965 358.006 154.766 358.769 153.233C359.532 151.7 359.704 149.939 359.252 148.288C358.801 146.636 357.757 145.208 356.32 144.276L355.502 147.03L354.922 143.578C354.916 143.575 354.911 143.573 354.904 143.571C354.043 143.258 353.129 143.118 352.214 143.159C351.299 143.199 350.401 143.42 349.571 143.807C348.741 144.195 347.995 144.743 347.377 145.419C346.759 146.095 346.28 146.886 345.967 147.747C345.655 148.608 345.515 149.523 345.556 150.438C345.597 151.353 345.818 152.251 346.207 153.081C346.595 153.91 347.143 154.656 347.819 155.273C348.496 155.891 349.287 156.37 350.148 156.682H350.148Z"
|
||||
@ -152,7 +152,7 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M350.48 155.434C352.09 156.018 353.858 155.989 355.448 155.353C357.038 154.717 358.338 153.518 359.101 151.985C359.864 150.452 360.036 148.691 359.584 147.04C359.132 145.388 358.089 143.96 356.652 143.028L355.834 145.782L355.254 142.33C355.248 142.327 355.242 142.325 355.236 142.323C354.375 142.01 353.461 141.87 352.546 141.911C351.631 141.951 350.732 142.172 349.902 142.559C349.072 142.947 348.327 143.495 347.709 144.171C347.091 144.847 346.611 145.638 346.299 146.499C345.987 147.36 345.847 148.274 345.888 149.19C345.929 150.105 346.15 151.003 346.538 151.833C346.927 152.662 347.475 153.407 348.151 154.025C348.827 154.643 349.619 155.122 350.48 155.434H350.48Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M342.888 168.263C343.165 169.838 343.975 171.269 345.182 172.318C346.389 173.367 347.92 173.968 349.519 174.022C351.117 174.076 352.685 173.579 353.96 172.614C355.235 171.649 356.139 170.275 356.521 168.722C356.903 167.169 356.74 165.532 356.058 164.086C355.377 162.639 354.219 161.471 352.778 160.777C351.338 160.083 349.702 159.905 348.146 160.274C346.59 160.643 345.208 161.535 344.232 162.802L347.339 167.478L343.094 164.996C342.765 166.053 342.694 167.173 342.888 168.263V168.263Z"
|
||||
@ -161,7 +161,7 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M343.176 167.339C343.452 168.913 344.262 170.345 345.469 171.394C346.677 172.443 348.208 173.044 349.806 173.098C351.404 173.152 352.972 172.655 354.247 171.69C355.522 170.725 356.426 169.35 356.808 167.798C357.191 166.245 357.027 164.608 356.346 163.162C355.664 161.715 354.506 160.547 353.065 159.853C351.625 159.159 349.989 158.981 348.433 159.35C346.877 159.719 345.495 160.611 344.519 161.878L347.627 166.554L343.381 164.072C343.052 165.129 342.981 166.249 343.176 167.339V167.339Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M3.01816 157.568C3.68505 157.81 4.39914 157.894 5.10415 157.814C5.80915 157.733 6.48579 157.49 7.08075 157.103C7.6757 156.716 8.17269 156.197 8.53256 155.585C8.89243 154.974 9.10533 154.287 9.15448 153.579C9.20364 152.871 9.0877 152.161 8.81581 151.506C8.54393 150.851 8.12352 150.267 7.58772 149.802C7.05193 149.337 6.4154 149.002 5.7283 148.825C5.04121 148.648 4.32233 148.633 3.62832 148.78L3.74301 151.139L2.62726 149.118C1.53221 149.632 0.686246 150.56 0.275259 151.698C0.129301 152.097 0.0405688 152.514 0.0117106 152.938C-0.0587161 153.931 0.19668 154.921 0.739195 155.757C1.28171 156.592 2.08178 157.228 3.01816 157.568V157.568Z"
|
||||
@ -170,12 +170,12 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M8.53892 184.92C8.14506 182.914 9.85174 181.136 11.5375 179.98C13.2233 178.825 15.1931 177.689 15.7683 175.728C16.595 172.909 14.1326 170.328 12.2161 168.102C10.7942 166.45 9.57311 164.635 8.57841 162.695C8.14597 161.933 7.85142 161.101 7.70834 160.237C7.55722 158.988 7.95864 157.744 8.36304 156.552C9.71024 152.582 11.1506 148.645 12.6842 144.741"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M3.20684 156.961C3.87373 157.203 4.58782 157.287 5.29282 157.207C5.99782 157.126 6.67447 156.883 7.26942 156.496C7.86437 156.109 8.36136 155.59 8.72123 154.978C9.08109 154.367 9.29399 153.68 9.34315 152.972C9.3923 152.264 9.27637 151.554 9.00448 150.899C8.73259 150.243 8.31218 149.66 7.77639 149.195C7.2406 148.73 6.60407 148.395 5.91698 148.218C5.22988 148.041 4.51101 148.025 3.817 148.173L3.93169 150.532L2.81594 148.511C1.72089 149.025 0.874921 149.953 0.463934 151.091C0.317977 151.49 0.229247 151.907 0.200387 152.331C0.129956 153.324 0.38535 154.314 0.927866 155.149C1.47038 155.985 2.27045 156.621 3.20684 156.961V156.961Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M7.97892 143.927C8.24064 143.205 8.67989 142.56 9.25622 142.052C9.83254 141.545 10.5274 141.19 11.2767 141.022L11.654 143.264L12.3534 140.909C13.3245 140.923 14.2659 141.246 15.0417 141.83C15.8175 142.415 16.3875 143.23 16.6695 144.16C16.9514 145.089 16.9307 146.084 16.6104 147.001C16.29 147.918 15.6866 148.709 14.8872 149.261C14.0878 149.812 13.1337 150.095 12.1629 150.069C11.192 150.043 10.2545 149.709 9.48578 149.116C8.71703 148.522 8.15678 147.7 7.88593 146.767C7.61509 145.835 7.64765 144.84 7.97892 143.927V143.927Z"
|
||||
@ -184,7 +184,7 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M8.23051 143.117C8.49223 142.395 8.93148 141.751 9.50781 141.243C10.0841 140.735 10.779 140.381 11.5283 140.212L11.9056 142.454L12.605 140.099C13.5761 140.114 14.5175 140.436 15.2933 141.021C16.0691 141.605 16.6391 142.421 16.921 143.35C17.203 144.279 17.1823 145.274 16.8619 146.191C16.5416 147.108 15.9381 147.899 15.1387 148.451C14.3393 149.003 13.3853 149.286 12.4145 149.26C11.4436 149.234 10.5061 148.9 9.73737 148.306C8.96861 147.713 8.40837 146.89 8.13752 145.958C7.86667 145.025 7.89923 144.03 8.23051 143.117V143.117Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M11.4118 168.147C12.4694 168.531 13.6312 168.512 14.6758 168.094C15.7203 167.676 16.5746 166.888 17.0757 165.881C17.5768 164.874 17.6898 163.717 17.3931 162.632C17.0963 161.547 16.4106 160.609 15.4667 159.996L14.9293 161.806L14.5482 159.538C14.5444 159.536 14.5405 159.534 14.5365 159.533C13.9708 159.327 13.3701 159.235 12.7687 159.262C12.1673 159.288 11.5771 159.433 11.0317 159.688C10.4863 159.943 9.99649 160.302 9.59021 160.747C9.18392 161.191 8.86914 161.711 8.66386 162.276C8.45859 162.842 8.36684 163.443 8.39385 164.044C8.42087 164.646 8.56612 165.236 8.82132 165.781C9.07651 166.326 9.43664 166.816 9.88112 167.222C10.3256 167.628 10.8457 167.942 11.4118 168.147V168.147Z"
|
||||
@ -193,7 +193,7 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M11.6298 167.327C12.6874 167.711 13.8492 167.692 14.8938 167.274C15.9383 166.856 16.7926 166.068 17.2937 165.061C17.7949 164.054 17.9078 162.897 17.6111 161.812C17.3143 160.727 16.6287 159.789 15.6847 159.176L15.1473 160.986L14.7662 158.718C14.7624 158.716 14.7585 158.714 14.7545 158.713C14.1889 158.508 13.5885 158.416 12.9874 158.443C12.3864 158.47 11.7965 158.615 11.2515 158.87C10.1508 159.385 9.29959 160.315 8.88523 161.458C8.47086 162.6 8.52722 163.86 9.04193 164.961C9.55663 166.061 10.4875 166.913 11.6298 167.327V167.327Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M6.64183 175.756C6.82368 176.791 7.35579 177.731 8.14892 178.42C8.94205 179.109 9.94797 179.505 10.998 179.54C12.048 179.575 13.0782 179.249 13.9159 178.615C14.7536 177.981 15.3478 177.078 15.5988 176.058C15.8499 175.037 15.7425 173.962 15.2947 173.012C14.847 172.061 14.086 171.294 13.1395 170.838C12.193 170.382 11.1185 170.265 10.0962 170.507C9.07393 170.75 8.16602 171.336 7.52475 172.168L9.56612 175.241L6.77684 173.61C6.56057 174.304 6.51427 175.04 6.64183 175.756V175.756Z"
|
||||
@ -202,7 +202,7 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M6.83052 175.149C7.01237 176.184 7.54448 177.124 8.33761 177.813C9.13074 178.502 10.1367 178.898 11.1867 178.933C12.2367 178.968 13.2669 178.642 14.1046 178.007C14.9423 177.373 15.5365 176.471 15.7875 175.45C16.0386 174.43 15.9312 173.355 15.4834 172.404C15.0357 171.454 14.2747 170.686 13.3282 170.23C12.3817 169.774 11.3072 169.658 10.2849 169.9C9.26262 170.142 8.35471 170.729 7.71343 171.561L9.75481 174.633L6.96553 173.003C6.74926 173.697 6.70296 174.433 6.83052 175.149V175.149Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M161.152 114.299C164.298 114.299 166.848 110.998 166.848 106.927C166.848 102.856 164.298 99.5555 161.152 99.5555C158.006 99.5555 155.456 102.856 155.456 106.927C155.456 110.998 158.006 114.299 161.152 114.299Z"
|
||||
@ -219,17 +219,17 @@ const NotFound = (): JSX.Element => {
|
||||
<path
|
||||
d="M162.492 112.623C165.638 112.623 168.189 109.323 168.189 105.252C168.189 101.18 165.638 97.8801 162.492 97.8801C159.346 97.8801 156.796 101.18 156.796 105.252C156.796 109.323 159.346 112.623 162.492 112.623Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M193.487 112.791C196.633 112.791 199.183 109.49 199.183 105.419C199.183 101.348 196.633 98.0476 193.487 98.0476C190.341 98.0476 187.79 101.348 187.79 105.419C187.79 109.49 190.341 112.791 193.487 112.791Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M178.743 133.23C184.48 133.23 189.131 130.53 189.131 127.199C189.131 123.868 184.48 121.168 178.743 121.168C173.007 121.168 168.356 123.868 168.356 127.199C168.356 130.53 173.007 133.23 178.743 133.23Z"
|
||||
stroke="#3F3D56"
|
||||
stroke-miterlimit="10"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M181.257 123.748C181.259 124.169 181.101 124.576 180.814 124.884C180.679 125.032 180.514 125.15 180.331 125.232C180.147 125.313 179.949 125.355 179.749 125.356H176.398C175.985 125.342 175.595 125.164 175.312 124.863C175.03 124.562 174.878 124.161 174.89 123.748C174.888 123.421 174.984 123.101 175.165 122.829C175.906 122.725 176.654 122.674 177.403 122.676C178.659 122.671 179.911 122.815 181.133 123.104C181.215 123.309 181.257 123.527 181.257 123.748V123.748Z"
|
||||
|
@ -4,9 +4,9 @@
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
#chart svg{
|
||||
#chart svg {
|
||||
width: 100%;
|
||||
}
|
||||
#chart{
|
||||
#chart {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { lazy, ComponentType } from "react";
|
||||
import { ComponentType,lazy } from 'react';
|
||||
|
||||
function Loadable(importPath: {
|
||||
(): LoadableProps;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { ReactElement } from "react";
|
||||
import { Modal } from "antd";
|
||||
import { Modal } from 'antd';
|
||||
import React, { ReactElement } from 'react';
|
||||
|
||||
export const CustomModal = ({
|
||||
title,
|
||||
|
@ -1,9 +1,8 @@
|
||||
import React from "react";
|
||||
import NotFoundImage from 'assets/NotFound';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React from 'react';
|
||||
|
||||
import { Button, Text, TextContainer, Container } from "./styles";
|
||||
|
||||
import NotFoundImage from "assets/NotFound";
|
||||
import ROUTES from "constants/routes";
|
||||
import { Button, Container,Text, TextContainer } from './styles';
|
||||
|
||||
const NotFound = (): JSX.Element => {
|
||||
return (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import styled from "styled-components";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Button = styled(Link)`
|
||||
height: 100%;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import { Spin, SpinProps } from "antd";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { Spin, SpinProps } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
import { SpinerStyle } from "./styles";
|
||||
import { SpinerStyle } from './styles';
|
||||
|
||||
const Spinner = ({ size, tip, height }: SpinnerProps): JSX.Element => (
|
||||
<SpinerStyle height={height}>
|
||||
@ -11,9 +11,9 @@ const Spinner = ({ size, tip, height }: SpinnerProps): JSX.Element => (
|
||||
);
|
||||
|
||||
interface SpinnerProps {
|
||||
size?: SpinProps["size"];
|
||||
tip?: SpinProps["tip"];
|
||||
height?: React.CSSProperties["height"];
|
||||
size?: SpinProps['size'];
|
||||
tip?: SpinProps['tip'];
|
||||
height?: React.CSSProperties['height'];
|
||||
}
|
||||
|
||||
export default Spinner;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface Props {
|
||||
height: React.CSSProperties["height"];
|
||||
height: React.CSSProperties['height'];
|
||||
}
|
||||
|
||||
export const SpinerStyle = styled.div<Props>`
|
||||
@ -12,5 +12,5 @@ export const SpinerStyle = styled.div<Props>`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: ${({ height = "100vh" }) => height};
|
||||
height: ${({ height = '100vh' }) => height};
|
||||
`;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import ROUTES from "./routes";
|
||||
import ROUTES from './routes';
|
||||
|
||||
export const WITHOUT_SESSION_PATH = ["/redirect"];
|
||||
export const WITHOUT_SESSION_PATH = ['/redirect'];
|
||||
|
||||
export const AUTH0_REDIRECT_PATH = "/redirect";
|
||||
export const AUTH0_REDIRECT_PATH = '/redirect';
|
||||
|
||||
export const DEFAULT_AUTH0_APP_REDIRECTION_PATH = ROUTES.APPLICATION;
|
||||
|
@ -1 +1 @@
|
||||
export const IS_LOGGED_IN = "isLoggedIn";
|
||||
export const IS_LOGGED_IN = 'isLoggedIn';
|
||||
|
@ -1,3 +1,3 @@
|
||||
export const ENVIRONMENT = {
|
||||
baseURL: process?.env?.FRONTEND_API_ENDPOINT || "",
|
||||
baseURL: process?.env?.FRONTEND_API_ENDPOINT || '',
|
||||
};
|
||||
|
@ -1,3 +1,3 @@
|
||||
export enum LOCAL_STORAGE {
|
||||
METRICS_TIME_IN_DURATION = "metricsTimeDurations",
|
||||
METRICS_TIME_IN_DURATION = 'metricsTimeDurations',
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export const SKIP_ONBOARDING = "skip_onboarding";
|
||||
export const SKIP_ONBOARDING = 'skip_onboarding';
|
||||
|
@ -1,9 +1,9 @@
|
||||
export enum METRICS_PAGE_QUERY_PARAM {
|
||||
interval = "interval",
|
||||
startTime = "startTime",
|
||||
endTime = "endTime",
|
||||
service = "service",
|
||||
error = "error",
|
||||
operation = "operation",
|
||||
kind = "kind"
|
||||
interval = 'interval',
|
||||
startTime = 'startTime',
|
||||
endTime = 'endTime',
|
||||
service = 'service',
|
||||
error = 'error',
|
||||
operation = 'operation',
|
||||
kind = 'kind'
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
const ROUTES = {
|
||||
SIGN_UP: "/signup",
|
||||
SERVICE_METRICS: "/application/:servicename",
|
||||
SERVICE_MAP: "/service-map",
|
||||
TRACES: "/traces",
|
||||
TRACE_GRAPH: "/traces/:id",
|
||||
SETTINGS: "/settings",
|
||||
INSTRUMENTATION: "/add-instrumentation",
|
||||
USAGE_EXPLORER: "/usage-explorer",
|
||||
APPLICATION: "/application",
|
||||
SIGN_UP: '/signup',
|
||||
SERVICE_METRICS: '/application/:servicename',
|
||||
SERVICE_MAP: '/service-map',
|
||||
TRACES: '/traces',
|
||||
TRACE_GRAPH: '/traces/:id',
|
||||
SETTINGS: '/settings',
|
||||
INSTRUMENTATION: '/add-instrumentation',
|
||||
USAGE_EXPLORER: '/usage-explorer',
|
||||
APPLICATION: '/application',
|
||||
};
|
||||
|
||||
export default ROUTES;
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Provider } from "react-redux";
|
||||
import { ThemeSwitcherProvider } from "react-css-theme-switcher";
|
||||
import store from "store";
|
||||
import AppRoutes from "AppRoutes";
|
||||
import "assets/index.css";
|
||||
import themes from "themes";
|
||||
import 'assets/index.css';
|
||||
|
||||
import AppRoutes from 'AppRoutes';
|
||||
import React from 'react';
|
||||
import { ThemeSwitcherProvider } from 'react-css-theme-switcher';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import store from 'store';
|
||||
import themes from 'themes';
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
@ -15,5 +16,5 @@ ReactDOM.render(
|
||||
</ThemeSwitcherProvider>
|
||||
</React.StrictMode>
|
||||
</Provider>,
|
||||
document.querySelector("#root"),
|
||||
document.querySelector('#root'),
|
||||
);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { ReactNode, useEffect } from "react";
|
||||
import { Layout } from 'antd';
|
||||
import React, { ReactNode, useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { Layout } from "antd";
|
||||
import SideNav from "./Nav/SideNav";
|
||||
import TopNav from "./Nav/TopNav";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useRoute } from "./RouteProvider";
|
||||
import SideNav from './Nav/SideNav';
|
||||
import TopNav from './Nav/TopNav';
|
||||
import { useRoute } from './RouteProvider';
|
||||
|
||||
const { Content, Footer } = Layout;
|
||||
|
||||
@ -17,18 +17,18 @@ const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => {
|
||||
const { dispatch } = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: "ROUTE_IS_LOADED", payload: location.pathname });
|
||||
dispatch({ type: 'ROUTE_IS_LOADED', payload: location.pathname });
|
||||
}, [location]);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: "100vh" }}>
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<SideNav />
|
||||
<Layout className="site-layout">
|
||||
<Content style={{ margin: "0 16px" }}>
|
||||
<Content style={{ margin: '0 16px' }}>
|
||||
<TopNav />
|
||||
{children}
|
||||
</Content>
|
||||
<Footer style={{ textAlign: "center", fontSize: 10 }}>
|
||||
<Footer style={{ textAlign: 'center', fontSize: 10 }}>
|
||||
SigNoz Inc. ©2020
|
||||
</Footer>
|
||||
</Layout>
|
||||
|
@ -1,32 +1,31 @@
|
||||
import React, { useState } from "react";
|
||||
import { Row, Space, Button, Input } from "antd";
|
||||
import api, { apiV1 } from "api";
|
||||
import ROUTES from "constants/routes";
|
||||
import { IS_LOGGED_IN } from "constants/auth";
|
||||
import { Button, Input,Row, Space } from 'antd';
|
||||
import api, { apiV1 } from 'api';
|
||||
import { IS_LOGGED_IN } from 'constants/auth';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React, { useState } from 'react';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
|
||||
interface SignUpProps extends RouteComponentProps<any> {}
|
||||
type SignUpProps = RouteComponentProps<any>;
|
||||
|
||||
const Signup = (props: SignUpProps) => {
|
||||
const [state, setState] = useState({ submitted: false });
|
||||
const [formState, setFormState] = useState({
|
||||
firstName: { value: "" },
|
||||
companyName: { value: "" },
|
||||
email: { value: "" },
|
||||
password: { value: "", valid: true },
|
||||
firstName: { value: '' },
|
||||
companyName: { value: '' },
|
||||
email: { value: '' },
|
||||
password: { value: '', valid: true },
|
||||
emailOptIn: { value: true },
|
||||
});
|
||||
|
||||
const updateForm = (name: any, target: any, valueAttr = "value") => {
|
||||
const updateForm = (name: any, target: any, valueAttr = 'value') => {
|
||||
/* Validate password (if applicable) */
|
||||
if (name === "firstName") {
|
||||
if (name === 'firstName') {
|
||||
setFormState({
|
||||
...formState,
|
||||
firstName: { ...formState.firstName, value: target[valueAttr] },
|
||||
});
|
||||
} else if (name === "email") {
|
||||
} else if (name === 'email') {
|
||||
setFormState({
|
||||
...formState,
|
||||
email: { ...formState.email, value: target[valueAttr] },
|
||||
@ -44,14 +43,14 @@ const Signup = (props: SignUpProps) => {
|
||||
email: formState.email,
|
||||
};
|
||||
|
||||
let texttolog = JSON.stringify(payload);
|
||||
const texttolog = JSON.stringify(payload);
|
||||
|
||||
api.post(apiV1 + "/user?email=" + texttolog).then((res) => {
|
||||
api.post(apiV1 + '/user?email=' + texttolog).then((res) => {
|
||||
console.log(res);
|
||||
console.log(res.data);
|
||||
});
|
||||
|
||||
localStorage.setItem(IS_LOGGED_IN, "yes");
|
||||
localStorage.setItem(IS_LOGGED_IN, 'yes');
|
||||
props.history.push(ROUTES.APPLICATION);
|
||||
};
|
||||
|
||||
@ -60,15 +59,15 @@ const Signup = (props: SignUpProps) => {
|
||||
<Space
|
||||
direction="vertical"
|
||||
className="space-top"
|
||||
style={{ width: "100%", paddingLeft: 32 }}
|
||||
style={{ width: '100%', paddingLeft: 32 }}
|
||||
>
|
||||
<h1
|
||||
className="title"
|
||||
style={{
|
||||
marginBottom: 0,
|
||||
marginTop: 40,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{/* <img src={"Signoz-white.svg"} alt="" style={{ height: 60 }} /> */}
|
||||
@ -78,25 +77,25 @@ const Signup = (props: SignUpProps) => {
|
||||
Monitor your applications. Find what is causing issues.
|
||||
</div>
|
||||
</Space>
|
||||
<Row style={{ display: "flex", justifyContent: "center" }}>
|
||||
<Row style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<div
|
||||
style={{ display: "flex", alignItems: "center", flexDirection: "column" }}
|
||||
style={{ display: 'flex', alignItems: 'center', flexDirection: 'column' }}
|
||||
>
|
||||
<img
|
||||
src={"signoz.svg"}
|
||||
style={{ maxHeight: "100%", maxWidth: 300, marginTop: 64 }}
|
||||
src={'signoz.svg'}
|
||||
style={{ maxHeight: '100%', maxWidth: 300, marginTop: 64 }}
|
||||
alt=""
|
||||
className="main-img"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
margin: "0 32px",
|
||||
flexDirection: "column",
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-start',
|
||||
margin: '0 32px',
|
||||
flexDirection: 'column',
|
||||
paddingTop: 32,
|
||||
maxWidth: "32rem",
|
||||
maxWidth: '32rem',
|
||||
}}
|
||||
>
|
||||
<form onSubmit={handleSubmit}>
|
||||
@ -106,7 +105,7 @@ const Signup = (props: SignUpProps) => {
|
||||
placeholder="mike@netflix.com"
|
||||
type="email"
|
||||
value={formState.email.value}
|
||||
onChange={(e) => updateForm("email", e.target)}
|
||||
onChange={(e) => updateForm('email', e.target)}
|
||||
required
|
||||
// disabled={accountLoading}
|
||||
id="signupEmail"
|
||||
@ -119,7 +118,7 @@ const Signup = (props: SignUpProps) => {
|
||||
placeholder="Mike"
|
||||
autoFocus
|
||||
value={formState.firstName.value}
|
||||
onChange={(e) => updateForm("firstName", e.target)}
|
||||
onChange={(e) => updateForm('firstName', e.target)}
|
||||
required
|
||||
// disabled={accountLoading}
|
||||
id="signupFirstName"
|
||||
|
@ -1,12 +1,11 @@
|
||||
import React from "react";
|
||||
import { Line as ChartJSLine } from "react-chartjs-2";
|
||||
import { ChartOptions } from "chart.js";
|
||||
import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import ROUTES from "constants/routes";
|
||||
|
||||
import { metricItem } from "store/actions/MetricsActions";
|
||||
import { ChartOptions } from 'chart.js';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React from 'react';
|
||||
import { Line as ChartJSLine } from 'react-chartjs-2';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { metricItem } from 'store/actions/MetricsActions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const ChartPopUpUnique = styled.div<{
|
||||
ycoordinate: number;
|
||||
@ -33,7 +32,7 @@ const PopUpElements = styled.p`
|
||||
`;
|
||||
|
||||
// PNOTE - Check if this should be the case
|
||||
const theme = "dark";
|
||||
const theme = 'dark';
|
||||
|
||||
interface ErrorRateChartProps extends RouteComponentProps<any> {
|
||||
data: metricItem[];
|
||||
@ -60,7 +59,7 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
};
|
||||
|
||||
onClickhandler = async (e: any, event: any) => {
|
||||
var firstPoint;
|
||||
let firstPoint;
|
||||
if (this.chartRef) {
|
||||
firstPoint = this.chartRef.current.chartInstance.getElementAtEvent(e)[0];
|
||||
}
|
||||
@ -94,22 +93,22 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
|
||||
title: {
|
||||
display: true,
|
||||
text: "",
|
||||
text: '',
|
||||
fontSize: 20,
|
||||
position: "top",
|
||||
position: 'top',
|
||||
padding: 2,
|
||||
fontFamily: "Arial",
|
||||
fontStyle: "regular",
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontFamily: 'Arial',
|
||||
fontStyle: 'regular',
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: "bottom",
|
||||
align: "center",
|
||||
position: 'bottom',
|
||||
align: 'center',
|
||||
|
||||
labels: {
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
fontSize: 10,
|
||||
boxWidth: 10,
|
||||
usePointStyle: true,
|
||||
@ -117,20 +116,20 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
mode: "label",
|
||||
mode: 'label',
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
if (typeof tooltipItem.yLabel === "number") {
|
||||
if (typeof tooltipItem.yLabel === 'number') {
|
||||
return (
|
||||
data.datasets![tooltipItem.datasetIndex!].label +
|
||||
" : " +
|
||||
' : ' +
|
||||
tooltipItem.yLabel.toFixed(2)
|
||||
);
|
||||
} else {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -156,18 +155,18 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
gridLines: {
|
||||
// You can change the color, the dash effect, the main axe color, etc.
|
||||
borderDash: [1, 4],
|
||||
color: "#D3D3D3",
|
||||
color: '#D3D3D3',
|
||||
lineWidth: 0.25,
|
||||
},
|
||||
},
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
type: 'time',
|
||||
// time: {
|
||||
// unit: 'second'
|
||||
// },
|
||||
distribution: "linear",
|
||||
distribution: 'linear',
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
fontSize: 10,
|
||||
@ -198,18 +197,18 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
const ndata = this.props.data;
|
||||
|
||||
const data_chartJS = (canvas: any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
const ctx = canvas.getContext('2d');
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, 100);
|
||||
gradient.addColorStop(0, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(1, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
gradient.addColorStop(1, 'rgba(250,174,50,1)');
|
||||
return {
|
||||
labels: ndata.map((s) => new Date(s.timestamp / 1000000)), // converting from nano second to mili second
|
||||
datasets: [
|
||||
{
|
||||
label: "Error Percentage (%)",
|
||||
label: 'Error Percentage (%)',
|
||||
data: ndata.map((s) => s.errorRate),
|
||||
pointRadius: 0.5,
|
||||
borderColor: "rgba(227, 74, 51,1)", // Can also add transparency in border color
|
||||
borderColor: 'rgba(227, 74, 51,1)', // Can also add transparency in border color
|
||||
borderWidth: 2,
|
||||
},
|
||||
],
|
||||
@ -219,7 +218,7 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
return (
|
||||
<div>
|
||||
{this.GraphTracePopUp()}
|
||||
<div style={{ textAlign: "center" }}>Error Percentage (%)</div>
|
||||
<div style={{ textAlign: 'center' }}>Error Percentage (%)</div>
|
||||
<ChartJSLine
|
||||
ref={this.chartRef}
|
||||
data={data_chartJS}
|
||||
|
@ -1,12 +1,13 @@
|
||||
import React from "react";
|
||||
import { Line as ChartJSLine } from "react-chartjs-2";
|
||||
import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import { getOptions, borderColors } from "./graphConfig";
|
||||
import { externalMetricsItem } from "store/actions/MetricsActions";
|
||||
import { uniqBy, filter } from "lodash";
|
||||
import { filter,uniqBy } from 'lodash';
|
||||
import React from 'react';
|
||||
import { Line as ChartJSLine } from 'react-chartjs-2';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { externalMetricsItem } from 'store/actions/MetricsActions';
|
||||
|
||||
const theme = "dark";
|
||||
import { borderColors,getOptions } from './graphConfig';
|
||||
|
||||
const theme = 'dark';
|
||||
|
||||
interface ExternalApiGraphProps extends RouteComponentProps<any> {
|
||||
data: externalMetricsItem[];
|
||||
@ -48,7 +49,7 @@ class ExternalApiGraph extends React.Component<ExternalApiGraphProps> {
|
||||
if (!keyIdentifier) {
|
||||
return [
|
||||
{
|
||||
label: label || "",
|
||||
label: label || '',
|
||||
data: data.map((s: externalMetricsItem) =>
|
||||
fnDataIdentifier
|
||||
? fnDataIdentifier(s[dataIdentifier])
|
||||
@ -80,11 +81,11 @@ class ExternalApiGraph extends React.Component<ExternalApiGraphProps> {
|
||||
});
|
||||
};
|
||||
const data_chartJS = (canvas: any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
const ctx = canvas.getContext('2d');
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, 100);
|
||||
gradient.addColorStop(0, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(1, "rgba(250,174,50,1)");
|
||||
const uniqTimestamp = uniqBy(data, "timestamp");
|
||||
gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
gradient.addColorStop(1, 'rgba(250,174,50,1)');
|
||||
const uniqTimestamp = uniqBy(data, 'timestamp');
|
||||
|
||||
return {
|
||||
labels: uniqTimestamp.map(
|
||||
@ -97,7 +98,7 @@ class ExternalApiGraph extends React.Component<ExternalApiGraphProps> {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<div style={{ textAlign: "center" }}>{title}</div>
|
||||
<div style={{ textAlign: 'center' }}>{title}</div>
|
||||
<ChartJSLine
|
||||
ref={this.chartRef}
|
||||
data={data_chartJS}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChartOptions } from "chart.js";
|
||||
import { ChartOptions } from 'chart.js';
|
||||
|
||||
export const getOptions = (theme: string): ChartOptions => {
|
||||
return {
|
||||
@ -7,22 +7,22 @@ export const getOptions = (theme: string): ChartOptions => {
|
||||
|
||||
title: {
|
||||
display: true,
|
||||
text: "",
|
||||
text: '',
|
||||
fontSize: 20,
|
||||
position: "top",
|
||||
position: 'top',
|
||||
padding: 8,
|
||||
fontFamily: "Arial",
|
||||
fontStyle: "regular",
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontFamily: 'Arial',
|
||||
fontStyle: 'regular',
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: "bottom",
|
||||
align: "center",
|
||||
position: 'bottom',
|
||||
align: 'center',
|
||||
|
||||
labels: {
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
fontSize: 10,
|
||||
boxWidth: 10,
|
||||
usePointStyle: true,
|
||||
@ -30,20 +30,20 @@ export const getOptions = (theme: string): ChartOptions => {
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
mode: "label",
|
||||
mode: 'label',
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
if (typeof tooltipItem.yLabel === "number") {
|
||||
if (typeof tooltipItem.yLabel === 'number') {
|
||||
return (
|
||||
data.datasets![tooltipItem.datasetIndex!].label +
|
||||
" : " +
|
||||
' : ' +
|
||||
tooltipItem.yLabel.toFixed(2)
|
||||
);
|
||||
} else {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -63,18 +63,18 @@ export const getOptions = (theme: string): ChartOptions => {
|
||||
gridLines: {
|
||||
// You can change the color, the dash effect, the main axe color, etc.
|
||||
borderDash: [1, 4],
|
||||
color: "#D3D3D3",
|
||||
color: '#D3D3D3',
|
||||
lineWidth: 0.25,
|
||||
},
|
||||
},
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
type: 'time',
|
||||
// time: {
|
||||
// unit: 'second'
|
||||
// },
|
||||
distribution: "linear",
|
||||
distribution: 'linear',
|
||||
//'linear': data are spread according to their time (distances can vary)
|
||||
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
|
||||
ticks: {
|
||||
@ -91,15 +91,15 @@ export const getOptions = (theme: string): ChartOptions => {
|
||||
};
|
||||
|
||||
export const borderColors = [
|
||||
"#00feff",
|
||||
"rgba(227, 74, 51, 1.0)",
|
||||
"rgba(250,174,50,1)",
|
||||
"#058b00",
|
||||
"#a47f00",
|
||||
"rgba(57, 255, 20, 1.0)",
|
||||
"#45a1ff",
|
||||
"#ffe900",
|
||||
"#30e60b",
|
||||
"#8000d7",
|
||||
"#ededf0"
|
||||
'#00feff',
|
||||
'rgba(227, 74, 51, 1.0)',
|
||||
'rgba(250,174,50,1)',
|
||||
'#058b00',
|
||||
'#a47f00',
|
||||
'rgba(57, 255, 20, 1.0)',
|
||||
'#45a1ff',
|
||||
'#ffe900',
|
||||
'#30e60b',
|
||||
'#8000d7',
|
||||
'#ededf0',
|
||||
];
|
||||
|
@ -1 +1 @@
|
||||
export { default } from "./ExternalApiGraph";
|
||||
export { default } from './ExternalApiGraph';
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React from "react";
|
||||
import { Bar, Line as ChartJSLine } from "react-chartjs-2";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { customMetricsItem } from "store/actions/MetricsActions";
|
||||
import React from 'react';
|
||||
import { Bar, Line as ChartJSLine } from 'react-chartjs-2';
|
||||
import { customMetricsItem } from 'store/actions/MetricsActions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const GenVisualizationWrapper = styled.div`
|
||||
height: 160px;
|
||||
@ -25,8 +24,8 @@ const GenericVisualizations = (props: GenericVisualizationsProps) => {
|
||||
props.data !== undefined &&
|
||||
props.data !== null &&
|
||||
props.data.map((s) => s.value),
|
||||
borderColor: "rgba(250,174,50,1)", // for line chart
|
||||
backgroundColor: props.chartType === "bar" ? "rgba(250,174,50,1)" : "", // for bar chart, don't assign backgroundcolor if its not a bar chart, may be relevant for area graph though
|
||||
borderColor: 'rgba(250,174,50,1)', // for line chart
|
||||
backgroundColor: props.chartType === 'bar' ? 'rgba(250,174,50,1)' : '', // for bar chart, don't assign backgroundcolor if its not a bar chart, may be relevant for area graph though
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -50,7 +49,7 @@ const GenericVisualizations = (props: GenericVisualizationsProps) => {
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
type: 'time',
|
||||
// distribution: 'linear',
|
||||
//'linear': data are spread according to their time (distances can vary)
|
||||
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
|
||||
@ -66,13 +65,13 @@ const GenericVisualizations = (props: GenericVisualizationsProps) => {
|
||||
},
|
||||
};
|
||||
|
||||
if (props.chartType === "line") {
|
||||
if (props.chartType === 'line') {
|
||||
return (
|
||||
<GenVisualizationWrapper>
|
||||
<ChartJSLine data={data} options={options} />
|
||||
</GenVisualizationWrapper>
|
||||
);
|
||||
} else if (props.chartType === "bar") {
|
||||
} else if (props.chartType === 'bar') {
|
||||
return (
|
||||
<GenVisualizationWrapper>
|
||||
<Bar data={data} options={options} />
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import { Line as ChartJSLine } from "react-chartjs-2";
|
||||
import { ChartOptions } from "chart.js";
|
||||
import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { metricItem } from "store/actions/MetricsActions";
|
||||
import { ChartOptions } from 'chart.js';
|
||||
import React from 'react';
|
||||
import { Line as ChartJSLine } from 'react-chartjs-2';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { metricItem } from 'store/actions/MetricsActions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const ChartPopUpUnique = styled.div<{
|
||||
ycoordinate: number;
|
||||
@ -30,7 +30,7 @@ const PopUpElements = styled.p`
|
||||
}
|
||||
`;
|
||||
|
||||
const theme = "dark";
|
||||
const theme = 'dark';
|
||||
|
||||
interface LatencyLineChartProps extends RouteComponentProps<any> {
|
||||
data: metricItem[];
|
||||
@ -52,7 +52,7 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
};
|
||||
|
||||
onClickhandler = async (e: any, event: any) => {
|
||||
var firstPoint;
|
||||
let firstPoint;
|
||||
if (this.chartRef) {
|
||||
firstPoint = this.chartRef.current.chartInstance.getElementAtEvent(e)[0];
|
||||
}
|
||||
@ -81,22 +81,22 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
|
||||
title: {
|
||||
display: true,
|
||||
text: "",
|
||||
text: '',
|
||||
fontSize: 20,
|
||||
position: "top",
|
||||
position: 'top',
|
||||
padding: 8,
|
||||
fontFamily: "Arial",
|
||||
fontStyle: "regular",
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontFamily: 'Arial',
|
||||
fontStyle: 'regular',
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: "bottom",
|
||||
align: "center",
|
||||
position: 'bottom',
|
||||
align: 'center',
|
||||
|
||||
labels: {
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
fontSize: 10,
|
||||
boxWidth: 10,
|
||||
usePointStyle: true,
|
||||
@ -104,20 +104,20 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
mode: "label",
|
||||
mode: 'label',
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
if (typeof tooltipItem.yLabel === "number") {
|
||||
if (typeof tooltipItem.yLabel === 'number') {
|
||||
return (
|
||||
data.datasets![tooltipItem.datasetIndex!].label +
|
||||
" : " +
|
||||
' : ' +
|
||||
tooltipItem.yLabel.toFixed(2)
|
||||
);
|
||||
} else {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -137,15 +137,15 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
gridLines: {
|
||||
// You can change the color, the dash effect, the main axe color, etc.
|
||||
borderDash: [1, 4],
|
||||
color: "#D3D3D3",
|
||||
color: '#D3D3D3',
|
||||
lineWidth: 0.25,
|
||||
},
|
||||
},
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
distribution: "linear",
|
||||
type: 'time',
|
||||
distribution: 'linear',
|
||||
//'linear': data are spread according to their time (distances can vary)
|
||||
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
|
||||
ticks: {
|
||||
@ -183,32 +183,32 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
const ndata = this.props.data;
|
||||
|
||||
const data_chartJS = (canvas: any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
const ctx = canvas.getContext('2d');
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, 100);
|
||||
gradient.addColorStop(0, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(1, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
gradient.addColorStop(1, 'rgba(250,174,50,1)');
|
||||
return {
|
||||
labels: ndata.map((s) => new Date(s.timestamp / 1000000)),
|
||||
datasets: [
|
||||
{
|
||||
label: "p99 Latency",
|
||||
label: 'p99 Latency',
|
||||
data: ndata.map((s) => s.p99 / 1000000), //converting latency from nano sec to ms
|
||||
pointRadius: 0.5,
|
||||
borderColor: "rgba(250,174,50,1)", // Can also add transparency in border color
|
||||
borderColor: 'rgba(250,174,50,1)', // Can also add transparency in border color
|
||||
borderWidth: 2,
|
||||
},
|
||||
{
|
||||
label: "p95 Latency",
|
||||
label: 'p95 Latency',
|
||||
data: ndata.map((s) => s.p95 / 1000000), //converting latency from nano sec to ms
|
||||
pointRadius: 0.5,
|
||||
borderColor: "rgba(227, 74, 51, 1.0)",
|
||||
borderColor: 'rgba(227, 74, 51, 1.0)',
|
||||
borderWidth: 2,
|
||||
},
|
||||
{
|
||||
label: "p50 Latency",
|
||||
label: 'p50 Latency',
|
||||
data: ndata.map((s) => s.p50 / 1000000), //converting latency from nano sec to ms
|
||||
pointRadius: 0.5,
|
||||
borderColor: "rgba(57, 255, 20, 1.0)",
|
||||
borderColor: 'rgba(57, 255, 20, 1.0)',
|
||||
borderWidth: 2,
|
||||
},
|
||||
],
|
||||
@ -219,7 +219,7 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
<div>
|
||||
{this.GraphTracePopUp()}
|
||||
<div>
|
||||
<div style={{ textAlign: "center" }}>Application latency in ms</div>
|
||||
<div style={{ textAlign: 'center' }}>Application latency in ms</div>
|
||||
<ChartJSLine
|
||||
ref={this.chartRef}
|
||||
data={data_chartJS}
|
||||
|
@ -1,12 +1,11 @@
|
||||
import React from "react";
|
||||
import { Line as ChartJSLine } from "react-chartjs-2";
|
||||
import { ChartOptions } from "chart.js";
|
||||
import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { metricItem } from "store/actions/MetricsActions";
|
||||
import ROUTES from "constants/routes";
|
||||
import { ChartOptions } from 'chart.js';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React from 'react';
|
||||
import { Line as ChartJSLine } from 'react-chartjs-2';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { metricItem } from 'store/actions/MetricsActions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const ChartPopUpUnique = styled.div<{
|
||||
ycoordinate: number;
|
||||
@ -32,7 +31,7 @@ const PopUpElements = styled.p`
|
||||
}
|
||||
`;
|
||||
|
||||
const theme = "dark";
|
||||
const theme = 'dark';
|
||||
|
||||
interface RequestRateChartProps extends RouteComponentProps<any> {
|
||||
data: metricItem[];
|
||||
@ -56,7 +55,7 @@ class RequestRateChart extends React.Component<RequestRateChartProps> {
|
||||
};
|
||||
|
||||
onClickhandler = async (e: any, event: any) => {
|
||||
var firstPoint;
|
||||
let firstPoint;
|
||||
if (this.chartRef) {
|
||||
firstPoint = this.chartRef.current.chartInstance.getElementAtEvent(e)[0];
|
||||
}
|
||||
@ -89,22 +88,22 @@ class RequestRateChart extends React.Component<RequestRateChartProps> {
|
||||
|
||||
title: {
|
||||
display: true,
|
||||
text: "",
|
||||
text: '',
|
||||
fontSize: 20,
|
||||
position: "top",
|
||||
position: 'top',
|
||||
padding: 2,
|
||||
fontFamily: "Arial",
|
||||
fontStyle: "regular",
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontFamily: 'Arial',
|
||||
fontStyle: 'regular',
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: "bottom",
|
||||
align: "center",
|
||||
position: 'bottom',
|
||||
align: 'center',
|
||||
|
||||
labels: {
|
||||
fontColor: theme === "dark" ? "rgb(200, 200, 200)" : "rgb(20, 20, 20)",
|
||||
fontColor: theme === 'dark' ? 'rgb(200, 200, 200)' : 'rgb(20, 20, 20)',
|
||||
fontSize: 10,
|
||||
boxWidth: 10,
|
||||
usePointStyle: true,
|
||||
@ -112,20 +111,20 @@ class RequestRateChart extends React.Component<RequestRateChartProps> {
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
mode: "label",
|
||||
mode: 'label',
|
||||
bodyFontSize: 12,
|
||||
titleFontSize: 12,
|
||||
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
if (typeof tooltipItem.yLabel === "number") {
|
||||
if (typeof tooltipItem.yLabel === 'number') {
|
||||
return (
|
||||
data.datasets![tooltipItem.datasetIndex!].label +
|
||||
" : " +
|
||||
' : ' +
|
||||
tooltipItem.yLabel.toFixed(2)
|
||||
);
|
||||
} else {
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -145,18 +144,18 @@ class RequestRateChart extends React.Component<RequestRateChartProps> {
|
||||
gridLines: {
|
||||
// You can change the color, the dash effect, the main axe color, etc.
|
||||
borderDash: [1, 4],
|
||||
color: "#D3D3D3",
|
||||
color: '#D3D3D3',
|
||||
lineWidth: 0.25,
|
||||
},
|
||||
},
|
||||
],
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
type: 'time',
|
||||
// time: {
|
||||
// unit: 'second'
|
||||
// },
|
||||
distribution: "linear",
|
||||
distribution: 'linear',
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
fontSize: 10,
|
||||
@ -187,18 +186,18 @@ class RequestRateChart extends React.Component<RequestRateChartProps> {
|
||||
const ndata = this.props.data;
|
||||
|
||||
const data_chartJS = (canvas: any) => {
|
||||
const ctx = canvas.getContext("2d");
|
||||
const ctx = canvas.getContext('2d');
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, 100);
|
||||
gradient.addColorStop(0, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(1, "rgba(250,174,50,1)");
|
||||
gradient.addColorStop(0, 'rgba(250,174,50,1)');
|
||||
gradient.addColorStop(1, 'rgba(250,174,50,1)');
|
||||
return {
|
||||
labels: ndata.map((s) => new Date(s.timestamp / 1000000)),
|
||||
datasets: [
|
||||
{
|
||||
label: "Request per sec",
|
||||
label: 'Request per sec',
|
||||
data: ndata.map((s) => s.callRate),
|
||||
pointRadius: 0.5,
|
||||
borderColor: "rgba(250,174,50,1)", // Can also add transparency in border color
|
||||
borderColor: 'rgba(250,174,50,1)', // Can also add transparency in border color
|
||||
borderWidth: 2,
|
||||
},
|
||||
],
|
||||
@ -208,7 +207,7 @@ class RequestRateChart extends React.Component<RequestRateChartProps> {
|
||||
return (
|
||||
<div>
|
||||
{this.GraphTracePopUp()}
|
||||
<div style={{ textAlign: "center" }}>Request per sec</div>
|
||||
<div style={{ textAlign: 'center' }}>Request per sec</div>
|
||||
<ChartJSLine
|
||||
ref={this.chartRef}
|
||||
data={data_chartJS}
|
||||
|
@ -1,34 +1,34 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Tabs, Card, Row, Col } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { useParams, RouteComponentProps } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import ROUTES from "constants/routes";
|
||||
import { GlobalTime, updateTimeInterval } from "store/actions";
|
||||
import { Card, Col,Row, Tabs } from 'antd';
|
||||
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps,useParams } from 'react-router-dom';
|
||||
import { GlobalTime, updateTimeInterval } from 'store/actions';
|
||||
import {
|
||||
metricItem,
|
||||
externalMetricsAvgDurationItem,
|
||||
externalErrCodeMetricsItem,
|
||||
externalMetricsItem,
|
||||
dbOverviewMetricsItem,
|
||||
externalErrCodeMetricsItem,
|
||||
externalMetricsAvgDurationItem,
|
||||
externalMetricsItem,
|
||||
metricItem,
|
||||
topEndpointListItem,
|
||||
} from "store/actions/MetricsActions";
|
||||
} from 'store/actions/MetricsActions';
|
||||
import {
|
||||
getServicesMetrics,
|
||||
getTopEndpoints,
|
||||
getDbOverViewMetrics,
|
||||
getExternalMetrics,
|
||||
getExternalAvgDurationMetrics,
|
||||
getExternalErrCodeMetrics,
|
||||
} from "store/actions/MetricsActions";
|
||||
getExternalMetrics,
|
||||
getServicesMetrics,
|
||||
getTopEndpoints,
|
||||
} from 'store/actions/MetricsActions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
|
||||
import { StoreState } from "store/reducers";
|
||||
import LatencyLineChart from "./LatencyLineChart";
|
||||
import RequestRateChart from "./RequestRateChart";
|
||||
import ErrorRateChart from "./ErrorRateChart";
|
||||
import TopEndpointsTable from "./TopEndpointsTable";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "constants/query";
|
||||
import ExternalApiGraph from "./ExternalApi";
|
||||
import ErrorRateChart from './ErrorRateChart';
|
||||
import ExternalApiGraph from './ExternalApi';
|
||||
import LatencyLineChart from './LatencyLineChart';
|
||||
import RequestRateChart from './RequestRateChart';
|
||||
import TopEndpointsTable from './TopEndpointsTable';
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
interface ServicesMetricsProps extends RouteComponentProps<any> {
|
||||
@ -63,7 +63,7 @@ const _ServiceMetrics = (props: ServicesMetricsProps) => {
|
||||
const currentTime = timestamp / 1000000;
|
||||
const tPlusOne = timestamp / 1000000 + 1 * 60 * 1000;
|
||||
|
||||
props.updateTimeInterval("custom", [currentTime, tPlusOne]); // updateTimeInterval takes second range in ms -- give -5 min to selected time,
|
||||
props.updateTimeInterval('custom', [currentTime, tPlusOne]); // updateTimeInterval takes second range in ms -- give -5 min to selected time,
|
||||
|
||||
const urlParams = new URLSearchParams();
|
||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.startTime, currentTime.toString());
|
||||
@ -79,7 +79,7 @@ const _ServiceMetrics = (props: ServicesMetricsProps) => {
|
||||
const currentTime = timestamp / 1000000;
|
||||
const tPlusOne = timestamp / 1000000 + 1 * 60 * 1000;
|
||||
|
||||
props.updateTimeInterval("custom", [currentTime, tPlusOne]); // updateTimeInterval takes second range in ms -- give -5 min to selected time,
|
||||
props.updateTimeInterval('custom', [currentTime, tPlusOne]); // updateTimeInterval takes second range in ms -- give -5 min to selected time,
|
||||
|
||||
const urlParams = new URLSearchParams();
|
||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.startTime, currentTime.toString());
|
||||
@ -87,7 +87,7 @@ const _ServiceMetrics = (props: ServicesMetricsProps) => {
|
||||
if (servicename) {
|
||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.service, servicename);
|
||||
}
|
||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.error, "true");
|
||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.error, 'true');
|
||||
|
||||
props.history.push(`${ROUTES.TRACES}?${urlParams.toString()}`);
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
export { ServiceMetrics as default } from "./ServiceMetrics";
|
||||
export { ServiceMetrics as default } from './ServiceMetrics';
|
||||
|
@ -1,15 +1,15 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { Button, Space, Table } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { connect } from "react-redux";
|
||||
import Spinner from "components/Spinner";
|
||||
import { SKIP_ONBOARDING } from "constants/onboarding";
|
||||
import ROUTES from "constants/routes";
|
||||
import { getServicesList, GlobalTime } from "store/actions";
|
||||
import { servicesListItem } from "store/actions/MetricsActions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { CustomModal } from "components/Modal";
|
||||
import { Button, Space, Table } from 'antd';
|
||||
import { CustomModal } from 'components/Modal';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { SKIP_ONBOARDING } from 'constants/onboarding';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { getServicesList, GlobalTime } from 'store/actions';
|
||||
import { servicesListItem } from 'store/actions/MetricsActions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface ServicesTableProps {
|
||||
servicesList: servicesListItem[];
|
||||
@ -45,38 +45,38 @@ const LoadingText = styled.div`
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "Application",
|
||||
dataIndex: "serviceName",
|
||||
key: "serviceName",
|
||||
title: 'Application',
|
||||
dataIndex: 'serviceName',
|
||||
key: 'serviceName',
|
||||
render: (text: string) => (
|
||||
<NavLink
|
||||
style={{ textTransform: "capitalize" }}
|
||||
to={ROUTES.APPLICATION + "/" + text}
|
||||
style={{ textTransform: 'capitalize' }}
|
||||
to={ROUTES.APPLICATION + '/' + text}
|
||||
>
|
||||
<strong>{text}</strong>
|
||||
</NavLink>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "P99 latency (in ms)",
|
||||
dataIndex: "p99",
|
||||
key: "p99",
|
||||
title: 'P99 latency (in ms)',
|
||||
dataIndex: 'p99',
|
||||
key: 'p99',
|
||||
sorter: (a: any, b: any) => a.p99 - b.p99,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "Error Rate (in %)",
|
||||
dataIndex: "errorRate",
|
||||
key: "errorRate",
|
||||
title: 'Error Rate (in %)',
|
||||
dataIndex: 'errorRate',
|
||||
key: 'errorRate',
|
||||
sorter: (a: any, b: any) => a.errorRate - b.errorRate,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => value.toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "Requests Per Second",
|
||||
dataIndex: "callRate",
|
||||
key: "callRate",
|
||||
title: 'Requests Per Second',
|
||||
dataIndex: 'callRate',
|
||||
key: 'callRate',
|
||||
sorter: (a: any, b: any) => a.callRate - b.callRate,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => value.toFixed(2),
|
||||
@ -86,18 +86,18 @@ const columns = [
|
||||
const _ServicesTable = (props: ServicesTableProps) => {
|
||||
const [initialDataFetch, setDataFetched] = useState(false);
|
||||
const [errorObject, setErrorObject] = useState({
|
||||
message: "",
|
||||
message: '',
|
||||
isError: false,
|
||||
});
|
||||
const isEmptyServiceList =
|
||||
!initialDataFetch && props.servicesList.length === 0;
|
||||
const refetchFromBackend = isEmptyServiceList || errorObject.isError;
|
||||
const [skipOnboarding, setSkipOnboarding] = useState(
|
||||
localStorage.getItem(SKIP_ONBOARDING) === "true",
|
||||
localStorage.getItem(SKIP_ONBOARDING) === 'true',
|
||||
);
|
||||
|
||||
const onContinueClick = () => {
|
||||
localStorage.setItem(SKIP_ONBOARDING, "true");
|
||||
localStorage.setItem(SKIP_ONBOARDING, 'true');
|
||||
setSkipOnboarding(true);
|
||||
};
|
||||
|
||||
@ -106,7 +106,7 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
.getServicesList(props.globalTime)
|
||||
.then(() => {
|
||||
setDataFetched(true);
|
||||
setErrorObject({ message: "", isError: false });
|
||||
setErrorObject({ message: '', isError: false });
|
||||
})
|
||||
.catch((e: string) => {
|
||||
setErrorObject({ message: e, isError: true });
|
||||
@ -130,7 +130,7 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
if (refetchFromBackend && !skipOnboarding) {
|
||||
return (
|
||||
<CustomModal
|
||||
title={"Setup instrumentation"}
|
||||
title={'Setup instrumentation'}
|
||||
isModalVisible={true}
|
||||
closable={false}
|
||||
setIsModalVisible={() => {}}
|
||||
@ -149,16 +149,17 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
<div style={{ margin: "20px 0" }}>
|
||||
<div style={{ margin: '20px 0' }}>
|
||||
<Spinner />
|
||||
</div>
|
||||
<div>
|
||||
No instrumentation data.
|
||||
<br />
|
||||
Please instrument your application as mentioned{" "}
|
||||
Please instrument your application as mentioned{' '}
|
||||
<a
|
||||
href={"https://signoz.io/docs/instrumentation/overview"}
|
||||
target={"_blank"}
|
||||
href={'https://signoz.io/docs/instrumentation/overview'}
|
||||
target={'_blank'}
|
||||
rel="noreferrer"
|
||||
>
|
||||
here
|
||||
</a>
|
||||
@ -178,20 +179,21 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
|
||||
{props.servicesList[0] !== undefined &&
|
||||
props.servicesList[0].numCalls === 0 && (
|
||||
<Space
|
||||
style={{ width: "100%", margin: "40px 0", justifyContent: "center" }}
|
||||
>
|
||||
<Space
|
||||
style={{ width: '100%', margin: '40px 0', justifyContent: 'center' }}
|
||||
>
|
||||
No applications present. Please add instrumentation (follow this
|
||||
<a
|
||||
href={"https://signoz.io/docs/instrumentation/overview"}
|
||||
target={"_blank"}
|
||||
style={{ marginLeft: 3 }}
|
||||
>
|
||||
<a
|
||||
href={'https://signoz.io/docs/instrumentation/overview'}
|
||||
target={'_blank'}
|
||||
style={{ marginLeft: 3 }}
|
||||
rel="noreferrer"
|
||||
>
|
||||
guide
|
||||
</a>
|
||||
</a>
|
||||
)
|
||||
</Space>
|
||||
)}
|
||||
</Space>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
export { ServicesTable as default } from "./ServicesTable";
|
||||
export { ServicesTable as default } from './ServicesTable';
|
||||
|
@ -1,13 +1,14 @@
|
||||
import React from "react";
|
||||
import { Table, Button, Tooltip } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import styled from "styled-components";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import { topEndpointListItem } from "store/actions/MetricsActions";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "constants/query";
|
||||
import { GlobalTime } from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import "./TopEndpointsTable.css";
|
||||
import './TopEndpointsTable.css';
|
||||
|
||||
import { Button, Table, Tooltip } from 'antd';
|
||||
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { GlobalTime } from 'store/actions';
|
||||
import { topEndpointListItem } from 'store/actions/MetricsActions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding-top: 10px;
|
||||
@ -60,9 +61,9 @@ const _TopEndpointsTable = (props: TopEndpointsTableProps) => {
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: "Name",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
|
||||
render: (text: string) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
@ -77,33 +78,33 @@ const _TopEndpointsTable = (props: TopEndpointsTableProps) => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "P50 (in ms)",
|
||||
dataIndex: "p50",
|
||||
key: "p50",
|
||||
title: 'P50 (in ms)',
|
||||
dataIndex: 'p50',
|
||||
key: 'p50',
|
||||
sorter: (a: any, b: any) => a.p50 - b.p50,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "P95 (in ms)",
|
||||
dataIndex: "p95",
|
||||
key: "p95",
|
||||
title: 'P95 (in ms)',
|
||||
dataIndex: 'p95',
|
||||
key: 'p95',
|
||||
sorter: (a: any, b: any) => a.p95 - b.p95,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "P99 (in ms)",
|
||||
dataIndex: "p99",
|
||||
key: "p99",
|
||||
title: 'P99 (in ms)',
|
||||
dataIndex: 'p99',
|
||||
key: 'p99',
|
||||
sorter: (a: any, b: any) => a.p99 - b.p99,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "Number of Calls",
|
||||
dataIndex: "numCalls",
|
||||
key: "numCalls",
|
||||
title: 'Number of Calls',
|
||||
dataIndex: 'numCalls',
|
||||
key: 'numCalls',
|
||||
sorter: (a: any, b: any) => a.numCalls - b.numCalls,
|
||||
},
|
||||
];
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Layout, Menu, Switch as ToggleButton } from "antd";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { useThemeSwitcher } from "react-css-theme-switcher";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import ROUTES from "constants/routes";
|
||||
|
||||
import {
|
||||
LineChartOutlined,
|
||||
AlignLeftOutlined,
|
||||
ApiOutlined,
|
||||
BarChartOutlined,
|
||||
DeploymentUnitOutlined,
|
||||
AlignLeftOutlined,
|
||||
LineChartOutlined,
|
||||
SettingOutlined,
|
||||
ApiOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { ThemeSwitcherWrapper } from "./styles";
|
||||
} from '@ant-design/icons';
|
||||
import { Layout, Menu, Switch as ToggleButton } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React, { useEffect,useState } from 'react';
|
||||
import { useThemeSwitcher } from 'react-css-theme-switcher';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { ThemeSwitcherWrapper } from './styles';
|
||||
const { Sider } = Layout;
|
||||
|
||||
const SideNav = () => {
|
||||
@ -25,11 +25,11 @@ const SideNav = () => {
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
const newRoute = location.pathname.split("/")[1];
|
||||
const newRoute = location.pathname.split('/')[1];
|
||||
setSelectedKeys([`/${newRoute}`]);
|
||||
}, [location.pathname]);
|
||||
|
||||
if (status === "loading" || location.pathname === ROUTES.SIGN_UP) {
|
||||
if (status === 'loading' || location.pathname === ROUTES.SIGN_UP) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -51,12 +51,12 @@ const SideNav = () => {
|
||||
</ThemeSwitcherWrapper>
|
||||
<NavLink to="/">
|
||||
<img
|
||||
src={"/signoz.svg"}
|
||||
alt={"SigNoz"}
|
||||
src={'/signoz.svg'}
|
||||
alt={'SigNoz'}
|
||||
style={{
|
||||
margin: "5%",
|
||||
margin: '5%',
|
||||
width: 100,
|
||||
display: !collapsed ? "block" : "none",
|
||||
display: !collapsed ? 'block' : 'none',
|
||||
}}
|
||||
/>
|
||||
</NavLink>
|
||||
@ -71,7 +71,7 @@ const SideNav = () => {
|
||||
<Menu.Item key={ROUTES.APPLICATION} icon={<BarChartOutlined />}>
|
||||
<NavLink
|
||||
to={ROUTES.APPLICATION}
|
||||
style={{ fontSize: 12, textDecoration: "none" }}
|
||||
style={{ fontSize: 12, textDecoration: 'none' }}
|
||||
>
|
||||
Metrics
|
||||
</NavLink>
|
||||
@ -79,7 +79,7 @@ const SideNav = () => {
|
||||
<Menu.Item key={ROUTES.TRACES} icon={<AlignLeftOutlined />}>
|
||||
<NavLink
|
||||
to={ROUTES.TRACES}
|
||||
style={{ fontSize: 12, textDecoration: "none" }}
|
||||
style={{ fontSize: 12, textDecoration: 'none' }}
|
||||
>
|
||||
Traces
|
||||
</NavLink>
|
||||
@ -87,7 +87,7 @@ const SideNav = () => {
|
||||
<Menu.Item key={ROUTES.SERVICE_MAP} icon={<DeploymentUnitOutlined />}>
|
||||
<NavLink
|
||||
to={ROUTES.SERVICE_MAP}
|
||||
style={{ fontSize: 12, textDecoration: "none" }}
|
||||
style={{ fontSize: 12, textDecoration: 'none' }}
|
||||
>
|
||||
Service Map
|
||||
</NavLink>
|
||||
@ -95,7 +95,7 @@ const SideNav = () => {
|
||||
<Menu.Item key={ROUTES.USAGE_EXPLORER} icon={<LineChartOutlined />}>
|
||||
<NavLink
|
||||
to={ROUTES.USAGE_EXPLORER}
|
||||
style={{ fontSize: 12, textDecoration: "none" }}
|
||||
style={{ fontSize: 12, textDecoration: 'none' }}
|
||||
>
|
||||
Usage Explorer
|
||||
</NavLink>
|
||||
@ -103,7 +103,7 @@ const SideNav = () => {
|
||||
<Menu.Item key={ROUTES.SETTINGS} icon={<SettingOutlined />}>
|
||||
<NavLink
|
||||
to={ROUTES.SETTINGS}
|
||||
style={{ fontSize: 12, textDecoration: "none" }}
|
||||
style={{ fontSize: 12, textDecoration: 'none' }}
|
||||
>
|
||||
Settings
|
||||
</NavLink>
|
||||
@ -111,7 +111,7 @@ const SideNav = () => {
|
||||
<Menu.Item key={ROUTES.INSTRUMENTATION} icon={<ApiOutlined />}>
|
||||
<NavLink
|
||||
to={ROUTES.INSTRUMENTATION}
|
||||
style={{ fontSize: 12, textDecoration: "none" }}
|
||||
style={{ fontSize: 12, textDecoration: 'none' }}
|
||||
>
|
||||
Add instrumentation
|
||||
</NavLink>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useState } from "react";
|
||||
import { Modal, DatePicker } from "antd";
|
||||
import { DateTimeRangeType } from "store/actions";
|
||||
import { Moment } from "moment";
|
||||
import moment from "moment";
|
||||
import { DatePicker,Modal } from 'antd';
|
||||
import { Moment } from 'moment';
|
||||
import moment from 'moment';
|
||||
import React, { useState } from 'react';
|
||||
import { DateTimeRangeType } from 'store/actions';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
@ -43,7 +43,7 @@ const CustomDateTimeModal: React.FC<CustomDateTimeModalProps> = ({
|
||||
okText="Apply"
|
||||
cancelText="Cancel"
|
||||
onCancel={onCancel}
|
||||
style={{ position: "absolute", top: 60, right: 40 }}
|
||||
style={{ position: 'absolute', top: 60, right: 40 }}
|
||||
onOk={() => onCreate(customDateTimeRange ? customDateTimeRange : null)}
|
||||
>
|
||||
<RangePicker
|
||||
|
@ -1,25 +1,26 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { Select as DefaultSelect, Button, Space, Form } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { withRouter } from "react-router";
|
||||
import { getLocalStorageRouteKey } from "./utils";
|
||||
import { RouteComponentProps, useLocation } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
import ROUTES from "constants/routes";
|
||||
import CustomDateTimeModal from "./CustomDateTimeModal";
|
||||
import { GlobalTime, updateTimeInterval } from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import FormItem from "antd/lib/form/FormItem";
|
||||
import { Button, Form,Select as DefaultSelect, Space } from 'antd';
|
||||
import FormItem from 'antd/lib/form/FormItem';
|
||||
import { LOCAL_STORAGE } from 'constants/localStorage';
|
||||
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router';
|
||||
import { RouteComponentProps, useLocation } from 'react-router-dom';
|
||||
import { GlobalTime, updateTimeInterval } from 'store/actions';
|
||||
import { DateTimeRangeType } from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import {
|
||||
DefaultOptionsBasedOnRoute,
|
||||
Options,
|
||||
ServiceMapOptions,
|
||||
DefaultOptionsBasedOnRoute,
|
||||
} from "./config";
|
||||
import { DateTimeRangeType } from "store/actions";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "constants/query";
|
||||
import { LOCAL_STORAGE } from "constants/localStorage";
|
||||
import moment from "moment";
|
||||
} from './config';
|
||||
import CustomDateTimeModal from './CustomDateTimeModal';
|
||||
import { getLocalStorageRouteKey } from './utils';
|
||||
const { Option } = DefaultSelect;
|
||||
|
||||
const DateTimeWrapper = styled.div`
|
||||
@ -60,7 +61,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
const [startTime, setStartTime] = useState<moment.Moment | null>(null);
|
||||
const [endTime, setEndTime] = useState<moment.Moment | null>(null);
|
||||
const [refreshButtonHidden, setRefreshButtonHidden] = useState(false);
|
||||
const [refreshText, setRefreshText] = useState("");
|
||||
const [refreshText, setRefreshText] = useState('');
|
||||
const [refreshButtonClick, setRefreshButtonClick] = useState(0);
|
||||
const [form_dtselector] = Form.useForm();
|
||||
|
||||
@ -126,7 +127,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
endTime: moment.Moment,
|
||||
triggeredByURLChange = false,
|
||||
) => {
|
||||
props.updateTimeInterval("custom", [startTime.valueOf(), endTime.valueOf()]);
|
||||
props.updateTimeInterval('custom', [startTime.valueOf(), endTime.valueOf()]);
|
||||
setEndTime(endTime);
|
||||
setStartTime(startTime);
|
||||
};
|
||||
@ -150,7 +151,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
};
|
||||
|
||||
const handleOnSelect = (value: string) => {
|
||||
if (value === "custom") {
|
||||
if (value === 'custom') {
|
||||
setCustomDTPickerVisible(true);
|
||||
} else {
|
||||
updateUrlForTimeInterval(value);
|
||||
@ -175,9 +176,9 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
setRefreshButtonHidden(true);
|
||||
form_dtselector.setFieldsValue({
|
||||
interval:
|
||||
dateTimeRange[0].format("YYYY/MM/DD HH:mm") +
|
||||
"-" +
|
||||
dateTimeRange[1].format("YYYY/MM/DD HH:mm"),
|
||||
dateTimeRange[0].format('YYYY/MM/DD HH:mm') +
|
||||
'-' +
|
||||
dateTimeRange[1].format('YYYY/MM/DD HH:mm'),
|
||||
});
|
||||
}
|
||||
setCustomDTPickerVisible(false);
|
||||
@ -206,7 +207,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setRefreshText("");
|
||||
setRefreshText('');
|
||||
const interval = setInterval(() => {
|
||||
setRefreshText(timeSinceLastRefresh());
|
||||
}, 2000);
|
||||
@ -220,19 +221,19 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
} else {
|
||||
const inputLabeLToShow =
|
||||
startTime && endTime
|
||||
? `${startTime.format("YYYY/MM/DD HH:mm")} - ${endTime.format(
|
||||
"YYYY/MM/DD HH:mm",
|
||||
? `${startTime.format('YYYY/MM/DD HH:mm')} - ${endTime.format(
|
||||
'YYYY/MM/DD HH:mm',
|
||||
)}`
|
||||
: timeInterval;
|
||||
|
||||
return (
|
||||
<DateTimeWrapper>
|
||||
<Space style={{ float: "right", display: "block" }}>
|
||||
<Space style={{ float: 'right', display: 'block' }}>
|
||||
<Space>
|
||||
<Form
|
||||
form={form_dtselector}
|
||||
layout="inline"
|
||||
initialValues={{ interval: "15min" }}
|
||||
initialValues={{ interval: '15min' }}
|
||||
style={{ marginTop: 10, marginBottom: 10 }}
|
||||
>
|
||||
<Select onSelect={handleOnSelect} value={inputLabeLToShow}>
|
||||
@ -250,12 +251,12 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => {
|
||||
</Space>
|
||||
<Space
|
||||
style={{
|
||||
float: "right",
|
||||
display: "block",
|
||||
float: 'right',
|
||||
display: 'block',
|
||||
marginRight: 20,
|
||||
minHeight: 23,
|
||||
width: 200,
|
||||
textAlign: "right",
|
||||
textAlign: 'right',
|
||||
}}
|
||||
>
|
||||
{refreshText}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import { Breadcrumb } from "antd";
|
||||
import { Link, withRouter } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import ROUTES from "constants/routes";
|
||||
import { Breadcrumb } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React from 'react';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const BreadCrumbWrapper = styled.div`
|
||||
padding-top: 20px;
|
||||
@ -11,23 +11,23 @@ const BreadCrumbWrapper = styled.div`
|
||||
|
||||
const breadcrumbNameMap: any = {
|
||||
// PNOTE - TO DO - Remove any and do typechecking - like https://stackoverflow.com/questions/56568423/typescript-no-index-signature-with-a-parameter-of-type-string-was-found-on-ty
|
||||
[ROUTES.APPLICATION]: "Application",
|
||||
[ROUTES.TRACES]: "Traces",
|
||||
[ROUTES.SERVICE_MAP]: "Service Map",
|
||||
[ROUTES.USAGE_EXPLORER]: "Usage Explorer",
|
||||
[ROUTES.INSTRUMENTATION]: "Add instrumentation",
|
||||
[ROUTES.SETTINGS]: "Settings",
|
||||
[ROUTES.APPLICATION]: 'Application',
|
||||
[ROUTES.TRACES]: 'Traces',
|
||||
[ROUTES.SERVICE_MAP]: 'Service Map',
|
||||
[ROUTES.USAGE_EXPLORER]: 'Usage Explorer',
|
||||
[ROUTES.INSTRUMENTATION]: 'Add instrumentation',
|
||||
[ROUTES.SETTINGS]: 'Settings',
|
||||
};
|
||||
|
||||
const ShowBreadcrumbs = withRouter((props) => {
|
||||
const { location } = props;
|
||||
const pathSnippets = location.pathname.split("/").filter((i) => i);
|
||||
const pathSnippets = location.pathname.split('/').filter((i) => i);
|
||||
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
|
||||
const url = `/${pathSnippets.slice(0, index + 1).join("/")}`;
|
||||
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
||||
if (breadcrumbNameMap[url] === undefined) {
|
||||
return (
|
||||
<Breadcrumb.Item key={url}>
|
||||
<Link to={url}>{url.split("/").slice(-1)[0]}</Link>
|
||||
<Link to={url}>{url.split('/').slice(-1)[0]}</Link>
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
} else {
|
||||
|
@ -1,19 +1,19 @@
|
||||
import ROUTES from "constants/routes";
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
export const Options = [
|
||||
{ value: "5min", label: "Last 5 min" },
|
||||
{ value: "15min", label: "Last 15 min" },
|
||||
{ value: "30min", label: "Last 30 min" },
|
||||
{ value: "1hr", label: "Last 1 hour" },
|
||||
{ value: "6hr", label: "Last 6 hour" },
|
||||
{ value: "1day", label: "Last 1 day" },
|
||||
{ value: "1week", label: "Last 1 week" },
|
||||
{ value: "custom", label: "Custom" },
|
||||
{ value: '5min', label: 'Last 5 min' },
|
||||
{ value: '15min', label: 'Last 15 min' },
|
||||
{ value: '30min', label: 'Last 30 min' },
|
||||
{ value: '1hr', label: 'Last 1 hour' },
|
||||
{ value: '6hr', label: 'Last 6 hour' },
|
||||
{ value: '1day', label: 'Last 1 day' },
|
||||
{ value: '1week', label: 'Last 1 week' },
|
||||
{ value: 'custom', label: 'Custom' },
|
||||
];
|
||||
|
||||
export const ServiceMapOptions = [
|
||||
{ value: "1min", label: "Last 1 min" },
|
||||
{ value: "5min", label: "Last 5 min" },
|
||||
{ value: '1min', label: 'Last 1 min' },
|
||||
{ value: '5min', label: 'Last 5 min' },
|
||||
];
|
||||
|
||||
export const DefaultOptionsBasedOnRoute = {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import { Row, Col } from "antd";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import ROUTES from "constants/routes";
|
||||
import { Col,Row } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import DateTimeSelector from "./DateTimeSelector";
|
||||
import ShowBreadcrumbs from "./ShowBreadcrumbs";
|
||||
import DateTimeSelector from './DateTimeSelector';
|
||||
import ShowBreadcrumbs from './ShowBreadcrumbs';
|
||||
|
||||
const TopNav = () => {
|
||||
const history = useHistory();
|
||||
|
@ -1,13 +1,13 @@
|
||||
import ROUTES from "constants/routes";
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
export const getLocalStorageRouteKey = (pathName: string) => {
|
||||
let localStorageKey = "";
|
||||
const pathNameSplit = pathName.split("/");
|
||||
let localStorageKey = '';
|
||||
const pathNameSplit = pathName.split('/');
|
||||
if (!pathNameSplit[2]) {
|
||||
localStorageKey = pathName;
|
||||
} else {
|
||||
Object.keys(ROUTES).forEach((key) => {
|
||||
if (ROUTES[key].indexOf(":") > -1) {
|
||||
if (ROUTES[key].indexOf(':') > -1) {
|
||||
if (ROUTES[key].indexOf(pathNameSplit[1]) > -1) {
|
||||
localStorageKey = ROUTES[key];
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import styled from "styled-components";
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const ThemeSwitcherWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
`;
|
||||
`;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext, createContext, ReactNode, Dispatch } from "react";
|
||||
import ROUTES from "constants/routes";
|
||||
import ROUTES from 'constants/routes';
|
||||
import React, { createContext, Dispatch,ReactNode, useContext } from 'react';
|
||||
|
||||
type State = {
|
||||
[key: string]: {
|
||||
@ -9,7 +9,7 @@ type State = {
|
||||
};
|
||||
|
||||
enum ActionTypes {
|
||||
UPDATE_IS_LOADED = "ROUTE_IS_LOADED",
|
||||
UPDATE_IS_LOADED = 'ROUTE_IS_LOADED',
|
||||
}
|
||||
|
||||
type Action = {
|
||||
@ -76,7 +76,7 @@ const RouteProvider: React.FC<RouteProviderProps> = ({ children }) => {
|
||||
const useRoute = (): ContextType => {
|
||||
const context = useContext(RouteContext);
|
||||
if (context === undefined) {
|
||||
throw new Error("useRoute must be used within a RouteProvider");
|
||||
throw new Error('useRoute must be used within a RouteProvider');
|
||||
}
|
||||
return context as ContextType;
|
||||
};
|
||||
|
@ -1,20 +1,20 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { RouteComponentProps, withRouter } from "react-router-dom";
|
||||
import Spinner from 'components/Spinner';
|
||||
import { useRoute } from 'modules/RouteProvider';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { ForceGraph2D } from 'react-force-graph';
|
||||
import { connect } from 'react-redux';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
import {
|
||||
getDetailedServiceMapItems,
|
||||
getServiceMapItems,
|
||||
GlobalTime,
|
||||
serviceMapStore,
|
||||
getServiceMapItems,
|
||||
getDetailedServiceMapItems,
|
||||
} from "store/actions";
|
||||
import styled from "styled-components";
|
||||
import { StoreState } from "store/reducers";
|
||||
} from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils";
|
||||
import SelectService from "./SelectService";
|
||||
import { ForceGraph2D } from "react-force-graph";
|
||||
import Spinner from "components/Spinner";
|
||||
import { useRoute } from "modules/RouteProvider";
|
||||
import SelectService from './SelectService';
|
||||
import { getGraphData, getTooltip, getZoomPx, transformLabel } from './utils';
|
||||
|
||||
const Container = styled.div`
|
||||
.force-graph-container .graph-tooltip {
|
||||
@ -75,7 +75,7 @@ const ServiceMap = (props: ServiceMapProps) => {
|
||||
}, [globalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
fgRef.current && fgRef.current.d3Force("charge").strength(-400);
|
||||
fgRef.current && fgRef.current.d3Force('charge').strength(-400);
|
||||
});
|
||||
if (!serviceMap.items.length || !serviceMap.services.length) {
|
||||
return <Spinner size="large" tip="Loading..." />;
|
||||
@ -116,13 +116,13 @@ const ServiceMap = (props: ServiceMapProps) => {
|
||||
ctx.beginPath();
|
||||
ctx.arc(node.x, node.y, width, 0, 2 * Math.PI, false);
|
||||
ctx.fill();
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = "#646464";
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillStyle = '#646464';
|
||||
ctx.fillText(label, node.x, node.y);
|
||||
}}
|
||||
onNodeClick={(node) => {
|
||||
const tooltip = document.querySelector(".graph-tooltip");
|
||||
const tooltip = document.querySelector('.graph-tooltip');
|
||||
if (tooltip && node) {
|
||||
tooltip.innerHTML = getTooltip(node);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export { default } from "./ServiceMap";
|
||||
export { default } from './ServiceMap';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { uniqBy, uniq, maxBy, cloneDeep, find } from "lodash";
|
||||
import { serviceMapStore } from "Src/store/actions";
|
||||
import { graphDataType } from "./ServiceMap";
|
||||
import { cloneDeep, find,maxBy, uniq, uniqBy } from 'lodash';
|
||||
import { serviceMapStore } from 'Src/store/actions';
|
||||
|
||||
import { graphDataType } from './ServiceMap';
|
||||
|
||||
const MIN_WIDTH = 10;
|
||||
const MAX_WIDTH = 20;
|
||||
@ -20,7 +21,7 @@ export const getGraphData = (serviceMap: serviceMapStore): graphDataType => {
|
||||
const highestCallCount = maxBy(items, (e) => e.callCount).callCount;
|
||||
const highestCallRate = maxBy(services, (e) => e.callRate).callRate;
|
||||
const divNum = Number(
|
||||
String(1).padEnd(highestCallCount.toString().length, "0"),
|
||||
String(1).padEnd(highestCallCount.toString().length, '0'),
|
||||
);
|
||||
|
||||
const links = cloneDeep(items).map((node) => {
|
||||
@ -31,12 +32,12 @@ export const getGraphData = (serviceMap: serviceMapStore): graphDataType => {
|
||||
value: (100 - callCount / divNum) * 0.03,
|
||||
};
|
||||
});
|
||||
const uniqParent = uniqBy(cloneDeep(items), "parent").map((e) => e.parent);
|
||||
const uniqChild = uniqBy(cloneDeep(items), "child").map((e) => e.child);
|
||||
const uniqParent = uniqBy(cloneDeep(items), 'parent').map((e) => e.parent);
|
||||
const uniqChild = uniqBy(cloneDeep(items), 'child').map((e) => e.child);
|
||||
const uniqNodes = uniq([...uniqParent, ...uniqChild]);
|
||||
const nodes = uniqNodes.map((node, i) => {
|
||||
const service = find(services, (service) => service.serviceName === node);
|
||||
let color = "#88CEA5";
|
||||
let color = '#88CEA5';
|
||||
if (!service) {
|
||||
return {
|
||||
id: node,
|
||||
@ -51,9 +52,9 @@ export const getGraphData = (serviceMap: serviceMapStore): graphDataType => {
|
||||
};
|
||||
}
|
||||
if (service.errorRate > 0) {
|
||||
color = "#F98989";
|
||||
color = '#F98989';
|
||||
} else if (service.fourXXRate > 0) {
|
||||
color = "#F9DA7B";
|
||||
color = '#F9DA7B';
|
||||
}
|
||||
const { fontSize, width } = getDimensions(service.callRate, highestCallRate);
|
||||
return {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Form, Input, Space } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { Alert } from "antd";
|
||||
import { Form, Input, Space } from 'antd';
|
||||
import { Alert } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { StoreState } from 'store/reducers';
|
||||
|
||||
interface SettingsPageProps {}
|
||||
|
||||
@ -16,7 +16,7 @@ const SettingsPage = (props: SettingsPageProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue({
|
||||
retention_period: "3 days",
|
||||
retention_period: '3 days',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React from "react";
|
||||
import { Card, Tag as AntTag } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import styled from "styled-components";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { TagItem, TraceFilters, updateTraceFilters } from "store/actions";
|
||||
import { Card, Tag as AntTag } from 'antd';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { TagItem, TraceFilters, updateTraceFilters } from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Tag = styled(AntTag)`
|
||||
.anticon {
|
||||
@ -20,19 +19,19 @@ interface FilterStateDisplayProps {
|
||||
|
||||
const _FilterStateDisplay = (props: FilterStateDisplayProps) => {
|
||||
function handleCloseTag(value: string) {
|
||||
if (value === "service")
|
||||
props.updateTraceFilters({ ...props.traceFilters, service: "" });
|
||||
if (value === "operation")
|
||||
props.updateTraceFilters({ ...props.traceFilters, operation: "" });
|
||||
if (value === "maxLatency")
|
||||
if (value === 'service')
|
||||
props.updateTraceFilters({ ...props.traceFilters, service: '' });
|
||||
if (value === 'operation')
|
||||
props.updateTraceFilters({ ...props.traceFilters, operation: '' });
|
||||
if (value === 'maxLatency')
|
||||
props.updateTraceFilters({
|
||||
...props.traceFilters,
|
||||
latency: { max: "", min: props.traceFilters.latency?.min },
|
||||
latency: { max: '', min: props.traceFilters.latency?.min },
|
||||
});
|
||||
if (value === "minLatency")
|
||||
if (value === 'minLatency')
|
||||
props.updateTraceFilters({
|
||||
...props.traceFilters,
|
||||
latency: { min: "", max: props.traceFilters.latency?.max },
|
||||
latency: { min: '', max: props.traceFilters.latency?.max },
|
||||
});
|
||||
}
|
||||
|
||||
@ -47,69 +46,69 @@ const _FilterStateDisplay = (props: FilterStateDisplayProps) => {
|
||||
style={{ padding: 6, marginTop: 10, marginBottom: 10 }}
|
||||
bodyStyle={{ padding: 6 }}
|
||||
>
|
||||
{props.traceFilters.service === "" ||
|
||||
{props.traceFilters.service === '' ||
|
||||
props.traceFilters.operation === undefined ? null : (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag("service");
|
||||
}}
|
||||
>
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag('service');
|
||||
}}
|
||||
>
|
||||
service:{props.traceFilters.service}
|
||||
</Tag>
|
||||
)}
|
||||
{props.traceFilters.operation === "" ||
|
||||
</Tag>
|
||||
)}
|
||||
{props.traceFilters.operation === '' ||
|
||||
props.traceFilters.operation === undefined ? null : (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag("operation");
|
||||
}}
|
||||
>
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag('operation');
|
||||
}}
|
||||
>
|
||||
operation:{props.traceFilters.operation}
|
||||
</Tag>
|
||||
)}
|
||||
</Tag>
|
||||
)}
|
||||
{props.traceFilters.latency === undefined ||
|
||||
props.traceFilters.latency?.min === "" ? null : (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag("minLatency");
|
||||
}}
|
||||
>
|
||||
props.traceFilters.latency?.min === '' ? null : (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag('minLatency');
|
||||
}}
|
||||
>
|
||||
minLatency:
|
||||
{(parseInt(props.traceFilters.latency!.min) / 1000000).toString()}ms
|
||||
</Tag>
|
||||
)}
|
||||
{(parseInt(props.traceFilters.latency!.min) / 1000000).toString()}ms
|
||||
</Tag>
|
||||
)}
|
||||
{props.traceFilters.latency === undefined ||
|
||||
props.traceFilters.latency?.max === "" ? null : (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag("maxLatency");
|
||||
}}
|
||||
>
|
||||
props.traceFilters.latency?.max === '' ? null : (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
onClose={(e) => {
|
||||
handleCloseTag('maxLatency');
|
||||
}}
|
||||
>
|
||||
maxLatency:
|
||||
{(parseInt(props.traceFilters.latency!.max) / 1000000).toString()}ms
|
||||
</Tag>
|
||||
)}
|
||||
{(parseInt(props.traceFilters.latency!.max) / 1000000).toString()}ms
|
||||
</Tag>
|
||||
)}
|
||||
{props.traceFilters.tags === undefined
|
||||
? null
|
||||
: props.traceFilters.tags.map((item) => (
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
key={`${item.key}-${item.operator}-${item.value}`}
|
||||
onClose={(e) => {
|
||||
handleCloseTagElement(item);
|
||||
}}
|
||||
>
|
||||
{item.key} {item.operator} {item.value}
|
||||
</Tag>
|
||||
<Tag
|
||||
style={{ fontSize: 14, padding: 8 }}
|
||||
closable
|
||||
key={`${item.key}-${item.operator}-${item.value}`}
|
||||
onClose={(e) => {
|
||||
handleCloseTagElement(item);
|
||||
}}
|
||||
>
|
||||
{item.key} {item.operator} {item.value}
|
||||
</Tag>
|
||||
))}
|
||||
</Card>
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { Modal, Form, InputNumber, Col, Row } from "antd";
|
||||
import { NamePath, Store } from "antd/lib/form/interface";
|
||||
import { Col, Form, InputNumber, Modal, Row } from 'antd';
|
||||
import { NamePath, Store } from 'antd/lib/form/interface';
|
||||
import React from 'react';
|
||||
|
||||
interface LatencyModalFormProps {
|
||||
onCreate: (values: Store) => void; //Store is defined in antd forms library
|
||||
@ -13,32 +13,42 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
onCancel,
|
||||
latencyFilterValues,
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const validateMinValue = ({ getFieldValue }: {getFieldValue: (name: NamePath) => any}) => ({
|
||||
validator(_, value: any) {
|
||||
if (value < getFieldValue('max')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(new Error('Min value should be less than Max value'));
|
||||
},
|
||||
})
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const validateMaxValue = ({ getFieldValue }: {getFieldValue: (name: NamePath) => any}) => ({
|
||||
const validateMinValue = ({
|
||||
getFieldValue,
|
||||
}: {
|
||||
getFieldValue: (name: NamePath) => any;
|
||||
}) => ({
|
||||
validator(_, value: any) {
|
||||
if (value > getFieldValue('min')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(new Error('Max value should be greater than Min value'));
|
||||
if (value < getFieldValue('max')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(new Error('Min value should be less than Max value'));
|
||||
},
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
const validateMaxValue = ({
|
||||
getFieldValue,
|
||||
}: {
|
||||
getFieldValue: (name: NamePath) => any;
|
||||
}) => ({
|
||||
validator(_, value: any) {
|
||||
if (value > getFieldValue('min')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(
|
||||
new Error('Max value should be greater than Min value'),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
title="Chose min and max values of Latency"
|
||||
okText="Apply"
|
||||
cancelText="Cancel"
|
||||
cancelText="Cancel"
|
||||
onCancel={onCancel}
|
||||
onOk={() => {
|
||||
form
|
||||
@ -48,9 +58,9 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
onCreate(values); // giving error for values
|
||||
})
|
||||
.catch((info) => {
|
||||
console.log("Validate Failed:", info);
|
||||
console.log('Validate Failed:', info);
|
||||
});
|
||||
}}
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
@ -63,7 +73,7 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="min"
|
||||
label="Min (in ms)"
|
||||
label="Min (in ms)"
|
||||
rules={[validateMinValue]}
|
||||
// rules={[{ required: true, message: 'Please input the title of collection!' }]}
|
||||
>
|
||||
@ -71,11 +81,7 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="max"
|
||||
label="Max (in ms)"
|
||||
rules = {[validateMaxValue]}
|
||||
>
|
||||
<Form.Item name="max" label="Max (in ms)" rules={[validateMaxValue]}>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { Card, Space, Tabs, Typography } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { pushDStree } from "store/actions";
|
||||
import { Card, Space, Tabs, Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import { pushDStree } from 'store/actions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
@ -56,15 +56,15 @@ const CardContainer = styled(Card)`
|
||||
|
||||
const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
const spanTags = props.data?.tags;
|
||||
const service = props.data?.name?.split(":")[0];
|
||||
const operation = props.data?.name?.split(":")[1];
|
||||
const service = props.data?.name?.split(':')[0];
|
||||
const operation = props.data?.name?.split(':')[1];
|
||||
|
||||
return (
|
||||
<CardContainer>
|
||||
<Space direction="vertical">
|
||||
<strong> Details for selected Span </strong>
|
||||
<Space direction="vertical" size={2}>
|
||||
<CustomTitle style={{ marginTop: "18px" }}>Service</CustomTitle>
|
||||
<CustomTitle style={{ marginTop: '18px' }}>Service</CustomTitle>
|
||||
<CustomText>{service}</CustomText>
|
||||
</Space>
|
||||
<Space direction="vertical" size={2}>
|
||||
@ -82,7 +82,7 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
<>
|
||||
<CustomSubTitle>{tags.key}</CustomSubTitle>
|
||||
<CustomSubText>
|
||||
{tags.key === "error" ? "true" : tags.value}
|
||||
{tags.key === 'error' ? 'true' : tags.value}
|
||||
</CustomSubText>
|
||||
</>
|
||||
)}
|
||||
@ -93,7 +93,7 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
<TabPane tab="Errors" key="2">
|
||||
{spanTags &&
|
||||
spanTags
|
||||
.filter((tags) => tags.key === "error")
|
||||
.filter((tags) => tags.key === 'error')
|
||||
.map((error) => (
|
||||
<>
|
||||
<CustomSubTitle>{error.key}</CustomSubTitle>
|
||||
|
@ -1,68 +1,68 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import GenericVisualizations from "modules/Metrics/GenericVisualization";
|
||||
import { Select, Card, Space, Form } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { GlobalTime, TraceFilters } from "store/actions";
|
||||
import { useRoute } from "modules/RouteProvider";
|
||||
import { getFilteredTraceMetrics } from "store/actions/MetricsActions";
|
||||
import { customMetricsItem } from "store/actions/MetricsActions";
|
||||
import { Card, Form,Select, Space } from 'antd';
|
||||
import GenericVisualizations from 'modules/Metrics/GenericVisualization';
|
||||
import { useRoute } from 'modules/RouteProvider';
|
||||
import React, { useEffect,useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { GlobalTime, TraceFilters } from 'store/actions';
|
||||
import { getFilteredTraceMetrics } from 'store/actions/MetricsActions';
|
||||
import { customMetricsItem } from 'store/actions/MetricsActions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
const { Option } = Select;
|
||||
|
||||
const entity = [
|
||||
{
|
||||
title: "Calls",
|
||||
key: "calls",
|
||||
dataindex: "calls",
|
||||
title: 'Calls',
|
||||
key: 'calls',
|
||||
dataindex: 'calls',
|
||||
},
|
||||
{
|
||||
title: "Duration",
|
||||
key: "duration",
|
||||
dataindex: "duration",
|
||||
title: 'Duration',
|
||||
key: 'duration',
|
||||
dataindex: 'duration',
|
||||
},
|
||||
{
|
||||
title: "Error",
|
||||
key: "error",
|
||||
dataindex: "error",
|
||||
title: 'Error',
|
||||
key: 'error',
|
||||
dataindex: 'error',
|
||||
},
|
||||
{
|
||||
title: "Status Code",
|
||||
key: "status_code",
|
||||
dataindex: "status_code",
|
||||
title: 'Status Code',
|
||||
key: 'status_code',
|
||||
dataindex: 'status_code',
|
||||
},
|
||||
];
|
||||
|
||||
const aggregation_options = [
|
||||
{
|
||||
linked_entity: "calls",
|
||||
default_selected: { title: "Count", dataindex: "count" },
|
||||
linked_entity: 'calls',
|
||||
default_selected: { title: 'Count', dataindex: 'count' },
|
||||
options_available: [
|
||||
{ title: "Count", dataindex: "count" },
|
||||
{ title: "Rate (per sec)", dataindex: "rate_per_sec" },
|
||||
{ title: 'Count', dataindex: 'count' },
|
||||
{ title: 'Rate (per sec)', dataindex: 'rate_per_sec' },
|
||||
],
|
||||
},
|
||||
{
|
||||
linked_entity: "duration",
|
||||
default_selected: { title: "p99", dataindex: "p99" },
|
||||
linked_entity: 'duration',
|
||||
default_selected: { title: 'p99', dataindex: 'p99' },
|
||||
// options_available: [ {title:'Avg', dataindex:'avg'}, {title:'Max', dataindex:'max'},{title:'Min', dataindex:'min'}, {title:'p50', dataindex:'p50'},{title:'p95', dataindex:'p95'}, {title:'p95', dataindex:'p95'}]
|
||||
options_available: [
|
||||
{ title: "p50", dataindex: "p50" },
|
||||
{ title: "p95", dataindex: "p95" },
|
||||
{ title: "p99", dataindex: "p99" },
|
||||
{ title: 'p50', dataindex: 'p50' },
|
||||
{ title: 'p95', dataindex: 'p95' },
|
||||
{ title: 'p99', dataindex: 'p99' },
|
||||
],
|
||||
},
|
||||
{
|
||||
linked_entity: "error",
|
||||
default_selected: { title: "Count", dataindex: "count" },
|
||||
linked_entity: 'error',
|
||||
default_selected: { title: 'Count', dataindex: 'count' },
|
||||
options_available: [
|
||||
{ title: "Count", dataindex: "count" },
|
||||
{ title: "Rate (per sec)", dataindex: "rate_per_sec" },
|
||||
{ title: 'Count', dataindex: 'count' },
|
||||
{ title: 'Rate (per sec)', dataindex: 'rate_per_sec' },
|
||||
],
|
||||
},
|
||||
{
|
||||
linked_entity: "status_code",
|
||||
default_selected: { title: "Count", dataindex: "count" },
|
||||
options_available: [{ title: "Count", dataindex: "count" }],
|
||||
linked_entity: 'status_code',
|
||||
default_selected: { title: 'Count', dataindex: 'count' },
|
||||
options_available: [{ title: 'Count', dataindex: 'count' }],
|
||||
},
|
||||
];
|
||||
|
||||
@ -74,38 +74,38 @@ interface TraceCustomVisualizationsProps {
|
||||
}
|
||||
|
||||
const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
const [selectedEntity, setSelectedEntity] = useState("calls");
|
||||
const [selectedAggOption, setSelectedAggOption] = useState("count");
|
||||
const [selectedEntity, setSelectedEntity] = useState('calls');
|
||||
const [selectedAggOption, setSelectedAggOption] = useState('count');
|
||||
const { state } = useRoute();
|
||||
const [form] = Form.useForm();
|
||||
const selectedStep = "60";
|
||||
const selectedStep = '60';
|
||||
|
||||
// Step should be multiples of 60, 60 -> 1 min
|
||||
|
||||
useEffect(() => {
|
||||
let request_string =
|
||||
"service=" +
|
||||
'service=' +
|
||||
props.traceFilters.service +
|
||||
"&operation=" +
|
||||
'&operation=' +
|
||||
props.traceFilters.operation +
|
||||
"&maxDuration=" +
|
||||
'&maxDuration=' +
|
||||
props.traceFilters.latency?.max +
|
||||
"&minDuration=" +
|
||||
'&minDuration=' +
|
||||
props.traceFilters.latency?.min +
|
||||
"&kind=" +
|
||||
'&kind=' +
|
||||
props.traceFilters.kind;
|
||||
if (props.traceFilters.tags)
|
||||
request_string =
|
||||
request_string +
|
||||
"&tags=" +
|
||||
'&tags=' +
|
||||
encodeURIComponent(JSON.stringify(props.traceFilters.tags));
|
||||
if (selectedEntity)
|
||||
request_string =
|
||||
request_string + "&dimension=" + selectedEntity.toLowerCase();
|
||||
request_string + '&dimension=' + selectedEntity.toLowerCase();
|
||||
if (selectedAggOption)
|
||||
request_string =
|
||||
request_string + "&aggregation_option=" + selectedAggOption.toLowerCase();
|
||||
if (selectedStep) request_string = request_string + "&step=" + selectedStep;
|
||||
request_string + '&aggregation_option=' + selectedAggOption.toLowerCase();
|
||||
if (selectedStep) request_string = request_string + '&step=' + selectedStep;
|
||||
const plusMinus15 = {
|
||||
minTime: props.globalTime.minTime - 15 * 60 * 1000000000,
|
||||
maxTime: props.globalTime.maxTime + 15 * 60 * 1000000000,
|
||||
@ -125,7 +125,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
// PNOTE - Can also use 'coordinate' option in antd Select for implementing this - https://ant.design/components/select/
|
||||
const handleFormValuesChange = (changedValues: any) => {
|
||||
const formFieldName = Object.keys(changedValues)[0];
|
||||
if (formFieldName === "entity") {
|
||||
if (formFieldName === 'entity') {
|
||||
const temp_entity = aggregation_options.filter(
|
||||
(item) => item.linked_entity === changedValues[formFieldName],
|
||||
)[0];
|
||||
@ -135,7 +135,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
// PNOTE - TO DO Check if this has the same behaviour as selecting an option?
|
||||
});
|
||||
|
||||
let temp = form.getFieldsValue(["agg_options", "entity"]);
|
||||
const temp = form.getFieldsValue(['agg_options', 'entity']);
|
||||
|
||||
setSelectedEntity(temp.entity);
|
||||
setSelectedAggOption(temp.agg_options);
|
||||
@ -143,7 +143,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
// PNOTE - https://stackoverflow.com/questions/64377293/update-select-option-list-based-on-other-select-field-selection-ant-design
|
||||
}
|
||||
|
||||
if (formFieldName === "agg_options") {
|
||||
if (formFieldName === 'agg_options') {
|
||||
setSelectedAggOption(changedValues[formFieldName]);
|
||||
}
|
||||
};
|
||||
@ -155,10 +155,10 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
form={form}
|
||||
onValuesChange={handleFormValuesChange}
|
||||
initialValues={{
|
||||
agg_options: "Count",
|
||||
chart_style: "line",
|
||||
interval: "5m",
|
||||
group_by: "none",
|
||||
agg_options: 'Count',
|
||||
chart_style: 'line',
|
||||
interval: '5m',
|
||||
group_by: 'none',
|
||||
}}
|
||||
>
|
||||
<Space>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React from "react";
|
||||
import { TraceCustomVisualizations } from "./TraceCustomVisualizations";
|
||||
import { TraceFilter } from "./TraceFilter";
|
||||
import { TraceList } from "./TraceList";
|
||||
import React from 'react';
|
||||
|
||||
import { TraceCustomVisualizations } from './TraceCustomVisualizations';
|
||||
import { TraceFilter } from './TraceFilter';
|
||||
import { TraceList } from './TraceList';
|
||||
|
||||
const TraceDetail = () => {
|
||||
return (
|
||||
|
@ -1,24 +1,23 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Select, Button, Input, Form, AutoComplete } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { Store } from "antd/lib/form/interface";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { AutoComplete,Button, Form, Input, Select } from 'antd';
|
||||
import FormItem from 'antd/lib/form/FormItem';
|
||||
import { Store } from 'antd/lib/form/interface';
|
||||
import api, { apiV1 } from 'api';
|
||||
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
||||
import { useRoute } from 'modules/RouteProvider';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import {
|
||||
updateTraceFilters,
|
||||
fetchTraces,
|
||||
TraceFilters,
|
||||
GlobalTime,
|
||||
} from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import LatencyModalForm from "./LatencyModalForm";
|
||||
import { FilterStateDisplay } from "./FilterStateDisplay";
|
||||
TraceFilters,
|
||||
updateTraceFilters,
|
||||
} from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import FormItem from "antd/lib/form/FormItem";
|
||||
import api, { apiV1 } from "api";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "constants/query";
|
||||
import { useRoute } from "modules/RouteProvider";
|
||||
import { FilterStateDisplay } from './FilterStateDisplay';
|
||||
import LatencyModalForm from './LatencyModalForm';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -41,7 +40,7 @@ interface TagKeyOptionItem {
|
||||
}
|
||||
|
||||
interface ISpanKind {
|
||||
label: "SERVER" | "CLIENT";
|
||||
label: 'SERVER' | 'CLIENT';
|
||||
value: string;
|
||||
}
|
||||
|
||||
@ -50,27 +49,27 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
const [operationList, setOperationsList] = useState<string[]>([]);
|
||||
const [tagKeyOptions, setTagKeyOptions] = useState<TagKeyOptionItem[]>([]);
|
||||
const location = useLocation();
|
||||
const urlParams = new URLSearchParams(location.search.split("?")[1]);
|
||||
const urlParams = new URLSearchParams(location.search.split('?')[1]);
|
||||
const { state } = useRoute();
|
||||
|
||||
const spanKindList: ISpanKind[] = [
|
||||
{
|
||||
label: "SERVER",
|
||||
value: "2",
|
||||
label: 'SERVER',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: "CLIENT",
|
||||
value: "3",
|
||||
label: 'CLIENT',
|
||||
value: '3',
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
handleApplyFilterForm({
|
||||
service: "",
|
||||
service: '',
|
||||
tags: [],
|
||||
operation: "",
|
||||
latency: { min: "", max: "" },
|
||||
kind: "",
|
||||
operation: '',
|
||||
latency: { min: '', max: '' },
|
||||
kind: '',
|
||||
});
|
||||
}, []);
|
||||
|
||||
@ -93,7 +92,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
...props.traceFilters,
|
||||
operation: operationName,
|
||||
service: serviceName,
|
||||
kind: "",
|
||||
kind: '',
|
||||
});
|
||||
populateData(serviceName);
|
||||
} else if (serviceName && errorTag) {
|
||||
@ -104,10 +103,10 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
{
|
||||
key: METRICS_PAGE_QUERY_PARAM.error,
|
||||
value: errorTag,
|
||||
operator: "equals",
|
||||
operator: 'equals',
|
||||
},
|
||||
],
|
||||
kind: "",
|
||||
kind: '',
|
||||
});
|
||||
} else {
|
||||
if (operationName) {
|
||||
@ -120,7 +119,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
onTagFormSubmit({
|
||||
tag_key: METRICS_PAGE_QUERY_PARAM.error,
|
||||
tag_value: errorTag,
|
||||
operator: "equals",
|
||||
operator: 'equals',
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -129,20 +128,20 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
let request_string =
|
||||
"service=" +
|
||||
'service=' +
|
||||
props.traceFilters.service +
|
||||
"&operation=" +
|
||||
'&operation=' +
|
||||
props.traceFilters.operation +
|
||||
"&maxDuration=" +
|
||||
'&maxDuration=' +
|
||||
props.traceFilters.latency?.max +
|
||||
"&minDuration=" +
|
||||
'&minDuration=' +
|
||||
props.traceFilters.latency?.min +
|
||||
"&kind=" +
|
||||
'&kind=' +
|
||||
props.traceFilters.kind;
|
||||
if (props.traceFilters.tags)
|
||||
request_string =
|
||||
request_string +
|
||||
"&tags=" +
|
||||
'&tags=' +
|
||||
encodeURIComponent(JSON.stringify(props.traceFilters.tags));
|
||||
|
||||
/*
|
||||
@ -155,33 +154,33 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}, [props.traceFilters, props.globalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
let latencyButtonText = "Latency";
|
||||
let latencyButtonText = 'Latency';
|
||||
if (
|
||||
props.traceFilters.latency?.min === "" &&
|
||||
props.traceFilters.latency?.max !== ""
|
||||
props.traceFilters.latency?.min === '' &&
|
||||
props.traceFilters.latency?.max !== ''
|
||||
)
|
||||
latencyButtonText =
|
||||
"Latency<" +
|
||||
'Latency<' +
|
||||
(parseInt(props.traceFilters.latency?.max) / 1000000).toString() +
|
||||
"ms";
|
||||
'ms';
|
||||
else if (
|
||||
props.traceFilters.latency?.min !== "" &&
|
||||
props.traceFilters.latency?.max === ""
|
||||
props.traceFilters.latency?.min !== '' &&
|
||||
props.traceFilters.latency?.max === ''
|
||||
)
|
||||
latencyButtonText =
|
||||
"Latency>" +
|
||||
'Latency>' +
|
||||
(parseInt(props.traceFilters.latency?.min) / 1000000).toString() +
|
||||
"ms";
|
||||
'ms';
|
||||
else if (
|
||||
props.traceFilters.latency !== undefined &&
|
||||
props.traceFilters.latency?.min !== "" &&
|
||||
props.traceFilters.latency?.max !== ""
|
||||
props.traceFilters.latency?.min !== '' &&
|
||||
props.traceFilters.latency?.max !== ''
|
||||
)
|
||||
latencyButtonText =
|
||||
(parseInt(props.traceFilters.latency.min) / 1000000).toString() +
|
||||
"ms <Latency<" +
|
||||
'ms <Latency<' +
|
||||
(parseInt(props.traceFilters.latency.max) / 1000000).toString() +
|
||||
"ms";
|
||||
'ms';
|
||||
|
||||
form_basefilter.setFieldsValue({ latency: latencyButtonText });
|
||||
}, [props.traceFilters.latency]);
|
||||
@ -201,13 +200,13 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [loading] = useState(false);
|
||||
|
||||
const [tagKeyValueApplied, setTagKeyValueApplied] = useState([""]);
|
||||
const [tagKeyValueApplied, setTagKeyValueApplied] = useState(['']);
|
||||
const [latencyFilterValues, setLatencyFilterValues] = useState<{
|
||||
min: string;
|
||||
max: string;
|
||||
}>({
|
||||
min: "100",
|
||||
max: "500",
|
||||
min: '100',
|
||||
max: '500',
|
||||
});
|
||||
|
||||
const [form] = Form.useForm();
|
||||
@ -219,13 +218,13 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
}
|
||||
|
||||
function populateData(value: string) {
|
||||
let service_request = "/service/" + value + "/operations";
|
||||
const service_request = '/service/' + value + '/operations';
|
||||
api.get<string[]>(apiV1 + service_request).then((response) => {
|
||||
// form_basefilter.resetFields(['operation',])
|
||||
setOperationsList(response.data);
|
||||
});
|
||||
|
||||
let tagkeyoptions_request = "/tags?service=" + value;
|
||||
const tagkeyoptions_request = '/tags?service=' + value;
|
||||
api
|
||||
.get<TagKeyOptionItem[]>(apiV1 + tagkeyoptions_request)
|
||||
.then((response) => {
|
||||
@ -247,8 +246,8 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
props.updateTraceFilters({
|
||||
...props.traceFilters,
|
||||
latency: {
|
||||
min: min ? (parseInt(min) * 1000000).toString() : "",
|
||||
max: max ? (parseInt(max) * 1000000).toString() : "",
|
||||
min: min ? (parseInt(min) * 1000000).toString() : '',
|
||||
max: max ? (parseInt(max) * 1000000).toString() : '',
|
||||
},
|
||||
});
|
||||
|
||||
@ -256,8 +255,8 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
};
|
||||
|
||||
const onTagFormSubmit = (values: any) => {
|
||||
let request_tags =
|
||||
"service=frontend&tags=" +
|
||||
const request_tags =
|
||||
'service=frontend&tags=' +
|
||||
encodeURIComponent(
|
||||
JSON.stringify([
|
||||
{
|
||||
@ -309,7 +308,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
form.setFieldsValue({ tag_key: data });
|
||||
};
|
||||
|
||||
const dataSource = ["status:200"];
|
||||
const dataSource = ['status:200'];
|
||||
const children = [];
|
||||
for (let i = 0; i < dataSource.length; i++) {
|
||||
children.push(
|
||||
@ -321,45 +320,45 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
// PNOTE - Remove any
|
||||
const handleApplyFilterForm = (values: any) => {
|
||||
let request_params: string = "";
|
||||
let request_params = '';
|
||||
if (
|
||||
typeof values.service !== undefined &&
|
||||
typeof values.operation !== undefined
|
||||
) {
|
||||
request_params =
|
||||
"service=" + values.service + "&operation=" + values.operation;
|
||||
'service=' + values.service + '&operation=' + values.operation;
|
||||
} else if (
|
||||
typeof values.service === undefined &&
|
||||
typeof values.operation !== undefined
|
||||
) {
|
||||
request_params = "operation=" + values.operation;
|
||||
request_params = 'operation=' + values.operation;
|
||||
} else if (
|
||||
typeof values.service !== undefined &&
|
||||
typeof values.operation === undefined
|
||||
) {
|
||||
request_params = "service=" + values.service;
|
||||
request_params = 'service=' + values.service;
|
||||
}
|
||||
|
||||
request_params =
|
||||
request_params +
|
||||
"&minDuration=" +
|
||||
'&minDuration=' +
|
||||
latencyFilterValues.min +
|
||||
"&maxDuration=" +
|
||||
'&maxDuration=' +
|
||||
latencyFilterValues.max;
|
||||
|
||||
setTagKeyValueApplied((tagKeyValueApplied) => [
|
||||
...tagKeyValueApplied,
|
||||
"service eq" + values.service,
|
||||
"operation eq " + values.operation,
|
||||
"maxduration eq " + (parseInt(latencyFilterValues.max) / 1000000).toString(),
|
||||
"minduration eq " + (parseInt(latencyFilterValues.min) / 1000000).toString(),
|
||||
'service eq' + values.service,
|
||||
'operation eq ' + values.operation,
|
||||
'maxduration eq ' + (parseInt(latencyFilterValues.max) / 1000000).toString(),
|
||||
'minduration eq ' + (parseInt(latencyFilterValues.min) / 1000000).toString(),
|
||||
]);
|
||||
props.updateTraceFilters({
|
||||
service: values.service,
|
||||
operation: values.operation,
|
||||
latency: {
|
||||
max: "",
|
||||
min: "",
|
||||
max: '',
|
||||
min: '',
|
||||
},
|
||||
kind: values.kind,
|
||||
});
|
||||
@ -368,16 +367,16 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
props.updateTraceFilters({
|
||||
service: "",
|
||||
operation: "",
|
||||
service: '',
|
||||
operation: '',
|
||||
tags: [],
|
||||
latency: { min: "", max: "" },
|
||||
kind: "",
|
||||
latency: { min: '', max: '' },
|
||||
kind: '',
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleChangeSpanKind = (value: string = "") => {
|
||||
const handleChangeSpanKind = (value = '') => {
|
||||
props.updateTraceFilters({ ...props.traceFilters, kind: value });
|
||||
};
|
||||
|
||||
@ -390,7 +389,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
form={form_basefilter}
|
||||
layout="inline"
|
||||
onFinish={handleApplyFilterForm}
|
||||
initialValues={{ service: "", operation: "", latency: "Latency" }}
|
||||
initialValues={{ service: '', operation: '', latency: 'Latency' }}
|
||||
style={{ marginTop: 10, marginBottom: 10 }}
|
||||
>
|
||||
<FormItem rules={[{ required: true }]} name="service">
|
||||
@ -460,7 +459,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
form={form}
|
||||
layout="inline"
|
||||
onFinish={onTagFormSubmit}
|
||||
initialValues={{ operator: "equals" }}
|
||||
initialValues={{ operator: 'equals' }}
|
||||
style={{ marginTop: 10, marginBottom: 10 }}
|
||||
>
|
||||
<FormItem rules={[{ required: true }]} name="tag_key">
|
||||
@ -468,7 +467,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
options={tagKeyOptions.map((s) => {
|
||||
return { value: s.tagKeys };
|
||||
})}
|
||||
style={{ width: 200, textAlign: "center" }}
|
||||
style={{ width: 200, textAlign: 'center' }}
|
||||
// onSelect={onSelect}
|
||||
// onSearch={onSearch}
|
||||
onChange={onChangeTagKey}
|
||||
@ -480,7 +479,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
</FormItem>
|
||||
|
||||
<FormItem name="operator">
|
||||
<Select style={{ width: 120, textAlign: "center" }}>
|
||||
<Select style={{ width: 120, textAlign: 'center' }}>
|
||||
<Option value="equals">EQUAL</Option>
|
||||
<Option value="contains">CONTAINS</Option>
|
||||
<Option value="regex">REGEX</Option>
|
||||
@ -489,15 +488,15 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
|
||||
<FormItem rules={[{ required: true }]} name="tag_value">
|
||||
<Input
|
||||
style={{ width: 160, textAlign: "center" }}
|
||||
style={{ width: 160, textAlign: 'center' }}
|
||||
placeholder="Tag Value"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem>
|
||||
<Button type="primary" htmlType="submit">
|
||||
{" "}
|
||||
Apply Tag Filter{" "}
|
||||
{' '}
|
||||
Apply Tag Filter{' '}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { Table, Progress, Tabs, Button, Row, Col } from "antd";
|
||||
import "./TraceGanttChart.css";
|
||||
import { max, isEmpty, has } from "lodash-es";
|
||||
import styled from "styled-components";
|
||||
import { pushDStree } from "store/actions";
|
||||
import traverseTreeData from "modules/Traces/TraceGanttChart/TraceGanttChartHelpers";
|
||||
import './TraceGanttChart.css';
|
||||
|
||||
import { Button, Col,Progress, Row, Table, Tabs } from 'antd';
|
||||
import { has,isEmpty, max } from 'lodash-es';
|
||||
import traverseTreeData from 'modules/Traces/TraceGanttChart/TraceGanttChartHelpers';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { pushDStree } from 'store/actions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
@ -31,28 +32,28 @@ const TraceGanttChart = ({
|
||||
resetZoom,
|
||||
setSpanTagsInfo,
|
||||
}: TraceGanttChartProps) => {
|
||||
let checkStrictly = true;
|
||||
const checkStrictly = true;
|
||||
const [selectedRows, setSelectedRows] = useState<string[]>([]);
|
||||
const [clickedSpanData, setClickedSpanData] = useState(clickedSpan);
|
||||
const [defaultExpandedRows, setDefaultExpandedRows] = useState<string[]>([]);
|
||||
const [sortedTreeData, setSortedTreeData] = useState(treeData);
|
||||
const [isReset, setIsReset] = useState(false);
|
||||
const [tabsContainerWidth, setTabsContainerWidth] = useState(0);
|
||||
const tableRef = useRef("");
|
||||
let tabsContainer = document.querySelector<HTMLElement>(
|
||||
"#collapsable .ant-tabs-nav-list",
|
||||
const tableRef = useRef('');
|
||||
const tabsContainer = document.querySelector<HTMLElement>(
|
||||
'#collapsable .ant-tabs-nav-list',
|
||||
);
|
||||
|
||||
let tabs = document.querySelectorAll("#collapsable .ant-tabs-tab");
|
||||
const tabs = document.querySelectorAll('#collapsable .ant-tabs-tab');
|
||||
|
||||
const { id } = treeData || "id";
|
||||
const { id } = treeData || 'id';
|
||||
let maxGlobal = 0;
|
||||
let minGlobal = 0;
|
||||
let medianGlobal = 0;
|
||||
let endTimeArray: [] = [];
|
||||
const endTimeArray: [] = [];
|
||||
|
||||
useEffect(() => {
|
||||
if (id !== "empty") {
|
||||
if (id !== 'empty') {
|
||||
setSortedTreeData(treeData);
|
||||
if (clickedSpan) {
|
||||
setClickedSpanData(clickedSpan);
|
||||
@ -73,22 +74,22 @@ const TraceGanttChart = ({
|
||||
) {
|
||||
setSelectedRows([clickedSpan.id]);
|
||||
getParentKeys(clickedSpan);
|
||||
handleFocusOnSelectedPath("", [clickedSpan.id]);
|
||||
handleFocusOnSelectedPath('', [clickedSpan.id]);
|
||||
}
|
||||
}, [clickedSpan, selectedRows, isReset, clickedSpanData]);
|
||||
|
||||
let parentKeys: string[] = [];
|
||||
let childrenKeys: string[] = [];
|
||||
const parentKeys: string[] = [];
|
||||
const childrenKeys: string[] = [];
|
||||
|
||||
const getParentKeys = (obj) => {
|
||||
if (has(obj, "parent")) {
|
||||
if (has(obj, 'parent')) {
|
||||
parentKeys.push(obj.parent.id);
|
||||
getParentKeys(obj.parent);
|
||||
}
|
||||
};
|
||||
|
||||
const getChildrenKeys = (obj: pushDStree) => {
|
||||
if (has(obj, "children")) {
|
||||
if (has(obj, 'children')) {
|
||||
childrenKeys.push(obj.id);
|
||||
if (!isEmpty(obj.children)) {
|
||||
obj.children.map((item) => {
|
||||
@ -101,7 +102,7 @@ const TraceGanttChart = ({
|
||||
useEffect(() => {
|
||||
if (!isEmpty(selectedSpan) && isEmpty(clickedSpan)) {
|
||||
getParentKeys(selectedSpan);
|
||||
let keys = [selectedSpan?.id, ...parentKeys];
|
||||
const keys = [selectedSpan?.id, ...parentKeys];
|
||||
setDefaultExpandedRows(keys);
|
||||
setSelectedRows([selectedSpan.id, clickedSpan]);
|
||||
// setSpanTagsInfo({data: selectedSpan})
|
||||
@ -114,7 +115,7 @@ const TraceGanttChart = ({
|
||||
|
||||
const getMaxEndTime = (treeData) => {
|
||||
if (treeData.length > 0) {
|
||||
if (treeData?.id !== "empty") {
|
||||
if (treeData?.id !== 'empty') {
|
||||
return Array.from(treeData).map((item, key) => {
|
||||
if (!isEmpty(item.children)) {
|
||||
endTimeArray.push(item.time / 1000000 + item.startTime);
|
||||
@ -127,7 +128,7 @@ const TraceGanttChart = ({
|
||||
}
|
||||
};
|
||||
|
||||
if (id !== "empty") {
|
||||
if (id !== 'empty') {
|
||||
getMaxEndTime(treeData);
|
||||
maxGlobal = max(endTimeArray);
|
||||
minGlobal = treeData?.[0]?.startTime;
|
||||
@ -143,28 +144,28 @@ const TraceGanttChart = ({
|
||||
return ((timeDiff / totalTime) * totalWidth).toFixed(0);
|
||||
};
|
||||
|
||||
let tabMinVal = 0;
|
||||
let tabMedianVal = (medianGlobal - minGlobal).toFixed(0);
|
||||
let tabMaxVal = (maxGlobal - minGlobal).toFixed(0);
|
||||
const tabMinVal = 0;
|
||||
const tabMedianVal = (medianGlobal - minGlobal).toFixed(0);
|
||||
const tabMaxVal = (maxGlobal - minGlobal).toFixed(0);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
title: '',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<Tabs>
|
||||
<TabPane tab={tabMinVal + "ms"} key="1" />
|
||||
<TabPane tab={tabMedianVal + "ms"} key="2" />
|
||||
<TabPane tab={tabMaxVal + "ms"} key="3" />
|
||||
<TabPane tab={tabMinVal + 'ms'} key="1" />
|
||||
<TabPane tab={tabMedianVal + 'ms'} key="2" />
|
||||
<TabPane tab={tabMaxVal + 'ms'} key="3" />
|
||||
</Tabs>
|
||||
),
|
||||
dataIndex: "trace",
|
||||
name: "trace",
|
||||
dataIndex: 'trace',
|
||||
name: 'trace',
|
||||
render: (_, record: pushDStree) => {
|
||||
let widths = [];
|
||||
const widths = [];
|
||||
let length;
|
||||
|
||||
if (widths.length < tabs.length) {
|
||||
@ -174,8 +175,8 @@ const TraceGanttChart = ({
|
||||
}
|
||||
|
||||
let paddingLeft = 0;
|
||||
let startTime = parseFloat(record.startTime.toString());
|
||||
let duration = parseFloat((record.time / 1000000).toFixed(2));
|
||||
const startTime = parseFloat(record.startTime.toString());
|
||||
const duration = parseFloat((record.time / 1000000).toFixed(2));
|
||||
paddingLeft = parseInt(
|
||||
getPaddingLeft(
|
||||
startTime - minGlobal,
|
||||
@ -191,11 +192,11 @@ const TraceGanttChart = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ paddingLeft: textPadding + "px" }}>{duration}ms</div>
|
||||
<div style={{ paddingLeft: textPadding + 'px' }}>{duration}ms</div>
|
||||
<Progress
|
||||
percent={length}
|
||||
showInfo={false}
|
||||
style={{ paddingLeft: paddingLeft + "px" }}
|
||||
style={{ paddingLeft: paddingLeft + 'px' }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@ -208,8 +209,8 @@ const TraceGanttChart = ({
|
||||
// initializing the node
|
||||
let node: pushDStree = {
|
||||
children: [],
|
||||
id: "",
|
||||
name: "",
|
||||
id: '',
|
||||
name: '',
|
||||
startTime: 0,
|
||||
tags: [],
|
||||
time: 0,
|
||||
@ -226,7 +227,7 @@ const TraceGanttChart = ({
|
||||
setSpanTagsInfo({ data: node });
|
||||
} catch (e) {
|
||||
// TODO: error logging.
|
||||
console.error("Node not found in Tree Data.");
|
||||
console.error('Node not found in Tree Data.');
|
||||
}
|
||||
|
||||
// get the parent of the node
|
||||
@ -235,15 +236,15 @@ const TraceGanttChart = ({
|
||||
// get the children of the node
|
||||
getChildrenKeys(node);
|
||||
|
||||
let rows = document.querySelectorAll("#collapsable table tbody tr");
|
||||
const rows = document.querySelectorAll('#collapsable table tbody tr');
|
||||
rows.forEach((row) => {
|
||||
let attribKey = row.getAttribute("data-row-key") || "";
|
||||
const attribKey = row.getAttribute('data-row-key') || '';
|
||||
if (
|
||||
!isEmpty(attribKey) &&
|
||||
!selectedRowsList.includes(attribKey) &&
|
||||
!childrenKeys.includes(attribKey)
|
||||
) {
|
||||
row.classList.add("hide");
|
||||
row.classList.add('hide');
|
||||
}
|
||||
});
|
||||
setDefaultExpandedRows([...parentKeys, ...childrenKeys]);
|
||||
@ -251,9 +252,9 @@ const TraceGanttChart = ({
|
||||
};
|
||||
|
||||
const handleResetFocus = () => {
|
||||
const rows = document.querySelectorAll("#collapsable table tbody tr");
|
||||
const rows = document.querySelectorAll('#collapsable table tbody tr');
|
||||
rows.forEach((row) => {
|
||||
row.classList.remove("hide");
|
||||
row.classList.remove('hide');
|
||||
});
|
||||
|
||||
resetZoom(true);
|
||||
@ -296,7 +297,7 @@ const TraceGanttChart = ({
|
||||
setSpanTagsInfo({ data: node });
|
||||
} catch (e) {
|
||||
// TODO: error logging.
|
||||
console.error("Node not found in TreeData.");
|
||||
console.error('Node not found in TreeData.');
|
||||
}
|
||||
|
||||
const selectedRowKeys = selectedRows;
|
||||
@ -314,13 +315,13 @@ const TraceGanttChart = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
{id !== "empty" && (
|
||||
{id !== 'empty' && (
|
||||
<>
|
||||
<Row
|
||||
justify="end"
|
||||
gutter={32}
|
||||
style={{
|
||||
marginBottom: "24px",
|
||||
marginBottom: '24px',
|
||||
}}
|
||||
>
|
||||
<Col>
|
||||
@ -337,7 +338,7 @@ const TraceGanttChart = ({
|
||||
refs={tableRef}
|
||||
hideSelectAll={true}
|
||||
columns={columns}
|
||||
rowSelection={{ ...rowSelection, checkStrictly, type: "radio" }}
|
||||
rowSelection={{ ...rowSelection, checkStrictly, type: 'radio' }}
|
||||
dataSource={sortedTreeData}
|
||||
rowKey="id"
|
||||
sticky={true}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { pushDStree } from "store/actions";
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { pushDStree } from 'store/actions';
|
||||
|
||||
interface itemProps {
|
||||
treeData: pushDStree[];
|
||||
@ -12,12 +12,12 @@ const traverseTreeData = (
|
||||
tree: pushDStree[],
|
||||
callback: (item: pushDStree) => void,
|
||||
): void => {
|
||||
if (isEmpty(tree) || tree[0].id === "empty") return;
|
||||
let node = { treeData: tree, marked: false };
|
||||
let stk: [itemProps] = [node];
|
||||
if (isEmpty(tree) || tree[0].id === 'empty') return;
|
||||
const node = { treeData: tree, marked: false };
|
||||
const stk: [itemProps] = [node];
|
||||
|
||||
while (!isEmpty(stk)) {
|
||||
let x = stk[stk.length - 1];
|
||||
const x = stk[stk.length - 1];
|
||||
|
||||
// marked means seeing the node for the second time.
|
||||
if (x.marked) {
|
||||
|
@ -1 +1 @@
|
||||
export { default } from "./TraceGanttChart";
|
||||
export { default } from './TraceGanttChart';
|
||||
|
@ -56,4 +56,4 @@
|
||||
|
||||
.fade:not(.show) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,24 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useParams, useLocation } from "react-router-dom";
|
||||
import { flamegraph } from "d3-flame-graph";
|
||||
import { connect } from "react-redux";
|
||||
import { Card, Row, Col, Space, Affix } from "antd";
|
||||
import * as d3 from "d3";
|
||||
import * as d3Tip from "d3-tip";
|
||||
import "./TraceGraph.css";
|
||||
import { spanToTreeUtil } from "utils/spanToTree";
|
||||
import './TraceGraph.css';
|
||||
|
||||
import { Affix,Card, Col, Row, Space } from 'antd';
|
||||
import * as d3 from 'd3';
|
||||
import { flamegraph } from 'd3-flame-graph';
|
||||
import * as d3Tip from 'd3-tip';
|
||||
import { isEmpty, sortBy } from 'lodash-es';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { useLocation,useParams } from 'react-router-dom';
|
||||
import {
|
||||
fetchTraceItem,
|
||||
pushDStree,
|
||||
spansWSameTraceIDResponse,
|
||||
} from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import SelectedSpanDetails from "./SelectedSpanDetails";
|
||||
import TraceGanttChart from "./TraceGanttChart";
|
||||
import styled from "styled-components";
|
||||
import { isEmpty, sortBy } from "lodash-es";
|
||||
} from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
import { spanToTreeUtil } from 'utils/spanToTree';
|
||||
|
||||
import SelectedSpanDetails from './SelectedSpanDetails';
|
||||
import TraceGanttChart from './TraceGanttChart';
|
||||
|
||||
interface TraceGraphProps {
|
||||
traceItem: spansWSameTraceIDResponse;
|
||||
@ -29,7 +31,7 @@ const TraceGanttChartContainer = styled(Card)`
|
||||
`;
|
||||
|
||||
const _TraceGraph = (props: TraceGraphProps) => {
|
||||
let location = useLocation();
|
||||
const location = useLocation();
|
||||
const spanId = location?.state?.spanId;
|
||||
const params = useParams<{ id?: string }>();
|
||||
const [clickedSpanTags, setClickedSpanTags] = useState<pushDStree>([]);
|
||||
@ -42,7 +44,7 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
|
||||
const getSortedData = (treeData: pushDStree[], parent = {}) => {
|
||||
if (!isEmpty(treeData)) {
|
||||
if (treeData[0].id !== "empty") {
|
||||
if (treeData[0].id !== 'empty') {
|
||||
return Array.from(treeData).map((item, key) => {
|
||||
if (!isEmpty(item.children)) {
|
||||
getSortedData(item.children, item);
|
||||
@ -68,12 +70,12 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (props.traceItem) {
|
||||
let sortedData = getSortedData([tree]);
|
||||
const sortedData = getSortedData([tree]);
|
||||
setSortedTreeData(sortedData?.[0]);
|
||||
getSpanInfo(sortedData?.[0], spanId);
|
||||
// This is causing element to change ref. Can use both useRef or this approach.
|
||||
d3
|
||||
.select("#chart")
|
||||
.select('#chart')
|
||||
.datum(tree)
|
||||
.call(chart)
|
||||
.sort((item) => item.startTime);
|
||||
@ -85,7 +87,7 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
useEffect(() => {
|
||||
if (
|
||||
!isEmpty(sortedTreeData) &&
|
||||
sortedTreeData?.id !== "empty" &&
|
||||
sortedTreeData?.id !== 'empty' &&
|
||||
isEmpty(clickedSpanTags)
|
||||
) {
|
||||
setClickedSpanTags(sortedTreeData?.[0]);
|
||||
@ -96,7 +98,7 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
if (resetZoom) {
|
||||
// This is causing element to change ref. Can use both useRef or this approach.
|
||||
d3
|
||||
.select("#chart")
|
||||
.select('#chart')
|
||||
.datum(tree)
|
||||
.call(chart)
|
||||
.sort((item) => item.startTime);
|
||||
@ -106,9 +108,9 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
|
||||
const tip = d3Tip
|
||||
.default()
|
||||
.attr("class", "d3-tip")
|
||||
.attr('class', 'd3-tip')
|
||||
.html(function (d: any) {
|
||||
return d.data.name + "<br>duration: " + d.data.value / 1000000 + "ms";
|
||||
return d.data.name + '<br>duration: ' + d.data.value / 1000000 + 'ms';
|
||||
});
|
||||
|
||||
const onClick = (z: any) => {
|
||||
@ -127,7 +129,7 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
setSelectedSpan({});
|
||||
return;
|
||||
}
|
||||
if (data?.[0]?.id !== "empty") {
|
||||
if (data?.[0]?.id !== 'empty') {
|
||||
Array.from(data).map((item) => {
|
||||
if (item.id === spanId) {
|
||||
setSelectedSpan(item);
|
||||
@ -163,24 +165,24 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
return (
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
<Col md={18} sm={18}>
|
||||
<Space direction="vertical" size="middle" style={{ width: "100%" }}>
|
||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||
<Card bodyStyle={{ padding: 24 }} style={{ height: 320 }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
Trace Graph component ID is {params.id}{" "}
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
Trace Graph component ID is {params.id}{' '}
|
||||
</div>
|
||||
<div id="chart" style={{ fontSize: 12, marginTop: 20 }}></div>
|
||||
</div>
|
||||
</Card>
|
||||
<Affix offsetTop={24}>
|
||||
<TraceGanttChartContainer id={"collapsable"}>
|
||||
<TraceGanttChartContainer id={'collapsable'}>
|
||||
<TraceGanttChart
|
||||
treeData={sortedTreeData}
|
||||
clickedSpan={clickedSpan}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Table } from "antd";
|
||||
|
||||
import { traceResponseNew, pushDStree } from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { Table } from 'antd';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { pushDStree,traceResponseNew } from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
|
||||
interface TraceGraphColumnProps {
|
||||
traces: traceResponseNew;
|
||||
@ -19,39 +18,39 @@ interface TableDataSourceItem {
|
||||
const _TraceGraphColumn = (props: TraceGraphColumnProps) => {
|
||||
const columns: any = [
|
||||
{
|
||||
title: "Start Time (UTC Time)",
|
||||
dataIndex: "startTime",
|
||||
key: "startTime",
|
||||
title: 'Start Time (UTC Time)',
|
||||
dataIndex: 'startTime',
|
||||
key: 'startTime',
|
||||
sorter: (a: any, b: any) => a.startTime - b.startTime,
|
||||
sortDirections: ["descend", "ascend"],
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => new Date(Math.round(value / 1000)).toUTCString(),
|
||||
},
|
||||
{
|
||||
title: "Duration (in ms)",
|
||||
dataIndex: "duration",
|
||||
key: "duration",
|
||||
title: 'Duration (in ms)',
|
||||
dataIndex: 'duration',
|
||||
key: 'duration',
|
||||
sorter: (a: any, b: any) => a.duration - b.duration,
|
||||
sortDirections: ["descend", "ascend"],
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "Operation",
|
||||
dataIndex: "operationName",
|
||||
key: "operationName",
|
||||
title: 'Operation',
|
||||
dataIndex: 'operationName',
|
||||
key: 'operationName',
|
||||
},
|
||||
];
|
||||
|
||||
let dataSource: TableDataSourceItem[] = [];
|
||||
const dataSource: TableDataSourceItem[] = [];
|
||||
|
||||
if (props.traces[0].events.length > 0) {
|
||||
props.traces[0].events.map(
|
||||
(item: (number | string | string[] | pushDStree[])[], index) => {
|
||||
if (
|
||||
typeof item[0] === "number" &&
|
||||
typeof item[4] === "string" &&
|
||||
typeof item[6] === "string" &&
|
||||
typeof item[1] === "string" &&
|
||||
typeof item[2] === "string"
|
||||
typeof item[0] === 'number' &&
|
||||
typeof item[4] === 'string' &&
|
||||
typeof item[6] === 'string' &&
|
||||
typeof item[1] === 'string' &&
|
||||
typeof item[2] === 'string'
|
||||
)
|
||||
dataSource.push({
|
||||
startTime: item[0],
|
||||
|
@ -1,4 +1,4 @@
|
||||
export { TraceGraph as default } from "./TraceGraph";
|
||||
export { TraceGraph as default } from './TraceGraph';
|
||||
|
||||
// PNOTE
|
||||
// Because react.lazy doesn't work on named components
|
||||
|
@ -1,14 +1,13 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { Space, Table } from "antd";
|
||||
import ROUTES from "constants/routes";
|
||||
|
||||
import { traceResponseNew, fetchTraces, pushDStree } from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { isOnboardingSkipped } from "utils/app";
|
||||
import moment from "moment";
|
||||
import styled from "styled-components";
|
||||
import { Space, Table } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import moment from 'moment';
|
||||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { fetchTraces, pushDStree,traceResponseNew } from 'store/actions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
import { isOnboardingSkipped } from 'utils/app';
|
||||
|
||||
const StyledTable = styled(Table)`
|
||||
cursor: pointer;
|
||||
@ -35,7 +34,7 @@ interface TableDataSourceItem {
|
||||
|
||||
const _TraceList = (props: TraceListProps) => {
|
||||
// PNOTE (TO DO) - Currently this use of useEffect gives warning. May need to memoise fetchtraces - https://stackoverflow.com/questions/55840294/how-to-fix-missing-dependency-warning-when-using-useeffect-react-hook
|
||||
let history = useHistory();
|
||||
const history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
props.fetchTraces();
|
||||
@ -43,51 +42,51 @@ const _TraceList = (props: TraceListProps) => {
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: "Start Time",
|
||||
dataIndex: "startTime",
|
||||
key: "startTime",
|
||||
title: 'Start Time',
|
||||
dataIndex: 'startTime',
|
||||
key: 'startTime',
|
||||
sorter: (a: any, b: any) => a.startTime - b.startTime,
|
||||
sortDirections: ["descend", "ascend"],
|
||||
render: (value: number) => moment(value).format("YYYY-MM-DD hh:mm:ss"),
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => moment(value).format('YYYY-MM-DD hh:mm:ss'),
|
||||
|
||||
// new Date() assumes input in milliseconds. Start Time stamp returned by druid api for span list is in ms
|
||||
},
|
||||
{
|
||||
title: "Service",
|
||||
dataIndex: "service",
|
||||
key: "service",
|
||||
title: 'Service',
|
||||
dataIndex: 'service',
|
||||
key: 'service',
|
||||
},
|
||||
{
|
||||
title: "Operation",
|
||||
dataIndex: "operationName",
|
||||
key: "operationName",
|
||||
title: 'Operation',
|
||||
dataIndex: 'operationName',
|
||||
key: 'operationName',
|
||||
},
|
||||
{
|
||||
title: "Duration (in ms)",
|
||||
dataIndex: "duration",
|
||||
key: "duration",
|
||||
title: 'Duration (in ms)',
|
||||
dataIndex: 'duration',
|
||||
key: 'duration',
|
||||
sorter: (a: any, b: any) => a.duration - b.duration,
|
||||
sortDirections: ["descend", "ascend"],
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
];
|
||||
|
||||
let dataSource: TableDataSourceItem[] = [];
|
||||
const dataSource: TableDataSourceItem[] = [];
|
||||
|
||||
const renderTraces = () => {
|
||||
if (
|
||||
typeof props.traces[0] !== "undefined" &&
|
||||
typeof props.traces[0] !== 'undefined' &&
|
||||
props.traces[0].events.length > 0
|
||||
) {
|
||||
props.traces[0].events.map(
|
||||
(item: (number | string | string[] | pushDStree[])[], index) => {
|
||||
if (
|
||||
typeof item[0] === "number" &&
|
||||
typeof item[4] === "string" &&
|
||||
typeof item[6] === "string" &&
|
||||
typeof item[1] === "string" &&
|
||||
typeof item[2] === "string" &&
|
||||
typeof item[3] === "string"
|
||||
typeof item[0] === 'number' &&
|
||||
typeof item[4] === 'string' &&
|
||||
typeof item[6] === 'string' &&
|
||||
typeof item[1] === 'string' &&
|
||||
typeof item[2] === 'string' &&
|
||||
typeof item[3] === 'string'
|
||||
)
|
||||
dataSource.push({
|
||||
startTime: item[0],
|
||||
@ -112,7 +111,7 @@ const _TraceList = (props: TraceListProps) => {
|
||||
onRow={(record) => ({
|
||||
onClick: () => {
|
||||
history.push({
|
||||
pathname: ROUTES.TRACES + "/" + record.traceid,
|
||||
pathname: ROUTES.TRACES + '/' + record.traceid,
|
||||
state: {
|
||||
spanId: record.spanid,
|
||||
},
|
||||
@ -125,13 +124,14 @@ const _TraceList = (props: TraceListProps) => {
|
||||
if (isOnboardingSkipped()) {
|
||||
return (
|
||||
<Space
|
||||
style={{ width: "100%", margin: "40px 0", justifyContent: "center" }}
|
||||
style={{ width: '100%', margin: '40px 0', justifyContent: 'center' }}
|
||||
>
|
||||
No spans found. Please add instrumentation (follow this
|
||||
<a
|
||||
href={"https://signoz.io/docs/instrumentation/overview"}
|
||||
target={"_blank"}
|
||||
href={'https://signoz.io/docs/instrumentation/overview'}
|
||||
target={'_blank'}
|
||||
style={{ marginLeft: 3 }}
|
||||
rel="noreferrer"
|
||||
>
|
||||
guide
|
||||
</a>
|
||||
|
@ -1,19 +1,18 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Bar } from "react-chartjs-2";
|
||||
import { Card, Select, Space } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { Card, Select, Space } from 'antd';
|
||||
import { useRoute } from 'modules/RouteProvider';
|
||||
import moment from 'moment';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Bar } from 'react-chartjs-2';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
getServicesList,
|
||||
getUsageData,
|
||||
GlobalTime,
|
||||
usageDataItem,
|
||||
} from "store/actions";
|
||||
import { StoreState } from "store/reducers";
|
||||
import moment from "moment";
|
||||
import { isOnboardingSkipped } from "utils/app";
|
||||
import { useRoute } from "modules/RouteProvider";
|
||||
import { servicesListItem } from "store/actions/MetricsActions";
|
||||
} from 'store/actions';
|
||||
import { servicesListItem } from 'store/actions/MetricsActions';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import { isOnboardingSkipped } from 'utils/app';
|
||||
const { Option } = Select;
|
||||
|
||||
interface UsageExplorerProps {
|
||||
@ -25,28 +24,28 @@ interface UsageExplorerProps {
|
||||
totalCount: number;
|
||||
}
|
||||
const timeDaysOptions = [
|
||||
{ value: 30, label: "Last 30 Days" },
|
||||
{ value: 7, label: "Last week" },
|
||||
{ value: 1, label: "Last day" },
|
||||
{ value: 30, label: 'Last 30 Days' },
|
||||
{ value: 7, label: 'Last week' },
|
||||
{ value: 1, label: 'Last day' },
|
||||
];
|
||||
|
||||
const interval = [
|
||||
{
|
||||
value: 604800,
|
||||
chartDivideMultiplier: 1,
|
||||
label: "Weekly",
|
||||
label: 'Weekly',
|
||||
applicableOn: [timeDaysOptions[0]],
|
||||
},
|
||||
{
|
||||
value: 86400,
|
||||
chartDivideMultiplier: 30,
|
||||
label: "Daily",
|
||||
label: 'Daily',
|
||||
applicableOn: [timeDaysOptions[0], timeDaysOptions[1]],
|
||||
},
|
||||
{
|
||||
value: 3600,
|
||||
chartDivideMultiplier: 10,
|
||||
label: "Hours",
|
||||
label: 'Hours',
|
||||
applicableOn: [timeDaysOptions[2], timeDaysOptions[1]],
|
||||
},
|
||||
];
|
||||
@ -54,7 +53,7 @@ const interval = [
|
||||
const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
const [selectedTime, setSelectedTime] = useState(timeDaysOptions[1]);
|
||||
const [selectedInterval, setSelectedInterval] = useState(interval[2]);
|
||||
const [selectedService, setSelectedService] = useState<string>("");
|
||||
const [selectedService, setSelectedService] = useState<string>('');
|
||||
|
||||
const { state } = useRoute();
|
||||
|
||||
@ -84,14 +83,14 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
|
||||
const data = {
|
||||
labels: props.usageData.map((s) =>
|
||||
moment(s.timestamp / 1000000).format("MMM Do h a"),
|
||||
moment(s.timestamp / 1000000).format('MMM Do h a'),
|
||||
),
|
||||
datasets: [
|
||||
{
|
||||
label: "Span Count",
|
||||
label: 'Span Count',
|
||||
data: props.usageData.map((s) => s.count),
|
||||
backgroundColor: "rgba(255, 99, 132, 0.2)",
|
||||
borderColor: "rgba(255, 99, 132, 1)",
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
borderWidth: 2,
|
||||
},
|
||||
],
|
||||
@ -153,9 +152,9 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
onSelect={(value) => {
|
||||
setSelectedService(value);
|
||||
}}
|
||||
value={selectedService || "All Services"}
|
||||
value={selectedService || 'All Services'}
|
||||
>
|
||||
<Option value={""}>All Services</Option>
|
||||
<Option value={''}>All Services</Option>
|
||||
{props.servicesList.map((service) => (
|
||||
<Option value={service.serviceName}>{service.serviceName}</Option>
|
||||
))}
|
||||
@ -165,30 +164,31 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
{isOnboardingSkipped() && props.totalCount === 0 ? (
|
||||
<Space
|
||||
style={{
|
||||
width: "100%",
|
||||
margin: "40px 0",
|
||||
width: '100%',
|
||||
margin: '40px 0',
|
||||
marginLeft: 20,
|
||||
justifyContent: "center",
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
No spans found. Please add instrumentation (follow this
|
||||
<a
|
||||
href={"https://signoz.io/docs/instrumentation/overview"}
|
||||
target={"_blank"}
|
||||
href={'https://signoz.io/docs/instrumentation/overview'}
|
||||
target={'_blank'}
|
||||
style={{ marginLeft: 3 }}
|
||||
rel="noreferrer"
|
||||
>
|
||||
guide
|
||||
</a>
|
||||
)
|
||||
</Space>
|
||||
) : (
|
||||
<Space style={{ display: "block", marginLeft: 20, width: 200 }}>
|
||||
<Space style={{ display: 'block', marginLeft: 20, width: 200 }}>
|
||||
{`Total count is ${props.totalCount}`}
|
||||
</Space>
|
||||
)}
|
||||
</Space>
|
||||
|
||||
<Card style={{ width: "90%", margin: 20 }} bodyStyle={{ padding: 20 }}>
|
||||
<Card style={{ width: '90%', margin: 20 }} bodyStyle={{ padding: 20 }}>
|
||||
<Bar data={data} options={options} />
|
||||
</Card>
|
||||
</React.Fragment>
|
||||
@ -204,7 +204,7 @@ const mapStateToProps = (
|
||||
usageData: usageDataItem[];
|
||||
} => {
|
||||
let totalCount = 0;
|
||||
for (let item of state.usageDate) {
|
||||
for (const item of state.usageDate) {
|
||||
totalCount = totalCount + item.count;
|
||||
}
|
||||
return {
|
||||
|
@ -1 +1 @@
|
||||
export { UsageExplorer as default } from "./UsageExplorer";
|
||||
export { UsageExplorer as default } from './UsageExplorer';
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from "react";
|
||||
import { Space } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { StoreState } from "store/reducers";
|
||||
import { useThemeSwitcher } from "react-css-theme-switcher";
|
||||
import styled from "styled-components";
|
||||
import { Space } from 'antd';
|
||||
import React from 'react';
|
||||
import { useThemeSwitcher } from 'react-css-theme-switcher';
|
||||
import { connect } from 'react-redux';
|
||||
import { StoreState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const InstrumentCard = styled.div<{
|
||||
currentThemeStatus: string | undefined;
|
||||
}>`
|
||||
border-radius: 4px;
|
||||
background: ${({ currentThemeStatus }) =>
|
||||
currentThemeStatus === "dark" ? "#313131" : "#ddd"};
|
||||
currentThemeStatus === 'dark' ? '#313131' : '#ddd'};
|
||||
padding: 33px 23px;
|
||||
max-width: 800px;
|
||||
margin-top: 40px;
|
||||
@ -23,7 +23,7 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Space style={{ marginLeft: 60, marginTop: 48, display: "block" }}>
|
||||
<Space style={{ marginLeft: 60, marginTop: 48, display: 'block' }}>
|
||||
<div>
|
||||
<h2>Instrument your application</h2>
|
||||
</div>
|
||||
@ -33,24 +33,24 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
|
||||
To start seeing YOUR application data here, follow the instructions in the
|
||||
docs -
|
||||
<a
|
||||
href={"https://signoz.io/docs/instrumentation/overview"}
|
||||
target="_blank"
|
||||
href={'https://signoz.io/docs/instrumentation/overview'}
|
||||
target="_blank" rel="noreferrer"
|
||||
>
|
||||
{" "}
|
||||
{' '}
|
||||
https://signoz.io/docs/instrumentation/overview
|
||||
</a>
|
||||
<br />
|
||||
If you face any issues, join our{" "}
|
||||
If you face any issues, join our{' '}
|
||||
<a
|
||||
href={
|
||||
"https://signoz-community.slack.com/join/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
'https://signoz-community.slack.com/join/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA'
|
||||
}
|
||||
target="_blank"
|
||||
target="_blank" rel="noreferrer"
|
||||
>
|
||||
slack community
|
||||
</a>{" "}
|
||||
to ask any questions or mail us at{" "}
|
||||
<a href={"mailto:support@signoz.io"} target="_blank">
|
||||
</a>{' '}
|
||||
to ask any questions or mail us at{' '}
|
||||
<a href={'mailto:support@signoz.io'} target="_blank" rel="noreferrer">
|
||||
support@signoz.io
|
||||
</a>
|
||||
</InstrumentCard>
|
||||
|
@ -1,61 +1,61 @@
|
||||
import Loadable from "./components/Loadable";
|
||||
import Loadable from './components/Loadable';
|
||||
|
||||
export const ServiceMetricsPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "ServiceMetricsPage" */ "modules/Metrics/ServiceMetricsDef"
|
||||
/* webpackChunkName: "ServiceMetricsPage" */ 'modules/Metrics/ServiceMetricsDef'
|
||||
),
|
||||
);
|
||||
|
||||
export const ServiceMapPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "ServiceMapPage" */ "modules/Servicemap/ServiceMap"
|
||||
/* webpackChunkName: "ServiceMapPage" */ 'modules/Servicemap/ServiceMap'
|
||||
),
|
||||
);
|
||||
|
||||
export const TraceDetailPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "TraceDetailPage" */ "modules/Traces/TraceDetail"
|
||||
/* webpackChunkName: "TraceDetailPage" */ 'modules/Traces/TraceDetail'
|
||||
),
|
||||
);
|
||||
|
||||
export const TraceGraphPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "TraceGraphPage" */ "modules/Traces/TraceGraphDef"
|
||||
/* webpackChunkName: "TraceGraphPage" */ 'modules/Traces/TraceGraphDef'
|
||||
),
|
||||
);
|
||||
|
||||
export const UsageExplorerPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "UsageExplorerPage" */ "modules/Usage/UsageExplorerDef"
|
||||
/* webpackChunkName: "UsageExplorerPage" */ 'modules/Usage/UsageExplorerDef'
|
||||
),
|
||||
);
|
||||
|
||||
export const ServicesTablePage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "ServicesTablePage" */ "modules/Metrics/ServicesTableDef"
|
||||
/* webpackChunkName: "ServicesTablePage" */ 'modules/Metrics/ServicesTableDef'
|
||||
),
|
||||
);
|
||||
|
||||
export const SignupPage = Loadable(
|
||||
() => import(/* webpackChunkName: "SignupPage" */ "modules/Auth/Signup"),
|
||||
() => import(/* webpackChunkName: "SignupPage" */ 'modules/Auth/Signup'),
|
||||
);
|
||||
|
||||
export const SettingsPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "SettingsPage" */ "modules/Settings/settingsPage"
|
||||
/* webpackChunkName: "SettingsPage" */ 'modules/Settings/settingsPage'
|
||||
),
|
||||
);
|
||||
|
||||
export const InstrumentationPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "InstrumentationPage" */ "modules/add-instrumentation/instrumentationPage"
|
||||
/* webpackChunkName: "InstrumentationPage" */ 'modules/add-instrumentation/instrumentationPage'
|
||||
),
|
||||
);
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from "./metricsInterfaces";
|
||||
export * from "./metricsActionTypes";
|
||||
export * from "./metricsActions";
|
||||
export * from './metricsActions';
|
||||
export * from './metricsActionTypes';
|
||||
export * from './metricsInterfaces';
|
||||
|
@ -7,18 +7,18 @@ import {
|
||||
getServiceMetricsAction,
|
||||
getServicesListAction,
|
||||
getTopEndpointsAction,
|
||||
} from "./metricsInterfaces";
|
||||
} from './metricsInterfaces';
|
||||
|
||||
export enum MetricsActionTypes {
|
||||
updateInput = "UPDATE_INPUT",
|
||||
getServicesList = "GET_SERVICE_LIST",
|
||||
getServiceMetrics = "GET_SERVICE_METRICS",
|
||||
getAvgDurationMetrics = "GET_AVG_DURATION_METRICS",
|
||||
getErrCodeMetrics = "GET_ERR_CODE_METRICS",
|
||||
getDbOverviewMetrics = "GET_DB_OVERVIEW_METRICS",
|
||||
getExternalMetrics = "GET_EXTERNAL_METRICS",
|
||||
getTopEndpoints = "GET_TOP_ENDPOINTS",
|
||||
getFilteredTraceMetrics = "GET_FILTERED_TRACE_METRICS",
|
||||
updateInput = 'UPDATE_INPUT',
|
||||
getServicesList = 'GET_SERVICE_LIST',
|
||||
getServiceMetrics = 'GET_SERVICE_METRICS',
|
||||
getAvgDurationMetrics = 'GET_AVG_DURATION_METRICS',
|
||||
getErrCodeMetrics = 'GET_ERR_CODE_METRICS',
|
||||
getDbOverviewMetrics = 'GET_DB_OVERVIEW_METRICS',
|
||||
getExternalMetrics = 'GET_EXTERNAL_METRICS',
|
||||
getTopEndpoints = 'GET_TOP_ENDPOINTS',
|
||||
getFilteredTraceMetrics = 'GET_FILTERED_TRACE_METRICS',
|
||||
}
|
||||
|
||||
export type MetricsActions =
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Dispatch } from "redux";
|
||||
import api, { apiV1 } from "api";
|
||||
import api, { apiV1 } from 'api';
|
||||
import { Dispatch } from 'redux';
|
||||
import { GlobalTime } from 'store/actions/global';
|
||||
import { toUTCEpoch } from 'utils/timeUtils';
|
||||
|
||||
import { GlobalTime } from "store/actions/global";
|
||||
import { toUTCEpoch } from "utils/timeUtils";
|
||||
import { MetricsActionTypes } from "./metricsActionTypes";
|
||||
import * as MetricsInterfaces from "./metricsInterfaces";
|
||||
import { MetricsActionTypes } from './metricsActionTypes';
|
||||
import * as MetricsInterfaces from './metricsInterfaces';
|
||||
|
||||
export const getServicesList = (globalTime: GlobalTime) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime;
|
||||
const request_string =
|
||||
'/services?start=' + globalTime.minTime + '&end=' + globalTime.maxTime;
|
||||
|
||||
const response = await api.get<MetricsInterfaces.servicesListItem[]>(
|
||||
apiV1 + request_string,
|
||||
@ -28,14 +28,14 @@ export const getDbOverViewMetrics = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/dbOverview?service=" +
|
||||
const request_string =
|
||||
'/service/dbOverview?service=' +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
'&start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
'&step=60';
|
||||
const response = await api.get<MetricsInterfaces.dbOverviewMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
@ -51,14 +51,14 @@ export const getExternalMetrics = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/external?service=" +
|
||||
const request_string =
|
||||
'/service/external?service=' +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
'&start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
'&step=60';
|
||||
const response = await api.get<MetricsInterfaces.externalMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
@ -74,14 +74,14 @@ export const getExternalAvgDurationMetrics = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/externalAvgDuration?service=" +
|
||||
const request_string =
|
||||
'/service/externalAvgDuration?service=' +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
'&start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
'&step=60';
|
||||
|
||||
const response = await api.get<
|
||||
MetricsInterfaces.externalMetricsAvgDurationItem[]
|
||||
@ -97,14 +97,14 @@ export const getExternalErrCodeMetrics = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/externalErrors?service=" +
|
||||
const request_string =
|
||||
'/service/externalErrors?service=' +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
'&start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
'&step=60';
|
||||
const response = await api.get<
|
||||
MetricsInterfaces.externalErrCodeMetricsItem[]
|
||||
>(apiV1 + request_string);
|
||||
@ -121,14 +121,14 @@ export const getServicesMetrics = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/overview?service=" +
|
||||
const request_string =
|
||||
'/service/overview?service=' +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
'&start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
'&step=60';
|
||||
const response = await api.get<MetricsInterfaces.metricItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
@ -146,12 +146,12 @@ export const getTopEndpoints = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/top_endpoints?service=" +
|
||||
const request_string =
|
||||
'/service/top_endpoints?service=' +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
'&start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime;
|
||||
const response = await api.get<MetricsInterfaces.topEndpointListItem[]>(
|
||||
apiV1 + request_string,
|
||||
@ -170,12 +170,12 @@ export const getFilteredTraceMetrics = (
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/spans/aggregates?start=" +
|
||||
const request_string =
|
||||
'/spans/aggregates?start=' +
|
||||
toUTCEpoch(globalTime.minTime) +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
toUTCEpoch(globalTime.maxTime) +
|
||||
"&" +
|
||||
'&' +
|
||||
filter_params;
|
||||
const response = await api.get<MetricsInterfaces.customMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MetricsActionTypes } from "./metricsActionTypes";
|
||||
import { MetricsActionTypes } from './metricsActionTypes';
|
||||
|
||||
export interface servicesListItem {
|
||||
serviceName: string;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ActionTypes } from "./types";
|
||||
import { Moment } from "moment";
|
||||
import { Moment } from 'moment';
|
||||
|
||||
import { ActionTypes } from './types';
|
||||
|
||||
export type DateTimeRangeType = [Moment | null, Moment | null] | null;
|
||||
|
||||
@ -17,60 +18,60 @@ export const updateTimeInterval = (
|
||||
interval: string,
|
||||
datetimeRange?: [number, number],
|
||||
) => {
|
||||
let maxTime: number = 0;
|
||||
let minTime: number = 0;
|
||||
let maxTime = 0;
|
||||
let minTime = 0;
|
||||
// if interval string is custom, then datetimRange should be present and max & min time should be
|
||||
// set directly based on that. Assuming datetimeRange values are in ms, and minTime is 0th element
|
||||
|
||||
switch (interval) {
|
||||
case "1min":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 1 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case "5min":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 5 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '1min':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 1 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '5min':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 5 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "15min":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 15 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '15min':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 15 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "30min":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 30 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '30min':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 30 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "1hr":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 1 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '1hr':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 1 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "6hr":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 6 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '6hr':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 6 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "1day":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 24 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '1day':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 24 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "1week":
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 7 * 24 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
case '1week':
|
||||
maxTime = Date.now() * 1000000; // in nano sec
|
||||
minTime = (Date.now() - 7 * 24 * 60 * 60 * 1000) * 1000000;
|
||||
break;
|
||||
|
||||
case "custom":
|
||||
if (datetimeRange !== undefined) {
|
||||
maxTime = datetimeRange[1] * 1000000; // in nano sec
|
||||
minTime = datetimeRange[0] * 1000000; // in nano sec
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
if (datetimeRange !== undefined) {
|
||||
maxTime = datetimeRange[1] * 1000000; // in nano sec
|
||||
minTime = datetimeRange[0] * 1000000; // in nano sec
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("not found matching case");
|
||||
default:
|
||||
console.log('not found matching case');
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -1,7 +1,7 @@
|
||||
export * from "./types";
|
||||
export * from "./traceFilters";
|
||||
export * from "./serviceMap";
|
||||
export * from "./traces";
|
||||
export * from "./MetricsActions";
|
||||
export * from "./usage";
|
||||
export * from "./global";
|
||||
export * from './global';
|
||||
export * from './MetricsActions';
|
||||
export * from './serviceMap';
|
||||
export * from './traceFilters';
|
||||
export * from './traces';
|
||||
export * from './types';
|
||||
export * from './usage';
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Dispatch } from "redux";
|
||||
import api, { apiV1 } from "api";
|
||||
import { GlobalTime } from "./global";
|
||||
import { ActionTypes } from "./types";
|
||||
import api, { apiV1 } from 'api';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
import { GlobalTime } from './global';
|
||||
import { ActionTypes } from './types';
|
||||
|
||||
export interface serviceMapStore {
|
||||
items: servicesMapItem[];
|
||||
@ -43,10 +44,10 @@ export const getServiceMapItems = (globalTime: GlobalTime) => {
|
||||
payload: [],
|
||||
});
|
||||
|
||||
let request_string =
|
||||
"/serviceMapDependencies?start=" +
|
||||
const request_string =
|
||||
'/serviceMapDependencies?start=' +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
globalTime.maxTime;
|
||||
|
||||
const response = await api.get<servicesMapItem[]>(apiV1 + request_string);
|
||||
@ -65,8 +66,8 @@ export const getDetailedServiceMapItems = (globalTime: GlobalTime) => {
|
||||
payload: [],
|
||||
});
|
||||
|
||||
let request_string =
|
||||
"/services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime;
|
||||
const request_string =
|
||||
'/services?start=' + globalTime.minTime + '&end=' + globalTime.maxTime;
|
||||
|
||||
const response = await api.get<servicesItem[]>(apiV1 + request_string);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Action creator must have a type and optionally a payload
|
||||
import { ActionTypes } from "./types";
|
||||
import { ActionTypes } from './types';
|
||||
|
||||
export interface TagItem {
|
||||
key: string;
|
||||
value: string;
|
||||
operator: "equals" | "contains" | "regex";
|
||||
operator: 'equals' | 'contains' | 'regex';
|
||||
}
|
||||
|
||||
export interface LatencyValue {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { ActionTypes } from "./types";
|
||||
import api, { apiV1 } from "api";
|
||||
import api, { apiV1 } from 'api';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { Dispatch } from 'redux';
|
||||
import { toUTCEpoch } from 'utils/timeUtils';
|
||||
|
||||
import { Dispatch } from "redux";
|
||||
import { GlobalTime } from "./global";
|
||||
import { toUTCEpoch } from "utils/timeUtils";
|
||||
import ROUTES from "constants/routes";
|
||||
import { GlobalTime } from './global';
|
||||
import { ActionTypes } from './types';
|
||||
|
||||
// PNOTE
|
||||
// define trace interface - what it should return
|
||||
@ -122,12 +122,12 @@ export interface FetchTraceItemAction {
|
||||
export const fetchTraces = (globalTime: GlobalTime, filter_params: string) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
if (globalTime) {
|
||||
let request_string =
|
||||
"/spans?limit=100&lookback=2d&start=" +
|
||||
const request_string =
|
||||
'/spans?limit=100&lookback=2d&start=' +
|
||||
toUTCEpoch(globalTime.minTime) +
|
||||
"&end=" +
|
||||
'&end=' +
|
||||
toUTCEpoch(globalTime.maxTime) +
|
||||
"&" +
|
||||
'&' +
|
||||
filter_params;
|
||||
const response = await api.get<traceResponseNew>(apiV1 + request_string);
|
||||
|
||||
@ -142,7 +142,7 @@ export const fetchTraces = (globalTime: GlobalTime, filter_params: string) => {
|
||||
|
||||
export const fetchTraceItem = (traceID: string) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string = ROUTES.TRACES + "/" + traceID;
|
||||
const request_string = ROUTES.TRACES + '/' + traceID;
|
||||
const response = await api.get<spansWSameTraceIDResponse>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
|
@ -1,18 +1,17 @@
|
||||
import { FetchTracesAction, FetchTraceItemAction } from "./traces";
|
||||
import { updateTraceFiltersAction } from "./traceFilters";
|
||||
|
||||
import { serviceMapItemAction, servicesAction } from "./serviceMap";
|
||||
import { getUsageDataAction } from "./usage";
|
||||
import { updateTimeIntervalAction } from "./global";
|
||||
import { updateTimeIntervalAction } from './global';
|
||||
import { serviceMapItemAction, servicesAction } from './serviceMap';
|
||||
import { updateTraceFiltersAction } from './traceFilters';
|
||||
import { FetchTraceItemAction,FetchTracesAction } from './traces';
|
||||
import { getUsageDataAction } from './usage';
|
||||
|
||||
export enum ActionTypes {
|
||||
updateTraceFilters = "UPDATE_TRACES_FILTER",
|
||||
updateTimeInterval = "UPDATE_TIME_INTERVAL",
|
||||
getServiceMapItems = "GET_SERVICE_MAP_ITEMS",
|
||||
getServices = "GET_SERVICES",
|
||||
getUsageData = "GET_USAGE_DATE",
|
||||
fetchTraces = "FETCH_TRACES",
|
||||
fetchTraceItem = "FETCH_TRACE_ITEM",
|
||||
updateTraceFilters = 'UPDATE_TRACES_FILTER',
|
||||
updateTimeInterval = 'UPDATE_TIME_INTERVAL',
|
||||
getServiceMapItems = 'GET_SERVICE_MAP_ITEMS',
|
||||
getServices = 'GET_SERVICES',
|
||||
getUsageData = 'GET_USAGE_DATE',
|
||||
fetchTraces = 'FETCH_TRACES',
|
||||
fetchTraceItem = 'FETCH_TRACE_ITEM',
|
||||
}
|
||||
|
||||
export type Action =
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Dispatch } from "redux";
|
||||
import api, { apiV1 } from "api";
|
||||
import api, { apiV1 } from 'api';
|
||||
import { Dispatch } from 'redux';
|
||||
import { toUTCEpoch } from 'utils/timeUtils';
|
||||
|
||||
import { ActionTypes } from "./types";
|
||||
import { toUTCEpoch } from "utils/timeUtils";
|
||||
import { ActionTypes } from './types';
|
||||
|
||||
export interface usageDataItem {
|
||||
timestamp: number;
|
||||
@ -21,9 +21,9 @@ export const getUsageData = (
|
||||
service: string,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string = `/usage?start=${toUTCEpoch(minTime)}&end=${toUTCEpoch(
|
||||
const request_string = `/usage?start=${toUTCEpoch(minTime)}&end=${toUTCEpoch(
|
||||
maxTime,
|
||||
)}&step=${step}&service=${service ? service : ""}`;
|
||||
)}&step=${step}&service=${service ? service : ''}`;
|
||||
//Step can only be multiple of 3600
|
||||
const response = await api.get<usageDataItem[]>(apiV1 + request_string);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { createStore, applyMiddleware, compose } from "redux";
|
||||
import reducers from "./reducers";
|
||||
import thunk from "redux-thunk";
|
||||
import { applyMiddleware, compose,createStore } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
|
||||
import reducers from './reducers';
|
||||
|
||||
const composeEnhancers =
|
||||
(window && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ActionTypes, Action, GlobalTime } from "store/actions";
|
||||
import { Action, ActionTypes, GlobalTime } from 'store/actions';
|
||||
|
||||
export const updateGlobalTimeReducer = (
|
||||
state: GlobalTime = {
|
||||
@ -9,9 +9,9 @@ export const updateGlobalTimeReducer = (
|
||||
) => {
|
||||
// Initial global state is time now and 15 minute interval
|
||||
switch (action.type) {
|
||||
case ActionTypes.updateTimeInterval:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
case ActionTypes.updateTimeInterval:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
@ -1,18 +1,19 @@
|
||||
import { combineReducers } from "redux";
|
||||
import { combineReducers } from 'redux';
|
||||
import {
|
||||
traceResponseNew,
|
||||
spansWSameTraceIDResponse,
|
||||
usageDataItem,
|
||||
GlobalTime,
|
||||
serviceMapStore,
|
||||
spansWSameTraceIDResponse,
|
||||
TraceFilters,
|
||||
} from "store/actions";
|
||||
import { updateGlobalTimeReducer } from "./global";
|
||||
import { MetricsInitialState, metricsReducer } from "./metrics";
|
||||
import TraceFilterReducer from "./traceFilters";
|
||||
import { traceItemReducer, tracesReducer } from "./traces";
|
||||
import { usageDataReducer } from "./usage";
|
||||
import { ServiceMapReducer } from "./serviceMap";
|
||||
traceResponseNew,
|
||||
usageDataItem,
|
||||
} from 'store/actions';
|
||||
|
||||
import { updateGlobalTimeReducer } from './global';
|
||||
import { MetricsInitialState, metricsReducer } from './metrics';
|
||||
import { ServiceMapReducer } from './serviceMap';
|
||||
import TraceFilterReducer from './traceFilters';
|
||||
import { traceItemReducer, tracesReducer } from './traces';
|
||||
import { usageDataReducer } from './usage';
|
||||
|
||||
export interface StoreState {
|
||||
metricsData: MetricsInitialState;
|
||||
|
@ -1,14 +1,14 @@
|
||||
import {
|
||||
servicesListItem,
|
||||
metricItem,
|
||||
topEndpointListItem,
|
||||
externalErrCodeMetricsItem,
|
||||
customMetricsItem,
|
||||
externalMetricsItem,
|
||||
dbOverviewMetricsItem,
|
||||
externalErrCodeMetricsItem,
|
||||
externalMetricsAvgDurationItem,
|
||||
} from "store/actions/MetricsActions";
|
||||
import { MetricsActionTypes as ActionTypes } from "store/actions/MetricsActions/metricsActionTypes";
|
||||
externalMetricsItem,
|
||||
metricItem,
|
||||
servicesListItem,
|
||||
topEndpointListItem,
|
||||
} from 'store/actions/MetricsActions';
|
||||
import { MetricsActionTypes as ActionTypes } from 'store/actions/MetricsActions/metricsActionTypes';
|
||||
|
||||
export type MetricsInitialState = {
|
||||
serviceList?: servicesListItem[];
|
||||
@ -23,7 +23,7 @@ export type MetricsInitialState = {
|
||||
export const metricsInitialState: MetricsInitialState = {
|
||||
serviceList: [
|
||||
{
|
||||
serviceName: "",
|
||||
serviceName: '',
|
||||
p99: 0,
|
||||
avgDuration: 0,
|
||||
numCalls: 0,
|
||||
@ -50,7 +50,7 @@ export const metricsInitialState: MetricsInitialState = {
|
||||
p95: 0,
|
||||
p99: 0,
|
||||
numCalls: 0,
|
||||
name: "",
|
||||
name: '',
|
||||
},
|
||||
],
|
||||
externalMetricsAvgDurationItem: [
|
||||
@ -62,7 +62,7 @@ export const metricsInitialState: MetricsInitialState = {
|
||||
externalErrCodeMetricsItem: [
|
||||
{
|
||||
callRate: 0,
|
||||
externalHttpUrl: "",
|
||||
externalHttpUrl: '',
|
||||
numCalls: 0,
|
||||
timestamp: 0,
|
||||
},
|
||||
@ -71,7 +71,7 @@ export const metricsInitialState: MetricsInitialState = {
|
||||
{
|
||||
avgDuration: 0,
|
||||
callRate: 0,
|
||||
externalHttpUrl: "",
|
||||
externalHttpUrl: '',
|
||||
numCalls: 0,
|
||||
timestamp: 0,
|
||||
},
|
||||
@ -80,7 +80,7 @@ export const metricsInitialState: MetricsInitialState = {
|
||||
{
|
||||
avgDuration: 0,
|
||||
callRate: 0,
|
||||
dbSystem: "",
|
||||
dbSystem: '',
|
||||
numCalls: 0,
|
||||
timestamp: 0,
|
||||
},
|
||||
@ -103,50 +103,50 @@ export const metricsReducer = (
|
||||
action: ActionType,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.getFilteredTraceMetrics:
|
||||
return {
|
||||
...state,
|
||||
customMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getServiceMetrics:
|
||||
return {
|
||||
...state,
|
||||
metricItems: action.payload,
|
||||
};
|
||||
case ActionTypes.getDbOverviewMetrics:
|
||||
return {
|
||||
...state,
|
||||
dbOverviewMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getExternalMetrics:
|
||||
return {
|
||||
...state,
|
||||
externalMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getTopEndpoints:
|
||||
return {
|
||||
...state,
|
||||
topEndpointListItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getErrCodeMetrics:
|
||||
return {
|
||||
...state,
|
||||
externalErrCodeMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getAvgDurationMetrics:
|
||||
return {
|
||||
...state,
|
||||
externalMetricsAvgDurationItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getFilteredTraceMetrics:
|
||||
return {
|
||||
...state,
|
||||
customMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getServiceMetrics:
|
||||
return {
|
||||
...state,
|
||||
metricItems: action.payload,
|
||||
};
|
||||
case ActionTypes.getDbOverviewMetrics:
|
||||
return {
|
||||
...state,
|
||||
dbOverviewMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getExternalMetrics:
|
||||
return {
|
||||
...state,
|
||||
externalMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getTopEndpoints:
|
||||
return {
|
||||
...state,
|
||||
topEndpointListItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getErrCodeMetrics:
|
||||
return {
|
||||
...state,
|
||||
externalErrCodeMetricsItem: action.payload,
|
||||
};
|
||||
case ActionTypes.getAvgDurationMetrics:
|
||||
return {
|
||||
...state,
|
||||
externalMetricsAvgDurationItem: action.payload,
|
||||
};
|
||||
|
||||
case ActionTypes.getServicesList:
|
||||
return {
|
||||
...state,
|
||||
serviceList: action.payload,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
case ActionTypes.getServicesList:
|
||||
return {
|
||||
...state,
|
||||
serviceList: action.payload,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ActionTypes, Action, serviceMapStore } from "store/actions";
|
||||
import { Action, ActionTypes, serviceMapStore } from 'store/actions';
|
||||
|
||||
const initialState: serviceMapStore = {
|
||||
items: [],
|
||||
@ -7,17 +7,17 @@ const initialState: serviceMapStore = {
|
||||
|
||||
export const ServiceMapReducer = (state = initialState, action: Action) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.getServiceMapItems:
|
||||
return {
|
||||
...state,
|
||||
items: action.payload,
|
||||
};
|
||||
case ActionTypes.getServices:
|
||||
return {
|
||||
...state,
|
||||
services: action.payload,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
case ActionTypes.getServiceMapItems:
|
||||
return {
|
||||
...state,
|
||||
items: action.payload,
|
||||
};
|
||||
case ActionTypes.getServices:
|
||||
return {
|
||||
...state,
|
||||
services: action.payload,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
@ -1,23 +1,23 @@
|
||||
import { ActionTypes, TraceFilters } from "store/actions";
|
||||
import { ActionTypes, TraceFilters } from 'store/actions';
|
||||
|
||||
type ACTION = {
|
||||
type: ActionTypes;
|
||||
payload: TraceFilters;
|
||||
};
|
||||
const initialState: TraceFilters = {
|
||||
service: "",
|
||||
service: '',
|
||||
tags: [],
|
||||
operation: "",
|
||||
latency: { min: "", max: "" },
|
||||
kind: "",
|
||||
operation: '',
|
||||
latency: { min: '', max: '' },
|
||||
kind: '',
|
||||
};
|
||||
|
||||
const TraceFilterReducer = (state = initialState, action: ACTION) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.updateTraceFilters:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
case ActionTypes.updateTraceFilters:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,33 +1,33 @@
|
||||
import {
|
||||
ActionTypes,
|
||||
Action,
|
||||
traceResponseNew,
|
||||
ActionTypes,
|
||||
spanList,
|
||||
spansWSameTraceIDResponse,
|
||||
} from "store/actions";
|
||||
traceResponseNew,
|
||||
} from 'store/actions';
|
||||
|
||||
// PNOTE - Initializing is a must for state variable otherwise it gives an error in reducer
|
||||
var spanlistinstance: spanList = { events: [], segmentID: "", columns: [] };
|
||||
const spanlistinstance: spanList = { events: [], segmentID: '', columns: [] };
|
||||
export const tracesReducer = (
|
||||
state: traceResponseNew = { "0": spanlistinstance },
|
||||
state: traceResponseNew = { '0': spanlistinstance },
|
||||
action: Action,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.fetchTraces:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
case ActionTypes.fetchTraces:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const traceItemReducer = (
|
||||
state: spansWSameTraceIDResponse = { "0": spanlistinstance },
|
||||
state: spansWSameTraceIDResponse = { '0': spanlistinstance },
|
||||
action: Action,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.fetchTraceItem:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
case ActionTypes.fetchTraceItem:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { ActionTypes, Action, usageDataItem } from "store/actions";
|
||||
import { Action, ActionTypes, usageDataItem } from 'store/actions';
|
||||
|
||||
export const usageDataReducer = (
|
||||
state: usageDataItem[] = [{ timestamp: 0, count: 0 }],
|
||||
action: Action,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.getUsageData:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
case ActionTypes.getUsageData:
|
||||
return action.payload;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
const themes = {
|
||||
dark: `/dark-theme.css`,
|
||||
light: `/light-theme.css`,
|
||||
dark: '/dark-theme.css',
|
||||
light: '/light-theme.css',
|
||||
};
|
||||
|
||||
export default themes;
|
||||
export default themes;
|
||||
|
2
frontend/src/typings/d3-tip.d.ts
vendored
2
frontend/src/typings/d3-tip.d.ts
vendored
@ -1 +1 @@
|
||||
declare module "d3-tip";
|
||||
declare module 'd3-tip';
|
||||
|
8
frontend/src/typings/react-graph-vis.d.ts
vendored
8
frontend/src/typings/react-graph-vis.d.ts
vendored
@ -1,9 +1,9 @@
|
||||
//You must first install the vis and react types 'npm install --save-dev @types/vis @types/react'
|
||||
declare module "react-graph-vis" {
|
||||
import { Network, NetworkEvents, Options, Node, Edge, DataSet } from "vis";
|
||||
import { Component } from "react";
|
||||
declare module 'react-graph-vis' {
|
||||
import { Network, NetworkEvents, Options, Node, Edge, DataSet } from 'vis';
|
||||
import { Component } from 'react';
|
||||
|
||||
export { Network, NetworkEvents, Options, Node, Edge, DataSet } from "vis";
|
||||
export { Network, NetworkEvents, Options, Node, Edge, DataSet } from 'vis';
|
||||
|
||||
export interface graphEvents {
|
||||
[event: NetworkEvents]: (params?: any) => void;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SKIP_ONBOARDING } from "constants/onboarding";
|
||||
import { SKIP_ONBOARDING } from 'constants/onboarding';
|
||||
|
||||
export const isOnboardingSkipped = () => {
|
||||
return localStorage.getItem(SKIP_ONBOARDING) === "true";
|
||||
return localStorage.getItem(SKIP_ONBOARDING) === 'true';
|
||||
};
|
||||
|
@ -1,2 +1,2 @@
|
||||
import { createBrowserHistory } from "history";
|
||||
import { createBrowserHistory } from 'history';
|
||||
export default createBrowserHistory();
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { pushDStree, span, RefItem } from "store/actions";
|
||||
import { pushDStree, RefItem,span } from 'store/actions';
|
||||
// PNOTE - should the data be taken from redux or only through props? - Directly as arguments
|
||||
|
||||
export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
|
||||
// Initializing tree. What should be returned is trace is empty? We should have better error handling
|
||||
let tree: pushDStree = {
|
||||
id: "empty",
|
||||
name: "default",
|
||||
id: 'empty',
|
||||
name: 'default',
|
||||
value: 0,
|
||||
time: 0,
|
||||
startTime: 0,
|
||||
@ -24,7 +24,7 @@ export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
|
||||
//May1
|
||||
//https://stackoverflow.com/questions/13315131/enforcing-the-type-of-the-indexed-members-of-a-typescript-object
|
||||
|
||||
let mapped_array: { [id: string]: span } = {};
|
||||
const mapped_array: { [id: string]: span } = {};
|
||||
|
||||
for (let i = 0; i < spanlist.length; i++) {
|
||||
mapped_array[spanlist[i][1]] = spanlist[i];
|
||||
@ -36,15 +36,15 @@ export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
|
||||
|
||||
// console.log(`In SpanTreeUtil: mapped_arrayis ${mapped_array}`);
|
||||
|
||||
for (let id in mapped_array) {
|
||||
let child_span = mapped_array[id];
|
||||
for (const id in mapped_array) {
|
||||
const child_span = mapped_array[id];
|
||||
|
||||
//mapping tags to new structure
|
||||
let tags_temp = [];
|
||||
const tags_temp = [];
|
||||
if (child_span[7] !== null && child_span[8] !== null) {
|
||||
if (
|
||||
typeof child_span[7] === "string" &&
|
||||
typeof child_span[8] === "string"
|
||||
typeof child_span[7] === 'string' &&
|
||||
typeof child_span[8] === 'string'
|
||||
) {
|
||||
tags_temp.push({ key: child_span[7], value: child_span[8] });
|
||||
} else if (child_span[7].length > 0 && child_span[8].length > 0) {
|
||||
@ -54,39 +54,39 @@ export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
|
||||
}
|
||||
}
|
||||
|
||||
let push_object: pushDStree = {
|
||||
const push_object: pushDStree = {
|
||||
id: child_span[1],
|
||||
name: child_span[3] + ": " + child_span[4],
|
||||
name: child_span[3] + ': ' + child_span[4],
|
||||
value: parseInt(child_span[6]),
|
||||
time: parseInt(child_span[6]),
|
||||
startTime: child_span[0],
|
||||
tags: tags_temp,
|
||||
children: mapped_array[id][10],
|
||||
};
|
||||
let referencesArr = mapped_array[id][9];
|
||||
const referencesArr = mapped_array[id][9];
|
||||
let refArray = [];
|
||||
if (typeof referencesArr === "string") {
|
||||
if (typeof referencesArr === 'string') {
|
||||
refArray.push(referencesArr);
|
||||
} else {
|
||||
refArray = referencesArr;
|
||||
}
|
||||
let references: RefItem[] = [];
|
||||
const references: RefItem[] = [];
|
||||
|
||||
refArray.forEach((element) => {
|
||||
element = element
|
||||
.replaceAll("{", "")
|
||||
.replaceAll("}", "")
|
||||
.replaceAll(" ", "");
|
||||
let arr = element.split(",");
|
||||
let refItem = { traceID: "", spanID: "", refType: "" };
|
||||
.replaceAll('{', '')
|
||||
.replaceAll('}', '')
|
||||
.replaceAll(' ', '');
|
||||
const arr = element.split(',');
|
||||
const refItem = { traceID: '', spanID: '', refType: '' };
|
||||
arr.forEach((obj) => {
|
||||
let arr2 = obj.split("=");
|
||||
if (arr2[0] === "TraceId") {
|
||||
refItem["traceID"] = arr2[1];
|
||||
} else if (arr2[0] === "SpanId") {
|
||||
refItem["spanID"] = arr2[1];
|
||||
} else if (arr2[0] === "RefType") {
|
||||
refItem["refType"] = arr2[1];
|
||||
const arr2 = obj.split('=');
|
||||
if (arr2[0] === 'TraceId') {
|
||||
refItem['traceID'] = arr2[1];
|
||||
} else if (arr2[0] === 'SpanId') {
|
||||
refItem['spanID'] = arr2[1];
|
||||
} else if (arr2[0] === 'RefType') {
|
||||
refItem['refType'] = arr2[1];
|
||||
}
|
||||
});
|
||||
|
||||
@ -94,11 +94,11 @@ export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
|
||||
});
|
||||
|
||||
if (references.length !== 0 && references[0].spanID.length !== 0) {
|
||||
if (references[0].refType === "CHILD_OF") {
|
||||
let parentID = references[0].spanID;
|
||||
if (references[0].refType === 'CHILD_OF') {
|
||||
const parentID = references[0].spanID;
|
||||
// console.log(`In SpanTreeUtil: mapped_array[parentID] is ${mapped_array[parentID]}`);
|
||||
|
||||
if (typeof mapped_array[parentID] !== "undefined") {
|
||||
if (typeof mapped_array[parentID] !== 'undefined') {
|
||||
//checking for undefined [10] issue
|
||||
mapped_array[parentID][10].push(push_object);
|
||||
} else {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user