Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5381dc7e56 | ||
|
|
76848b8925 | ||
|
|
3f32322385 | ||
|
|
29c26777b6 | ||
|
|
f861a5c77d | ||
|
|
d1a4bb10ea | ||
|
|
41e2c6b075 | ||
|
|
b5b0725cc4 | ||
|
|
3acef9c86a | ||
|
|
48e32878e6 | ||
|
|
f070bdf5b9 | ||
|
|
888e3ff79b | ||
|
|
3e8c9308b6 | ||
|
|
a3c1080519 | ||
|
|
350a49060f | ||
|
|
35abf2dddf | ||
|
|
9a32db608f | ||
|
|
11c94c0fbb | ||
|
|
5431333b1a | ||
|
|
dd34bd5990 | ||
|
|
a8adadcfff | ||
|
|
db3c7a3b9f | ||
|
|
1d479ca158 | ||
|
|
76e7bd5292 | ||
|
|
2f99a661de | ||
|
|
b1169c7315 | ||
|
|
ec0059dbd8 | ||
|
|
3d4bdec4ba | ||
|
|
437de3682c | ||
|
|
9e76106ee0 | ||
|
|
553967f76b | ||
|
|
beb15e0a5f | ||
|
|
27e2ceffaa | ||
|
|
7de1737f5f | ||
|
|
7917b5f3b4 | ||
|
|
470b68aa67 | ||
|
|
1255da08dc | ||
|
|
8c21aeb2a9 | ||
|
|
6f2b66c286 | ||
|
|
d09c63331d | ||
|
|
af68ca52ba | ||
|
|
655f8b65a2 | ||
|
|
c07f68333e | ||
|
|
421a102291 | ||
|
|
1d5ce423f2 | ||
|
|
0c12eaf89b | ||
|
|
09586faed2 | ||
|
|
bf0c1a3dcc | ||
|
|
77abb47b4c | ||
|
|
2e71230bbf | ||
|
|
bf2002d6a2 | ||
|
|
59749d0576 | ||
|
|
c9c6ccc687 | ||
|
|
88082c1278 | ||
|
|
84f150bc18 | ||
|
|
299e80ca49 | ||
|
|
7127dec6f6 | ||
|
|
6afb91fa84 | ||
|
|
72f5688194 | ||
|
|
a118c3c8a1 | ||
|
|
9baf873521 | ||
|
|
12911db945 | ||
|
|
bd149f4364 | ||
|
|
c69b9ae62a | ||
|
|
bc3f16d3de | ||
|
|
61bbd5551b | ||
|
|
286577d13d | ||
|
|
dbd0701779 | ||
|
|
0c7a5ce3c7 | ||
|
|
a92381df1b | ||
|
|
eb1509d385 | ||
|
|
34e33af290 | ||
|
|
c0004cd51c | ||
|
|
10bf545c65 | ||
|
|
7d2bcf11c3 | ||
|
|
3ff7ace54e | ||
|
|
abdfe6ccc5 | ||
|
|
aa398263fb | ||
|
|
ace02486e0 | ||
|
|
b318ba6b2f | ||
|
|
de4be411f4 | ||
|
|
362f264bae | ||
|
|
e94d984cdb | ||
|
|
bf0267d579 | ||
|
|
e4b3ea1f34 | ||
|
|
4ee6d4b546 | ||
|
|
a7836c26d0 | ||
|
|
15eb5364d5 | ||
|
|
47bf512a33 | ||
|
|
2776bfa311 | ||
|
|
8c7ac88f84 | ||
|
|
a08ad9e2cf | ||
|
|
d312398f18 | ||
|
|
d891c3e118 | ||
|
|
1e7b68203f | ||
|
|
3d152e23cd | ||
|
|
47cf1eebf7 | ||
|
|
6c84882dca | ||
|
|
a4424eca0e | ||
|
|
77992a59bc | ||
|
|
3cbb071138 | ||
|
|
9cd6e5cabe | ||
|
|
13bec63fca | ||
|
|
f2164a1a86 | ||
|
|
8a4f58e77b | ||
|
|
51a24673b9 | ||
|
|
c94feb9af2 | ||
|
|
a8668d19a8 | ||
|
|
a8e81c9666 | ||
|
|
2eed75560d | ||
|
|
8d6fb7f897 | ||
|
|
4cd0088029 | ||
|
|
872c8adbbb | ||
|
|
bba7344bae | ||
|
|
51fe634566 | ||
|
|
af58d085a0 | ||
|
|
5b9b344816 | ||
|
|
1caa07e0af | ||
|
|
ae23cec8d6 | ||
|
|
5afc04f205 | ||
|
|
6aed23ce66 | ||
|
|
007e2e7b78 | ||
|
|
762a3cdfcd | ||
|
|
308f8f8fed | ||
|
|
588bf2b93a | ||
|
|
fff38b58d2 | ||
|
|
cbd2036613 | ||
|
|
7ef72d4147 | ||
|
|
07af5c843a | ||
|
|
e524ce5743 | ||
|
|
24e1346521 | ||
|
|
62e77613a6 | ||
|
|
56c0265660 | ||
|
|
91b1d08dff | ||
|
|
239c2cb859 | ||
|
|
4173258d0a | ||
|
|
1cbbdd8265 | ||
|
|
433f3f3d94 | ||
|
|
fed23a6ab9 | ||
|
|
b979c24cb4 | ||
|
|
e4b41b1a27 | ||
|
|
44495b7669 | ||
|
|
cc3133b2d6 | ||
|
|
9c83319143 | ||
|
|
571c08c58e | ||
|
|
092cfc7804 | ||
|
|
245050aac2 | ||
|
|
606fa6591d | ||
|
|
a1468cf126 |
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Bug description
|
||||
|
||||
*Please describe.*
|
||||
*If this affects the front-end, screenshots would be of great help.*
|
||||
|
||||
## Expected behavior
|
||||
|
||||
|
||||
|
||||
## How to reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Version information
|
||||
* **Signoz version**:
|
||||
* **Browser version**:
|
||||
* **Your OS and version**:
|
||||
|
||||
## Additional context
|
||||
|
||||
|
||||
#### *Thank you* for your bug report – we love squashing them!
|
||||
27
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Is your feature request related to a problem?
|
||||
|
||||
*Please describe.*
|
||||
|
||||
## Describe the solution you'd like
|
||||
|
||||
|
||||
|
||||
## Describe alternatives you've considered
|
||||
|
||||
|
||||
|
||||
## Additional context
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
|
||||
|
||||
#### *Thank you* for your feature request – we love each and every one!
|
||||
33
.github/ISSUE_TEMPLATE/performance-issue-report.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/performance-issue-report.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: Performance issue report
|
||||
about: Long response times, high resource usage? Ensuring that SigNoz is scalable
|
||||
is our top priority
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## In what situation are you experiencing subpar performance?
|
||||
|
||||
*Please describe.*
|
||||
|
||||
## How to reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Your Environment
|
||||
|
||||
- [ ] Linux
|
||||
- [ ] Mac
|
||||
- [ ] Windows
|
||||
|
||||
Please provide details of OS version etc.
|
||||
|
||||
## Additional context
|
||||
|
||||
|
||||
|
||||
#### *Thank you* for your performance issue report – we want SigNoz to be blazing fast!
|
||||
29
.github/release-drafter.yml
vendored
Normal file
29
.github/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name-template: 'v$RESOLVED_VERSION'
|
||||
tag-template: 'v$RESOLVED_VERSION'
|
||||
template: |
|
||||
# What's Changed
|
||||
$CHANGES
|
||||
autolabeler:
|
||||
- label: 'chore'
|
||||
title:
|
||||
- '/chore/i'
|
||||
- label: 'bug'
|
||||
title:
|
||||
- '/fix/i'
|
||||
- label: 'enhancement'
|
||||
title:
|
||||
- '/feat/i'
|
||||
|
||||
categories:
|
||||
- title: '🚀 Features'
|
||||
label: 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'bug'
|
||||
- title: '🧰 Maintenance'
|
||||
label: 'chore'
|
||||
- title: 'Breaking'
|
||||
label: 'breaking'
|
||||
|
||||
exclude-labels:
|
||||
- 'skip-changelog'
|
||||
25
.github/workflows/README.md
vendored
Normal file
25
.github/workflows/README.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
To run GitHub workflow, a few environment variables needs to add in GitHub secrets
|
||||
|
||||
#### Environment Variables
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th> Variables </th>
|
||||
<th> Description </th>
|
||||
<th> Example </th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> REPONAME </td>
|
||||
<td> Provide the DockerHub user/organisation name of the image. </td>
|
||||
<td> signoz</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> DOCKERHUB_USERNAME </td>
|
||||
<td> Docker hub username </td>
|
||||
<td> signoz</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> DOCKERHUB_TOKEN </td>
|
||||
<td> Docker hub password/token with push permission </td>
|
||||
<td> **** </td>
|
||||
</tr>
|
||||
69
.github/workflows/build.yaml
vendored
Normal file
69
.github/workflows/build.yaml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: build-pipeline
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- v*
|
||||
paths:
|
||||
- 'pkg/**'
|
||||
- 'frontend/**'
|
||||
|
||||
jobs:
|
||||
get_filters:
|
||||
runs-on: ubuntu-latest
|
||||
# Set job outputs to values from filter step
|
||||
outputs:
|
||||
frontend: ${{ steps.filter.outputs.frontend }}
|
||||
query-service: ${{ steps.filter.outputs.query-service }}
|
||||
flattener: ${{ steps.filter.outputs.flattener }}
|
||||
steps:
|
||||
# For pull requests it's not necessary to checkout the code
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
frontend:
|
||||
- 'frontend/**'
|
||||
query-service:
|
||||
- 'pkg/query-service/**'
|
||||
flattener:
|
||||
- 'pkg/processors/flattener/**'
|
||||
|
||||
build-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get_filters
|
||||
if: ${{ needs.get_filters.outputs.frontend == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Build frontend docker image
|
||||
shell: bash
|
||||
run: |
|
||||
make build-frontend-amd64
|
||||
|
||||
build-query-service:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get_filters
|
||||
if: ${{ needs.get_filters.outputs.query-service == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Build query-service image
|
||||
shell: bash
|
||||
run: |
|
||||
make build-flattener-amd64
|
||||
|
||||
build-flattener:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get_filters
|
||||
if: ${{ needs.get_filters.outputs.flattener == 'true' }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Build flattener docker image
|
||||
shell: bash
|
||||
run: |
|
||||
make build-query-service-amd64
|
||||
14
.github/workflows/commitlint.yml
vendored
Normal file
14
.github/workflows/commitlint.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: commitlint
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
lint-commits:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.1
|
||||
with:
|
||||
# we actually need "github.event.pull_request.commits + 1" commit
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v2.1.0
|
||||
# or just "yarn" if you depend on "@commitlint/cli" already
|
||||
- run: yarn add @commitlint/cli
|
||||
- run: yarn run commitlint --from HEAD~${{ github.event.pull_request.commits }} --to HEAD
|
||||
163
.github/workflows/push.yaml
vendored
Normal file
163
.github/workflows/push.yaml
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
name: push-pipeline
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- ^v[0-9]*.[0-9]*.x$
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
get-envs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- shell: bash
|
||||
run: |
|
||||
img_tag=""
|
||||
array=(`echo ${GITHUB_REF} | sed 's/\//\n/g'`)
|
||||
if [ ${array[1]} == "tags" ]
|
||||
then
|
||||
echo "tag build"
|
||||
img_tag=${GITHUB_REF#refs/*/v}
|
||||
else
|
||||
echo "non tag build"
|
||||
img_tag="latest"
|
||||
fi
|
||||
# This is a condition where image tag looks like "pull/<pullrequest-name>" during pull request build
|
||||
NEW_IMG_TAG=`echo $img_tag | sed "s/\//-/g"`
|
||||
echo $NEW_IMG_TAG
|
||||
echo export IMG_TAG=$NEW_IMG_TAG >> env-vars
|
||||
echo export FRONTEND_IMAGE="frontend" >> env-vars
|
||||
echo export QUERY_SERVICE="query-service" >> env-vars
|
||||
echo export FLATTENER_PROCESSOR="flattener-processor" >> env-vars
|
||||
|
||||
- name: Uploading envs
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: env_artifact
|
||||
path: env-vars
|
||||
|
||||
build-and-push-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get-envs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Downloading image artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: env_artifact
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build & Push Frontend Docker Image
|
||||
shell: bash
|
||||
env:
|
||||
FRONTEND_DIRECTORY: "frontend"
|
||||
REPONAME: ${{ secrets.REPONAME }}
|
||||
FRONTEND_DOCKER_IMAGE: ${FRONTEND_IMAGE}
|
||||
DOCKER_TAG: ${IMG_TAG}
|
||||
run: |
|
||||
branch=${GITHUB_REF#refs/*/}
|
||||
array=(`echo ${GITHUB_REF} | sed 's/\//\n/g'`)
|
||||
if [ $branch == "main" ] || [ ${array[1]} == "tags" ] || [[ $branch =~ ^v[0-9]*.[0-9]*.x$ ]]
|
||||
then
|
||||
source env-vars
|
||||
make build-push-frontend
|
||||
fi
|
||||
|
||||
build-and-push-query-service:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get-envs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Downloading image artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: env_artifact
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build & Push Query Service Docker Image
|
||||
shell: bash
|
||||
env:
|
||||
QUERY_SERVICE_DIRECTORY: "pkg/query-service"
|
||||
REPONAME: ${{ secrets.REPONAME }}
|
||||
QUERY_SERVICE_DOCKER_IMAGE: ${QUERY_SERVICE}
|
||||
DOCKER_TAG: ${IMG_TAG}
|
||||
run: |
|
||||
branch=${GITHUB_REF#refs/*/}
|
||||
array=(`echo ${GITHUB_REF} | sed 's/\//\n/g'`)
|
||||
if [ $branch == "main" ] || [ ${array[1]} == "tags" ] || [[ $branch =~ ^v[0-9]*.[0-9]*.x$ ]]
|
||||
then
|
||||
source env-vars
|
||||
make build-push-query-service
|
||||
fi
|
||||
|
||||
build-and-push-flattener:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- get-envs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Downloading image artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: env_artifact
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build & Push Flattener Processor Docker Image
|
||||
shell: bash
|
||||
env:
|
||||
FLATTENER_DIRECTORY: "pkg/processors/flattener"
|
||||
REPONAME: ${{ secrets.REPONAME }}
|
||||
FLATTERNER_DOCKER_IMAGE: ${FLATTENER_PROCESSOR}
|
||||
DOCKER_TAG: ${IMG_TAG}
|
||||
run: |
|
||||
branch=${GITHUB_REF#refs/*/}
|
||||
array=(`echo ${GITHUB_REF} | sed 's/\//\n/g'`)
|
||||
if [ $branch == "main" ] || [ ${array[1]} == "tags" ] || [[ $branch =~ ^v[0-9]*.[0-9]*.x$ ]]
|
||||
then
|
||||
source env-vars
|
||||
make build-push-flattener
|
||||
fi
|
||||
29
.github/workflows/release-drafter.yml
vendored
Normal file
29
.github/workflows/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Release Drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
# branches to consider in the event; optional, defaults to all
|
||||
branches:
|
||||
- main
|
||||
# pull_request event is required only for autolabeler
|
||||
pull_request:
|
||||
# Only following types are handled by the action, but one can default to all as well
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# (Optional) GitHub Enterprise requires GHE_HOST variable set
|
||||
#- name: Set GHE_HOST
|
||||
# run: |
|
||||
# echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV
|
||||
|
||||
# Drafts your next Release notes as Pull Requests are merged into "master"
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
# (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
|
||||
# with:
|
||||
# config-name: my-config.yml
|
||||
# disable-autolabeler: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,3 +30,4 @@ frontend/src/constants/env.ts
|
||||
**/storage
|
||||
**/locust-scripts/__pycache__/
|
||||
|
||||
frontend/*.env
|
||||
|
||||
@@ -1,9 +1,75 @@
|
||||
# How to Contribute
|
||||
|
||||
You can always reach out to ankit@signoz.io to understand more about the repo and product. We are very responsive over email and [slack](https://signoz-community.slack.com/join/shared_invite/zt-kj26gm1u-Xe3CYxCu0bGXCrCqKipjOA#/).
|
||||
There are primarily 3 areas in which you can contribute in SigNoz
|
||||
|
||||
- Frontend ( written in Typescript, React)
|
||||
- Query Service (written in Go)
|
||||
- Flattener Processor (written in Go)
|
||||
|
||||
Depending upon your area of expertise & interest, you can chose one or more to contribute. Below are detailed instructions to contribute in each area
|
||||
|
||||
# Develop Frontend
|
||||
|
||||
Need to update [https://github.com/SigNoz/signoz/tree/main/frontend](https://github.com/SigNoz/signoz/tree/main/frontend)
|
||||
|
||||
### Contribute to Frontend with Docker installation of SigNoz
|
||||
|
||||
- `git clone https://github.com/SigNoz/signoz.git && cd signoz`
|
||||
- comment out frontend service section at `deploy/docker/clickhouse-setup/docker-compose.yaml#L38`
|
||||
- run `cd deploy && docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d` (this will install signoz locally without the frontend service)
|
||||
- `cd ../frontend` and change baseURL to `http://localhost:8080` in file `src/constants/env.ts`
|
||||
- `yarn install`
|
||||
- `yarn dev`
|
||||
|
||||
### Contribute to Frontend without installing SigNoz backend
|
||||
|
||||
If you don't want to install SigNoz backend just for doing frontend development, we can provide you with test environments which you can use as the backend. Please ping us in #contributing channel in our [slack community](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA) and we will DM you with `<test environment URL>`
|
||||
|
||||
- `git clone https://github.com/SigNoz/signoz.git && cd signoz/frontend`
|
||||
- change baseURL to `<test environment URL>` in file `src/constants/env.ts`
|
||||
- `yarn install`
|
||||
- `yarn dev`
|
||||
|
||||
**_Frontend should now be accessible at `http://localhost:3000/application`_**
|
||||
|
||||
# Contribute to Query-Service
|
||||
|
||||
Need to update [https://github.com/SigNoz/signoz/tree/main/pkg/query-service](https://github.com/SigNoz/signoz/tree/main/pkg/query-service)
|
||||
|
||||
### To run ClickHouse setup (recommended for local development)
|
||||
|
||||
- `git clone https://github.com/SigNoz/signoz.git && cd signoz/deploy`
|
||||
- comment out frontend service section at `docker/clickhouse-setup/docker-compose.yaml#L38`
|
||||
- comment out query-service section at `docker/clickhouse-setup/docker-compose.yaml#L22`
|
||||
- Run `docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d` (this will install signoz locally without the frontend and query-service)
|
||||
- `STORAGE=clickhouse ClickHouseUrl=tcp://localhost:9001 go run main.go`
|
||||
|
||||
**_Query Service should now be available at `http://localhost:8080`_**
|
||||
|
||||
> If you want to see how, frontend plays with query service, you can run frontend also in you local env with the baseURL changed to `http://localhost:8080` in file `src/constants/env.ts` as the query-service is now running at port `8080`
|
||||
|
||||
# Contribute to Flattener Processor
|
||||
|
||||
Not needed to run for the ClickHouse setup
|
||||
|
||||
more info at [https://github.com/SigNoz/signoz/tree/main/pkg/processors/flattener](https://github.com/SigNoz/signoz/tree/main/pkg/processors/flattener)
|
||||
|
||||
## General Instructions
|
||||
|
||||
You can always reach out to `ankit@signoz.io` to understand more about the repo and product. We are very responsive over email and [slack](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA).
|
||||
|
||||
- You can create a PR (Pull Request)
|
||||
- If you find any bugs, please create an issue
|
||||
- If you find anything missing in documentation, you can create an issue with label **documentation**
|
||||
- If you want to build any new feature, please create an issue with label `enhancement`
|
||||
- If you want to discuss something about the product, start a new [discussion](https://github.com/SigNoz/signoz/discussions)
|
||||
|
||||
#### If you want to build any new feature, please create an issue with label `enhancement`
|
||||
### Conventions to follow when submitting commits, PRs
|
||||
1. We try to follow https://www.conventionalcommits.org/en/v1.0.0/
|
||||
|
||||
More specifically the commits and PRs should have type specifiers prefixed in the name. [This](https://www.conventionalcommits.org/en/v1.0.0/#specification) should give you a better idea.
|
||||
|
||||
e.g. If you are submitting a fix for an issue in frontend - PR name should be prefixed with `fix(FE):`
|
||||
|
||||
2. Follow [GitHub Flow](https://guides.github.com/introduction/flow/) guidelines for your contribution flows
|
||||
|
||||
3. Feel free to ping us on `#contributing` or `#contributing-frontend` on our slack community if you need any help on this :)
|
||||
|
||||
69
Makefile
Normal file
69
Makefile
Normal file
@@ -0,0 +1,69 @@
|
||||
# Reference Guide - https://www.gnu.org/software/make/manual/make.html
|
||||
#
|
||||
# Internal variables or constants.
|
||||
#
|
||||
FRONTEND_DIRECTORY ?= frontend
|
||||
FLATTENER_DIRECTORY ?= pkg/processors/flattener
|
||||
QUERY_SERVICE_DIRECTORY ?= pkg/query-service
|
||||
|
||||
REPONAME ?= signoz
|
||||
DOCKER_TAG ?= latest
|
||||
|
||||
FRONTEND_DOCKER_IMAGE ?= frontend
|
||||
FLATTERNER_DOCKER_IMAGE ?= query-service
|
||||
QUERY_SERVICE_DOCKER_IMAGE ?= flattener-processor
|
||||
|
||||
all: build-push-frontend build-push-query-service build-push-flattener
|
||||
# Steps to build and push docker image of frontend
|
||||
.PHONY: build-frontend-amd64 build-push-frontend
|
||||
# Step to build docker image of frontend in amd64 (used in build pipeline)
|
||||
build-frontend-amd64:
|
||||
@echo "------------------"
|
||||
@echo "--> Building frontend docker image for amd64"
|
||||
@echo "------------------"
|
||||
@cd $(FRONTEND_DIRECTORY) && \
|
||||
docker build -f Dockerfile --no-cache -t $(REPONAME)/$(FRONTEND_DOCKER_IMAGE):$(DOCKER_TAG) . --build-arg TARGETPLATFORM="linux/amd64"
|
||||
|
||||
# Step to build and push docker image of frontend(used in push pipeline)
|
||||
build-push-frontend:
|
||||
@echo "------------------"
|
||||
@echo "--> Building and pushing frontend docker image"
|
||||
@echo "------------------"
|
||||
@cd $(FRONTEND_DIRECTORY) && \
|
||||
docker buildx build --file Dockerfile --progress plane --no-cache --push --platform linux/amd64 --tag $(REPONAME)/$(FRONTEND_DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||
|
||||
# Steps to build and push docker image of query service
|
||||
.PHONY: build-query-service-amd64 build-push-query-service
|
||||
# Step to build docker image of query service in amd64 (used in build pipeline)
|
||||
build-query-service-amd64:
|
||||
@echo "------------------"
|
||||
@echo "--> Building query-service docker image for amd64"
|
||||
@echo "------------------"
|
||||
@cd $(QUERY_SERVICE_DIRECTORY) && \
|
||||
docker build -f Dockerfile --no-cache -t $(REPONAME)/$(QUERY_SERVICE_DOCKER_IMAGE):$(DOCKER_TAG) . --build-arg TARGETPLATFORM="linux/amd64"
|
||||
|
||||
# Step to build and push docker image of query in amd64 and arm64 (used in push pipeline)
|
||||
build-push-query-service:
|
||||
@echo "------------------"
|
||||
@echo "--> Building and pushing query-service docker image"
|
||||
@echo "------------------"
|
||||
@cd $(QUERY_SERVICE_DIRECTORY) && \
|
||||
docker buildx build --file Dockerfile --progress plane --no-cache --push --platform linux/arm64,linux/amd64 --tag $(REPONAME)/$(QUERY_SERVICE_DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||
|
||||
# Steps to build and push docker image of flattener
|
||||
.PHONY: build-flattener-amd64 build-push-flattener
|
||||
# Step to build docker image of flattener in amd64 (used in build pipeline)
|
||||
build-flattener-amd64:
|
||||
@echo "------------------"
|
||||
@echo "--> Building flattener docker image for amd64"
|
||||
@echo "------------------"
|
||||
@cd $(FLATTENER_DIRECTORY) && \
|
||||
docker build -f Dockerfile --no-cache -t $(REPONAME)/$(FLATTERNER_DOCKER_IMAGE):$(DOCKER_TAG) . --build-arg TARGETPLATFORM="linux/amd64"
|
||||
|
||||
# Step to build and push docker image of flattener in amd64 (used in push pipeline)
|
||||
build-push-flattener:
|
||||
@echo "------------------"
|
||||
@echo "--> Building and pushing flattener docker image"
|
||||
@echo "------------------"
|
||||
@cd $(FLATTENER_DIRECTORY) && \
|
||||
docker buildx build --file Dockerfile --progress plane --no-cache --push --platform linux/arm64,linux/amd64 --tag $(REPONAME)/$(FLATTERNER_DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||
129
README.md
129
README.md
@@ -8,23 +8,42 @@
|
||||
<img alt="License" src="https://img.shields.io/badge/license-MIT-brightgreen"> </a>
|
||||
<img alt="Downloads" src="https://img.shields.io/docker/pulls/signoz/frontend?label=Downloads"> </a>
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/signoz/signoz"> </a>
|
||||
<a href="https://twitter.com/intent/tweet?text=Monitor%20your%20applications%20and%20troubleshoot%20problems%20with%20SigNoz,%20an%20open-source%20alternative%20to%20DataDog,%20NewRelic.&url=https://signoz.io/&via=SigNoz_io&hashtags=opensource,signoz,observability">
|
||||
<a href="https://twitter.com/intent/tweet?text=Monitor%20your%20applications%20and%20troubleshoot%20problems%20with%20SigNoz,%20an%20open-source%20alternative%20to%20DataDog,%20NewRelic.&url=https://signoz.io/&via=SigNozHQ&hashtags=opensource,signoz,observability">
|
||||
<img alt="tweet" src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social"> </a>
|
||||
</p>
|
||||
|
||||
|
||||
<h3 align="center">
|
||||
<a href="https://signoz.io/docs"><b>Documentation</b></a> •
|
||||
<a href="https://github.com/SigNoz/signoz/blob/main/README.zh-cn.md"><b>ReadMe in Chinese</b></a> •
|
||||
<a href="https://bit.ly/signoz-slack"><b>Slack Community</b></a> •
|
||||
<a href="https://twitter.com/SigNozHq"><b>Twitter</b></a>
|
||||
</h3>
|
||||
|
||||
##
|
||||
|
||||
SigNoz helps developer monitor applications and troubleshoot problems in their deployed applications. SigNoz uses distributed tracing to gain visibility into your software stack.
|
||||
SigNoz helps developers monitor applications and troubleshoot problems in their deployed applications. SigNoz uses distributed tracing to gain visibility into your software stack.
|
||||
|
||||
👉 You can see metrics like p99 latency, error rates for your services, external API calls and individual end points.
|
||||
|
||||
👉 You can find the root cause of the problem by going to the exact traces which are causing the problem and see detailed flamegraphs of individual request traces.
|
||||
|
||||
<!--  -->
|
||||
|
||||

|
||||

|
||||
|
||||
### 👇 Features:
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## Join our Slack community
|
||||
|
||||
Come say Hi to us on [Slack](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA) 👋
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Features.svg" width="50px" />
|
||||
|
||||
## Features:
|
||||
|
||||
- Application overview metrics like RPS, 50th/90th/99th Percentile latencies, and Error Rate
|
||||
- Slowest endpoints in your application
|
||||
@@ -33,7 +52,11 @@ SigNoz helps developer monitor applications and troubleshoot problems in their d
|
||||
- Aggregate metrics on filtered traces. Eg, you can get error rate and 99th percentile latency of `customer_type: gold` or `deployment_version: v2` or `external_call: paypal`
|
||||
- Unified UI for metrics and traces. No need to switch from Prometheus to Jaeger to debug issues.
|
||||
|
||||
### 🤓 Why SigNoz?
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/WhatsCool.svg" width="50px" />
|
||||
|
||||
## Why SigNoz?
|
||||
|
||||
Being developers, we found it annoying to rely on closed source SaaS vendors for every small feature we wanted. Closed source vendors often surprise you with huge month end bills without any transparency.
|
||||
|
||||
@@ -41,7 +64,7 @@ We wanted to make a self-hosted & open source version of tools like DataDog, New
|
||||
|
||||
Being open source also gives you complete control of your configuration, sampling, uptimes. You can also build modules over SigNoz to extend business specific capabilities
|
||||
|
||||
### 👊🏻 Languages supported:
|
||||
### Languages supported:
|
||||
|
||||
We support [OpenTelemetry](https://opentelemetry.io) as the library which you can use to instrument your applications. So any framework and language supported by OpenTelemetry is also supported by SigNoz. Some of the main supported languages are:
|
||||
|
||||
@@ -52,54 +75,84 @@ We support [OpenTelemetry](https://opentelemetry.io) as the library which you ca
|
||||
|
||||
You can find the complete list of languages here - https://opentelemetry.io/docs/
|
||||
|
||||
# Getting Started
|
||||
<br /><br />
|
||||
|
||||
## Deploy using docker-compose
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Philosophy.svg" width="50px" />
|
||||
|
||||
We have a tiny-cluster setup and a standard setup to deploy using docker-compose.
|
||||
Follow the steps listed at https://signoz.io/docs/deployment/docker/.
|
||||
The troubleshooting instructions at https://signoz.io/docs/deployment/docker/#troubleshooting may be helpful
|
||||
## Getting Started
|
||||
|
||||
|
||||
### Deploy using Docker
|
||||
|
||||
## Deploy in Kubernetes using Helm
|
||||
Please follow the steps listed [here](https://signoz.io/docs/deployment/docker/) to install using docker
|
||||
|
||||
Below steps will install the SigNoz in `platform` namespace inside your k8s cluster.
|
||||
The [troubleshooting instructions](https://signoz.io/docs/deployment/troubleshooting) may be helpful if you face any issues.
|
||||
|
||||
```console
|
||||
git clone https://github.com/SigNoz/signoz.git && cd signoz
|
||||
helm dependency update deploy/kubernetes/platform
|
||||
kubectl create ns platform
|
||||
helm -n platform install signoz deploy/kubernetes/platform
|
||||
kubectl -n platform apply -Rf deploy/kubernetes/jobs
|
||||
kubectl -n platform apply -f deploy/kubernetes/otel-collector
|
||||
```
|
||||
<p>  </p>
|
||||
|
||||
|
||||
### Deploy in Kubernetes using Helm
|
||||
|
||||
\*_You can choose a different namespace too. In that case, you need to point your applications to correct address to send traces. In our sample application just change the `JAEGER_ENDPOINT` environment variable in `sample-apps/hotrod/deployment.yaml`_
|
||||
Please follow the steps listed [here](https://signoz.io/docs/deployment/helm_chart) to install using helm charts
|
||||
|
||||
|
||||
### Test HotROD application with SigNoz
|
||||
<br /><br />
|
||||
|
||||
```console
|
||||
kubectl create ns sample-application
|
||||
kubectl -n sample-application apply -Rf sample-apps/hotrod/
|
||||
```
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/UseSigNoz.svg" width="50px" />
|
||||
|
||||
### How to generate load
|
||||
## Comparisons to Familiar Tools
|
||||
|
||||
`kubectl -n sample-application run strzal --image=djbingham/curl --restart='OnFailure' -i --tty --rm --command -- curl -X POST -F 'locust_count=6' -F 'hatch_rate=2' http://locust-master:8089/swarm`
|
||||
### SigNoz vs Prometheus
|
||||
|
||||
### See UI
|
||||
Prometheus is good if you want to do just metrics. But if you want to have a seamless experience between metrics and traces, then current experience of stitching together Prometheus & Jaeger is not great.
|
||||
|
||||
`kubectl -n platform port-forward svc/signoz-frontend 3000:3000`
|
||||
Our goal is to provide an integrated UI between metrics & traces - similar to what SaaS vendors like Datadog provides - and give advanced filtering and aggregation over traces, something which Jaeger currently lack.
|
||||
|
||||
### How to stop load
|
||||
<p>  </p>
|
||||
|
||||
`kubectl -n sample-application run strzal --image=djbingham/curl --restart='OnFailure' -i --tty --rm --command -- curl http://locust-master:8089/stop`
|
||||
### SigNoz vs Jaeger
|
||||
|
||||
# Documentation
|
||||
Jaeger only does distributed tracing. SigNoz does both metrics and traces, and we also have log management in our roadmap.
|
||||
|
||||
You can find docs at https://signoz.io/docs/deployment/docker. If you need any clarification or find something missing, feel free to raise a GitHub issue with the label `documentation` or reach out to us at the community slack channel.
|
||||
Moreover, SigNoz has few more advanced features wrt Jaeger:
|
||||
|
||||
# Community
|
||||
- Jaegar UI doesn’t show any metrics on traces or on filtered traces
|
||||
- Jaeger can’t get aggregates on filtered traces. For example, p99 latency of requests which have tag - customer_type='premium'. This can be done easily on SigNoz
|
||||
|
||||
Join the [slack community](https://app.slack.com/client/T01HWUTP0LT#/) to know more about distributed tracing, observability, or SigNoz and to connect with other users and contributors.
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributors.svg" width="50px" />
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
We ❤️ contributions big or small. Please read [CONTRIBUTING.md](CONTRIBUTING.md) to get started with making contributions to SigNoz.
|
||||
|
||||
Not sure how to get started? Just ping us on `#contributing` in our [slack community](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA)
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/DevelopingLocally.svg" width="50px" />
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find docs at https://signoz.io/docs/. If you need any clarification or find something missing, feel free to raise a GitHub issue with the label `documentation` or reach out to us at the community slack channel.
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## Community
|
||||
|
||||
Join the [slack community](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA) to know more about distributed tracing, observability, or SigNoz and to connect with other users and contributors.
|
||||
|
||||
If you have any ideas, questions, or any feedback, please share on our [Github Discussions](https://github.com/SigNoz/signoz/discussions)
|
||||
|
||||
As always, thanks to our amazing contributors!
|
||||
|
||||
<a href="https://github.com/signoz/signoz/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=signoz/signoz" />
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
150
README.zh-cn.md
Normal file
150
README.zh-cn.md
Normal file
@@ -0,0 +1,150 @@
|
||||
<p align="center">
|
||||
<img src="https://res.cloudinary.com/dcv3epinx/image/upload/v1618904450/signoz-images/LogoGithub_sigfbu.svg" alt="SigNoz-logo" width="240" />
|
||||
|
||||
<p align="center">监视你的应用,并可排查已部署应用中的问题,这是一个开源的可替代DataDog、NewRelic的方案</p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="License" src="https://img.shields.io/badge/license-MIT-brightgreen"> </a>
|
||||
<img alt="Downloads" src="https://img.shields.io/docker/pulls/signoz/frontend?label=Downloads"> </a>
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/signoz/signoz"> </a>
|
||||
<a href="https://twitter.com/intent/tweet?text=Monitor%20your%20applications%20and%20troubleshoot%20problems%20with%20SigNoz,%20an%20open-source%20alternative%20to%20DataDog,%20NewRelic.&url=https://signoz.io/&via=SigNozHQ&hashtags=opensource,signoz,observability">
|
||||
<img alt="tweet" src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social"> </a>
|
||||
</p>
|
||||
|
||||
##
|
||||
|
||||
SigNoz帮助开发人员监控应用并排查已部署应用中的问题。SigNoz使用分布式跟踪来增加软件技术栈的可见性。
|
||||
|
||||
👉 你能看到一些性能矩阵,服务、外部api调用、每个终端(endpoint)的p99延迟和错误率。
|
||||
|
||||
👉 通过准确的跟踪来确定是什么引起了问题,并且可以看到每个独立请求的帧图(framegraph),这样你就能找到根本原因。
|
||||
|
||||
|
||||

|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## 加入我们的Slack社区
|
||||
|
||||
来[Slack](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA) 跟我们打声招呼👋
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Features.svg" width="50px" />
|
||||
|
||||
## 功能:
|
||||
|
||||
- 应用总览矩阵(matrix),如RPS, 50/90/99百分比延迟率,错误率
|
||||
- 应用中最慢的终端(endpoint)
|
||||
- 查看准确的网络请求跟踪来分析下游服务问题、慢数据库查询问题 及调用第三方服务如支付网关的问题
|
||||
- 通过服务名称、操作、延迟、错误、标签来过滤跟踪
|
||||
- 对过滤后的跟踪数据做矩阵聚合。比如,获得过滤条件`customer_type: gold` or `deployment_version: v2` or `external_call: paypal`的错误率和p99延迟
|
||||
- 整合的矩阵和跟踪用户界面。不需要像从Prometheus切换到Jaeger才能调试问题
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/WhatsCool.svg" width="50px" />
|
||||
|
||||
## 为何选择SigNoz?
|
||||
|
||||
作为开发人员,我们发现依赖闭源的SaaS厂商提供的每个小功能有些麻烦,闭源厂商通常会给你一份巨额月付账单,但不提供足够的透明度,你不知道你为哪些功能付费。
|
||||
|
||||
我们想做一个自服务的开源版本的工具,类似于DataDog和NewRelic,用于那些对客户数据流入第三方有隐私和安全担忧的厂商。
|
||||
|
||||
开源也让你对配置、采样和上线率有完整的控制,你可以在SigNoz基础上构建模块来满足特定的商业需求。
|
||||
|
||||
### 语言支持
|
||||
|
||||
我们支持[OpenTelemetry](https://opentelemetry.io)库,你可以使用它来装备应用。也就是说SigNoz支持任何支持OpenTelemetry库的框架和语言。 主要支持语言包括:
|
||||
|
||||
- Java
|
||||
- Python
|
||||
- NodeJS
|
||||
- Go
|
||||
|
||||
你可以在这个文档里找到完整的语言列表 - https://opentelemetry.io/docs/
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Philosophy.svg" width="50px" />
|
||||
|
||||
## 入门
|
||||
|
||||
|
||||
### 使用Docker部署
|
||||
|
||||
请按照[这里](https://signoz.io/docs/deployment/docker/)列出的步骤使用Docker来安装
|
||||
|
||||
如果你遇到任何问题,这个[排查指南](https://signoz.io/docs/deployment/troubleshooting)会对你有帮助。
|
||||
|
||||
<p>  </p>
|
||||
|
||||
|
||||
### 使用Helm在Kubernetes上部署
|
||||
|
||||
请跟着[这里](https://signoz.io/docs/deployment/helm_chart)的步骤使用helm charts安装
|
||||
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/UseSigNoz.svg" width="50px" />
|
||||
|
||||
## Comparisons to Familiar Tools
|
||||
|
||||
### SigNoz vs Prometheus
|
||||
|
||||
如果你只是需要矩阵,那Prometheus是不错的,但如果你要无缝的在矩阵和跟踪之间切换,那目前把Prometheus & Jaeger串起来的体验并不好。
|
||||
|
||||
我们的目标是在矩阵和跟踪之间提供整合的UI - 类似于Datadog这样的Saas厂提供的方案,能够对跟踪进行过滤和聚合,这是目前Jaeger缺失的功能。
|
||||
|
||||
<p>  </p>
|
||||
|
||||
### SigNoz vs Jaeger
|
||||
|
||||
Jaeger只做分布式跟踪,SigNoz则是做了矩阵和跟踪两块,我们在计划中也有日志管理功能。
|
||||
|
||||
并且SigNoz有一些Jaeger没有的高级功能:
|
||||
|
||||
- Jaegar UI无法在跟踪或过滤的跟踪基础上展示矩阵。
|
||||
- Jaeger不能在过滤的跟踪上进行聚合操作。例如,拥有tag为customer_type='premium'的所有请求的p99延迟,在SigNoz里这很容易实现。
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributors.svg" width="50px" />
|
||||
|
||||
## 贡献
|
||||
|
||||
|
||||
我们 ❤️ 任何贡献无论大小。 请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 然后开始给Signoz做贡献。
|
||||
|
||||
还不清楚怎么开始? 只需在[slack社区](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA)的`#contributing`频道里ping我们。
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/DevelopingLocally.svg" width="50px" />
|
||||
|
||||
## 文档
|
||||
|
||||
文档在这里:https://signoz.io/docs/. 如果你觉得有任何不清楚或者有文档缺失,请在Github里发一个问题,并使用标签 `documentation` 或者在社区stack频道里告诉我们。
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## 社区
|
||||
|
||||
加入[slack community](https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA),了解更多关于分布式跟踪、可观察性(observability),以及SigNoz。同时与其他用户和贡献者一起交流。
|
||||
|
||||
如果你有任何想法、问题或者反馈,请在[Github Discussions](https://github.com/SigNoz/signoz/discussions)分享给我们。
|
||||
|
||||
最后,感谢我们这些优秀的贡献者们。
|
||||
|
||||
<a href="https://github.com/signoz/signoz/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=signoz/signoz" />
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
517
deploy/docker/clickhouse-setup/clickhouse-config.xml
Normal file
517
deploy/docker/clickhouse-setup/clickhouse-config.xml
Normal file
@@ -0,0 +1,517 @@
|
||||
<?xml version="1.0"?>
|
||||
<yandex>
|
||||
<logger>
|
||||
<level>trace</level>
|
||||
<log>/var/log/clickhouse-server/clickhouse-server.log</log>
|
||||
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
|
||||
<size>1000M</size>
|
||||
<count>10</count>
|
||||
</logger>
|
||||
|
||||
<http_port>8123</http_port>
|
||||
<tcp_port>9000</tcp_port>
|
||||
|
||||
<!-- For HTTPS and SSL over native protocol. -->
|
||||
<!--
|
||||
<https_port>8443</https_port>
|
||||
<tcp_ssl_port>9440</tcp_ssl_port>
|
||||
-->
|
||||
|
||||
<!-- Used with https_port and tcp_ssl_port. Full ssl options list: https://github.com/yandex/ClickHouse/blob/master/contrib/libpoco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h#L71 -->
|
||||
<openSSL>
|
||||
<server> <!-- Used for https server AND secure tcp port -->
|
||||
<!-- openssl req -subj "/CN=localhost" -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout /etc/clickhouse-server/server.key -out /etc/clickhouse-server/server.crt -->
|
||||
<certificateFile>/etc/clickhouse-server/server.crt</certificateFile>
|
||||
<privateKeyFile>/etc/clickhouse-server/server.key</privateKeyFile>
|
||||
<!-- openssl dhparam -out /etc/clickhouse-server/dhparam.pem 4096 -->
|
||||
<dhParamsFile>/etc/clickhouse-server/dhparam.pem</dhParamsFile>
|
||||
<verificationMode>none</verificationMode>
|
||||
<loadDefaultCAFile>true</loadDefaultCAFile>
|
||||
<cacheSessions>true</cacheSessions>
|
||||
<disableProtocols>sslv2,sslv3</disableProtocols>
|
||||
<preferServerCiphers>true</preferServerCiphers>
|
||||
</server>
|
||||
|
||||
<client> <!-- Used for connecting to https dictionary source -->
|
||||
<loadDefaultCAFile>true</loadDefaultCAFile>
|
||||
<cacheSessions>true</cacheSessions>
|
||||
<disableProtocols>sslv2,sslv3</disableProtocols>
|
||||
<preferServerCiphers>true</preferServerCiphers>
|
||||
<!-- Use for self-signed: <verificationMode>none</verificationMode> -->
|
||||
<invalidCertificateHandler>
|
||||
<!-- Use for self-signed: <name>AcceptCertificateHandler</name> -->
|
||||
<name>RejectCertificateHandler</name>
|
||||
</invalidCertificateHandler>
|
||||
</client>
|
||||
</openSSL>
|
||||
|
||||
<!-- Default root page on http[s] server. For example load UI from https://tabix.io/ when opening http://localhost:8123 -->
|
||||
<!--
|
||||
<http_server_default_response><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>]]></http_server_default_response>
|
||||
-->
|
||||
|
||||
<!-- Port for communication between replicas. Used for data exchange. -->
|
||||
<interserver_http_port>9009</interserver_http_port>
|
||||
|
||||
<!-- Hostname that is used by other replicas to request this server.
|
||||
If not specified, than it is determined analoguous to 'hostname -f' command.
|
||||
This setting could be used to switch replication to another network interface.
|
||||
-->
|
||||
<!--
|
||||
<interserver_http_host>example.yandex.ru</interserver_http_host>
|
||||
-->
|
||||
|
||||
<!-- Listen specified host. use :: (wildcard IPv6 address), if you want to accept connections both with IPv4 and IPv6 from everywhere. -->
|
||||
<listen_host>::</listen_host>
|
||||
<!-- Same for hosts with disabled ipv6: -->
|
||||
<!-- <listen_host>0.0.0.0</listen_host> -->
|
||||
|
||||
<!-- Default values - try listen localhost on ipv4 and ipv6: -->
|
||||
<!-- <listen_host>0.0.0.0</listen_host> -->
|
||||
|
||||
<max_connections>4096</max_connections>
|
||||
<keep_alive_timeout>3</keep_alive_timeout>
|
||||
|
||||
<!-- Maximum number of concurrent queries. -->
|
||||
<max_concurrent_queries>100</max_concurrent_queries>
|
||||
|
||||
<!-- Set limit on number of open files (default: maximum). This setting makes sense on Mac OS X because getrlimit() fails to retrieve
|
||||
correct maximum value. -->
|
||||
<!-- <max_open_files>262144</max_open_files> -->
|
||||
|
||||
<!-- Size of cache of uncompressed blocks of data, used in tables of MergeTree family.
|
||||
In bytes. Cache is single for server. Memory is allocated only on demand.
|
||||
Cache is used when 'use_uncompressed_cache' user setting turned on (off by default).
|
||||
Uncompressed cache is advantageous only for very short queries and in rare cases.
|
||||
-->
|
||||
<uncompressed_cache_size>8589934592</uncompressed_cache_size>
|
||||
|
||||
<!-- Approximate size of mark cache, used in tables of MergeTree family.
|
||||
In bytes. Cache is single for server. Memory is allocated only on demand.
|
||||
You should not lower this value.
|
||||
-->
|
||||
<mark_cache_size>5368709120</mark_cache_size>
|
||||
|
||||
|
||||
<!-- Path to data directory, with trailing slash. -->
|
||||
<path>/var/lib/clickhouse/</path>
|
||||
|
||||
<!-- Path to temporary data for processing hard queries. -->
|
||||
<tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
|
||||
|
||||
<!-- Path to configuration file with users, access rights, profiles of settings, quotas. -->
|
||||
<users_config>users.xml</users_config>
|
||||
|
||||
<!-- Default profile of settings.. -->
|
||||
<default_profile>default</default_profile>
|
||||
|
||||
<!-- Default database. -->
|
||||
<default_database>default</default_database>
|
||||
|
||||
<!-- Server time zone could be set here.
|
||||
|
||||
Time zone is used when converting between String and DateTime types,
|
||||
when printing DateTime in text formats and parsing DateTime from text,
|
||||
it is used in date and time related functions, if specific time zone was not passed as an argument.
|
||||
|
||||
Time zone is specified as identifier from IANA time zone database, like UTC or Africa/Abidjan.
|
||||
If not specified, system time zone at server startup is used.
|
||||
|
||||
Please note, that server could display time zone alias instead of specified name.
|
||||
Example: W-SU is an alias for Europe/Moscow and Zulu is an alias for UTC.
|
||||
-->
|
||||
<!-- <timezone>Europe/Moscow</timezone> -->
|
||||
|
||||
<!-- You can specify umask here (see "man umask"). Server will apply it on startup.
|
||||
Number is always parsed as octal. Default umask is 027 (other users cannot read logs, data files, etc; group can only read).
|
||||
-->
|
||||
<!-- <umask>022</umask> -->
|
||||
|
||||
<!-- Configuration of clusters that could be used in Distributed tables.
|
||||
https://clickhouse.yandex/reference_en.html#Distributed
|
||||
-->
|
||||
<remote_servers incl="clickhouse_remote_servers" >
|
||||
<!-- Test only shard config for testing distributed storage -->
|
||||
<test_shard_localhost>
|
||||
<shard>
|
||||
<replica>
|
||||
<host>localhost</host>
|
||||
<port>9000</port>
|
||||
</replica>
|
||||
</shard>
|
||||
</test_shard_localhost>
|
||||
</remote_servers>
|
||||
|
||||
|
||||
<!-- If element has 'incl' attribute, then for it's value will be used corresponding substitution from another file.
|
||||
By default, path to file with substitutions is /etc/metrika.xml. It could be changed in config in 'include_from' element.
|
||||
Values for substitutions are specified in /yandex/name_of_substitution elements in that file.
|
||||
-->
|
||||
|
||||
<!-- ZooKeeper is used to store metadata about replicas, when using Replicated tables.
|
||||
Optional. If you don't use replicated tables, you could omit that.
|
||||
|
||||
See https://clickhouse.yandex/reference_en.html#Data%20replication
|
||||
-->
|
||||
<zookeeper incl="zookeeper-servers" optional="true" />
|
||||
|
||||
<!-- Substitutions for parameters of replicated tables.
|
||||
Optional. If you don't use replicated tables, you could omit that.
|
||||
|
||||
See https://clickhouse.yandex/reference_en.html#Creating%20replicated%20tables
|
||||
-->
|
||||
<macros incl="macros" optional="true" />
|
||||
|
||||
|
||||
<!-- Reloading interval for embedded dictionaries, in seconds. Default: 3600. -->
|
||||
<builtin_dictionaries_reload_interval>3600</builtin_dictionaries_reload_interval>
|
||||
|
||||
|
||||
<!-- Maximum session timeout, in seconds. Default: 3600. -->
|
||||
<max_session_timeout>3600</max_session_timeout>
|
||||
|
||||
<!-- Default session timeout, in seconds. Default: 60. -->
|
||||
<default_session_timeout>60</default_session_timeout>
|
||||
|
||||
<!-- Sending data to Graphite for monitoring. Several sections can be defined. -->
|
||||
<!--
|
||||
interval - send every X second
|
||||
root_path - prefix for keys
|
||||
hostname_in_path - append hostname to root_path (default = true)
|
||||
metrics - send data from table system.metrics
|
||||
events - send data from table system.events
|
||||
asynchronous_metrics - send data from table system.asynchronous_metrics
|
||||
-->
|
||||
<!--
|
||||
<graphite>
|
||||
<host>localhost</host>
|
||||
<port>42000</port>
|
||||
<timeout>0.1</timeout>
|
||||
<interval>60</interval>
|
||||
<root_path>one_min</root_path>
|
||||
<hostname_in_path>true<hostname_in_path>
|
||||
|
||||
<metrics>true</metrics>
|
||||
<events>true</events>
|
||||
<asynchronous_metrics>true</asynchronous_metrics>
|
||||
</graphite>
|
||||
<graphite>
|
||||
<host>localhost</host>
|
||||
<port>42000</port>
|
||||
<timeout>0.1</timeout>
|
||||
<interval>1</interval>
|
||||
<root_path>one_sec</root_path>
|
||||
|
||||
<metrics>true</metrics>
|
||||
<events>true</events>
|
||||
<asynchronous_metrics>false</asynchronous_metrics>
|
||||
</graphite>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Query log. Used only for queries with setting log_queries = 1. -->
|
||||
<query_log>
|
||||
<!-- What table to insert data. If table is not exist, it will be created.
|
||||
When query log structure is changed after system update,
|
||||
then old table will be renamed and new table will be created automatically.
|
||||
-->
|
||||
<database>system</database>
|
||||
<table>query_log</table>
|
||||
|
||||
<!-- Interval of flushing data. -->
|
||||
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
|
||||
</query_log>
|
||||
|
||||
|
||||
<!-- Uncomment if use part_log
|
||||
<part_log>
|
||||
<database>system</database>
|
||||
<table>part_log</table>
|
||||
|
||||
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
|
||||
</part_log>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Parameters for embedded dictionaries, used in Yandex.Metrica.
|
||||
See https://clickhouse.yandex/reference_en.html#Internal%20dictionaries
|
||||
-->
|
||||
|
||||
<!-- Path to file with region hierarchy. -->
|
||||
<!-- <path_to_regions_hierarchy_file>/opt/geo/regions_hierarchy.txt</path_to_regions_hierarchy_file> -->
|
||||
|
||||
<!-- Path to directory with files containing names of regions -->
|
||||
<!-- <path_to_regions_names_files>/opt/geo/</path_to_regions_names_files> -->
|
||||
|
||||
|
||||
<!-- Configuration of external dictionaries. See:
|
||||
https://clickhouse.yandex/reference_en.html#External%20Dictionaries
|
||||
-->
|
||||
<dictionaries_config>*_dictionary.xml</dictionaries_config>
|
||||
|
||||
<!-- Uncomment if you want data to be compressed 30-100% better.
|
||||
Don't do that if you just started using ClickHouse.
|
||||
-->
|
||||
<compression incl="clickhouse_compression">
|
||||
<!--
|
||||
<!- - Set of variants. Checked in order. Last matching case wins. If nothing matches, lz4 will be used. - ->
|
||||
<case>
|
||||
|
||||
<!- - Conditions. All must be satisfied. Some conditions may be omitted. - ->
|
||||
<min_part_size>10000000000</min_part_size> <!- - Min part size in bytes. - ->
|
||||
<min_part_size_ratio>0.01</min_part_size_ratio> <!- - Min size of part relative to whole table size. - ->
|
||||
|
||||
<!- - What compression method to use. - ->
|
||||
<method>zstd</method>
|
||||
</case>
|
||||
-->
|
||||
</compression>
|
||||
|
||||
<!-- Allow to execute distributed DDL queries (CREATE, DROP, ALTER, RENAME) on cluster.
|
||||
Works only if ZooKeeper is enabled. Comment it if such functionality isn't required. -->
|
||||
<distributed_ddl>
|
||||
<!-- Path in ZooKeeper to queue with DDL queries -->
|
||||
<path>/clickhouse/task_queue/ddl</path>
|
||||
</distributed_ddl>
|
||||
|
||||
<!-- Settings to fine tune MergeTree tables. See documentation in source code, in MergeTreeSettings.h -->
|
||||
<!--
|
||||
<merge_tree>
|
||||
<max_suspicious_broken_parts>5</max_suspicious_broken_parts>
|
||||
</merge_tree>
|
||||
-->
|
||||
|
||||
<!-- Protection from accidental DROP.
|
||||
If size of a MergeTree table is greater than max_table_size_to_drop (in bytes) than table could not be dropped with any DROP query.
|
||||
If you want do delete one table and don't want to restart clickhouse-server, you could create special file <clickhouse-path>/flags/force_drop_table and make DROP once.
|
||||
By default max_table_size_to_drop is 50GB, max_table_size_to_drop=0 allows to DROP any tables.
|
||||
Uncomment to disable protection.
|
||||
-->
|
||||
<!-- <max_table_size_to_drop>0</max_table_size_to_drop> -->
|
||||
|
||||
<!-- Example of parameters for GraphiteMergeTree table engine -->
|
||||
<graphite_rollup>
|
||||
<!-- carbon -->
|
||||
<pattern>
|
||||
<regexp>^carbon\.</regexp>
|
||||
<function>any</function>
|
||||
<retention>
|
||||
<age>0</age>
|
||||
<precision>60</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>7776000</age>
|
||||
<precision>3600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>10368000</age>
|
||||
<precision>21600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>34560000</age>
|
||||
<precision>43200</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>63072000</age>
|
||||
<precision>86400</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>94608000</age>
|
||||
<precision>604800</precision>
|
||||
</retention>
|
||||
</pattern>
|
||||
<!-- collectd -->
|
||||
<pattern>
|
||||
<regexp>^collectd\.</regexp>
|
||||
<function>any</function>
|
||||
<retention>
|
||||
<age>0</age>
|
||||
<precision>10</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>43200</age>
|
||||
<precision>60</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>864000</age>
|
||||
<precision>900</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>1728000</age>
|
||||
<precision>1800</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>3456000</age>
|
||||
<precision>3600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>10368000</age>
|
||||
<precision>21600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>34560000</age>
|
||||
<precision>43200</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>63072000</age>
|
||||
<precision>86400</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>94608000</age>
|
||||
<precision>604800</precision>
|
||||
</retention>
|
||||
</pattern>
|
||||
<!-- high -->
|
||||
<pattern>
|
||||
<regexp>^high\.</regexp>
|
||||
<function>any</function>
|
||||
<retention>
|
||||
<age>0</age>
|
||||
<precision>10</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>172800</age>
|
||||
<precision>60</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>864000</age>
|
||||
<precision>900</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>1728000</age>
|
||||
<precision>1800</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>3456000</age>
|
||||
<precision>3600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>10368000</age>
|
||||
<precision>21600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>34560000</age>
|
||||
<precision>43200</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>63072000</age>
|
||||
<precision>86400</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>94608000</age>
|
||||
<precision>604800</precision>
|
||||
</retention>
|
||||
</pattern>
|
||||
<!-- medium -->
|
||||
<pattern>
|
||||
<regexp>^medium\.</regexp>
|
||||
<function>any</function>
|
||||
<retention>
|
||||
<age>0</age>
|
||||
<precision>60</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>864000</age>
|
||||
<precision>900</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>1728000</age>
|
||||
<precision>1800</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>3456000</age>
|
||||
<precision>3600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>10368000</age>
|
||||
<precision>21600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>34560000</age>
|
||||
<precision>43200</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>63072000</age>
|
||||
<precision>86400</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>94608000</age>
|
||||
<precision>604800</precision>
|
||||
</retention>
|
||||
</pattern>
|
||||
<!-- low -->
|
||||
<pattern>
|
||||
<regexp>^low\.</regexp>
|
||||
<function>any</function>
|
||||
<retention>
|
||||
<age>0</age>
|
||||
<precision>600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>15552000</age>
|
||||
<precision>1800</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>31536000</age>
|
||||
<precision>3600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>63072000</age>
|
||||
<precision>21600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>126144000</age>
|
||||
<precision>43200</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>252288000</age>
|
||||
<precision>86400</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>315360000</age>
|
||||
<precision>604800</precision>
|
||||
</retention>
|
||||
</pattern>
|
||||
<!-- default -->
|
||||
<default>
|
||||
<function>any</function>
|
||||
<retention>
|
||||
<age>0</age>
|
||||
<precision>60</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>864000</age>
|
||||
<precision>900</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>1728000</age>
|
||||
<precision>1800</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>3456000</age>
|
||||
<precision>3600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>10368000</age>
|
||||
<precision>21600</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>34560000</age>
|
||||
<precision>43200</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>63072000</age>
|
||||
<precision>86400</precision>
|
||||
</retention>
|
||||
<retention>
|
||||
<age>94608000</age>
|
||||
<precision>604800</precision>
|
||||
</retention>
|
||||
</default>
|
||||
</graphite_rollup>
|
||||
|
||||
<!-- Directory in <clickhouse-path> containing schema files for various input formats.
|
||||
The directory will be created if it doesn't exist.
|
||||
-->
|
||||
<format_schema_path>/var/lib/clickhouse/format_schemas/</format_schema_path>
|
||||
</yandex>
|
||||
97
deploy/docker/clickhouse-setup/docker-compose.yaml
Normal file
97
deploy/docker/clickhouse-setup/docker-compose.yaml
Normal file
@@ -0,0 +1,97 @@
|
||||
version: "2.4"
|
||||
|
||||
services:
|
||||
clickhouse:
|
||||
image: yandex/clickhouse-server
|
||||
expose:
|
||||
- 8123
|
||||
- 9000
|
||||
ports:
|
||||
- 9001:9000
|
||||
- 8123:8123
|
||||
volumes:
|
||||
- ./clickhouse-config.xml:/etc/clickhouse-server/config.xml
|
||||
- ./docker-entrypoint-initdb.d/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql
|
||||
healthcheck:
|
||||
# "clickhouse", "client", "-u ${CLICKHOUSE_USER}", "--password ${CLICKHOUSE_PASSWORD}", "-q 'SELECT 1'"
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8123/ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
query-service:
|
||||
image: signoz/query-service:0.3.4
|
||||
container_name: query-service
|
||||
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
environment:
|
||||
- ClickHouseUrl=tcp://clickhouse:9000
|
||||
- STORAGE=clickhouse
|
||||
- POSTHOG_API_KEY=H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w
|
||||
|
||||
depends_on:
|
||||
clickhouse:
|
||||
condition: service_healthy
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:0.3.4
|
||||
container_name: frontend
|
||||
|
||||
depends_on:
|
||||
- query-service
|
||||
links:
|
||||
- "query-service"
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
|
||||
otel-collector:
|
||||
image: signoz/otelcol:latest
|
||||
command: ["--config=/etc/otel-collector-config.yaml", "--mem-ballast-size-mib=683"]
|
||||
volumes:
|
||||
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
|
||||
ports:
|
||||
- "1777:1777" # pprof extension
|
||||
- "8887:8888" # Prometheus metrics exposed by the agent
|
||||
- "14268:14268" # Jaeger receiver
|
||||
- "55678" # OpenCensus receiver
|
||||
- "55680:55680" # OTLP HTTP/2.0 legacy port
|
||||
- "55681:55681" # OTLP HTTP/1.0 receiver
|
||||
- "4317:4317" # OTLP GRPC receiver
|
||||
- "55679:55679" # zpages extension
|
||||
- "13133" # health_check
|
||||
|
||||
depends_on:
|
||||
clickhouse:
|
||||
condition: service_healthy
|
||||
|
||||
hotrod:
|
||||
image: jaegertracing/example-hotrod:latest
|
||||
container_name: hotrod
|
||||
ports:
|
||||
- "9000:8080"
|
||||
command: ["all"]
|
||||
environment:
|
||||
- JAEGER_ENDPOINT=http://otel-collector:14268/api/traces
|
||||
|
||||
|
||||
load-hotrod:
|
||||
image: "grubykarol/locust:1.2.3-python3.9-alpine3.12"
|
||||
container_name: load-hotrod
|
||||
hostname: load-hotrod
|
||||
ports:
|
||||
- "8089:8089"
|
||||
environment:
|
||||
ATTACKED_HOST: http://hotrod:8080
|
||||
LOCUST_MODE: standalone
|
||||
NO_PROXY: standalone
|
||||
TASK_DELAY_FROM: 5
|
||||
TASK_DELAY_TO: 30
|
||||
QUIET_MODE: "${QUIET_MODE:-false}"
|
||||
LOCUST_OPTS: "--headless -u 10 -r 1"
|
||||
volumes:
|
||||
- ../common/locust-scripts:/locust
|
||||
@@ -0,0 +1,27 @@
|
||||
CREATE TABLE IF NOT EXISTS signoz_index (
|
||||
timestamp DateTime64(9) CODEC(Delta, ZSTD(1)),
|
||||
traceID String CODEC(ZSTD(1)),
|
||||
spanID String CODEC(ZSTD(1)),
|
||||
parentSpanID String CODEC(ZSTD(1)),
|
||||
serviceName LowCardinality(String) CODEC(ZSTD(1)),
|
||||
name LowCardinality(String) CODEC(ZSTD(1)),
|
||||
kind Int32 CODEC(ZSTD(1)),
|
||||
durationNano UInt64 CODEC(ZSTD(1)),
|
||||
tags Array(String) CODEC(ZSTD(1)),
|
||||
tagsKeys Array(String) CODEC(ZSTD(1)),
|
||||
tagsValues Array(String) CODEC(ZSTD(1)),
|
||||
statusCode Int64 CODEC(ZSTD(1)),
|
||||
references String CODEC(ZSTD(1)),
|
||||
externalHttpMethod Nullable(String) CODEC(ZSTD(1)),
|
||||
externalHttpUrl Nullable(String) CODEC(ZSTD(1)),
|
||||
component Nullable(String) CODEC(ZSTD(1)),
|
||||
dbSystem Nullable(String) CODEC(ZSTD(1)),
|
||||
dbName Nullable(String) CODEC(ZSTD(1)),
|
||||
dbOperation Nullable(String) CODEC(ZSTD(1)),
|
||||
peerService Nullable(String) CODEC(ZSTD(1)),
|
||||
INDEX idx_tagsKeys tagsKeys TYPE bloom_filter(0.01) GRANULARITY 64,
|
||||
INDEX idx_tagsValues tagsValues TYPE bloom_filter(0.01) GRANULARITY 64,
|
||||
INDEX idx_duration durationNano TYPE minmax GRANULARITY 1
|
||||
) ENGINE MergeTree()
|
||||
PARTITION BY toDate(timestamp)
|
||||
ORDER BY (serviceName, -toUnixTimestamp(timestamp))
|
||||
39
deploy/docker/clickhouse-setup/otel-collector-config.yaml
Normal file
39
deploy/docker/clickhouse-setup/otel-collector-config.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
jaeger:
|
||||
protocols:
|
||||
grpc:
|
||||
thrift_http:
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
memory_limiter:
|
||||
# Same as --mem-ballast-size-mib CLI argument
|
||||
ballast_size_mib: 683
|
||||
# 80% of maximum memory up to 2G
|
||||
limit_mib: 1500
|
||||
# 25% of limit up to 2G
|
||||
spike_limit_mib: 512
|
||||
check_interval: 5s
|
||||
# queued_retry:
|
||||
# num_workers: 4
|
||||
# queue_size: 100
|
||||
# retry_on_failure: true
|
||||
extensions:
|
||||
health_check: {}
|
||||
zpages: {}
|
||||
exporters:
|
||||
clickhouse:
|
||||
datasource: tcp://clickhouse:9000
|
||||
|
||||
service:
|
||||
extensions: [health_check, zpages]
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [jaeger, otlp]
|
||||
processors: [batch]
|
||||
exporters: [clickhouse]
|
||||
@@ -1,6 +1,16 @@
|
||||
server {
|
||||
listen 3000;
|
||||
server_name _;
|
||||
|
||||
gzip on;
|
||||
gzip_static on;
|
||||
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
gzip_proxied any;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
@@ -140,9 +140,14 @@ services:
|
||||
env_file:
|
||||
- environment_tiny/router
|
||||
- environment_tiny/common
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://router:8888/druid/coordinator/v1/datasources/flattened_spans"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
flatten-processor:
|
||||
image: signoz/flattener-processor:0.2.0
|
||||
image: signoz/flattener-processor:0.3.4
|
||||
container_name: flattener-processor
|
||||
|
||||
depends_on:
|
||||
@@ -158,7 +163,7 @@ services:
|
||||
|
||||
|
||||
query-service:
|
||||
image: signoz.docker.scarf.sh/signoz/query-service:0.2.2
|
||||
image: signoz.docker.scarf.sh/signoz/query-service:0.3.4
|
||||
container_name: query-service
|
||||
|
||||
depends_on:
|
||||
@@ -169,11 +174,15 @@ services:
|
||||
environment:
|
||||
- DruidClientUrl=http://router:8888
|
||||
- DruidDatasource=flattened_spans
|
||||
- STORAGE=druid
|
||||
- POSTHOG_API_KEY=H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w
|
||||
|
||||
|
||||
depends_on:
|
||||
router:
|
||||
condition: service_healthy
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:0.2.3
|
||||
image: signoz/frontend:0.3.4
|
||||
container_name: frontend
|
||||
|
||||
depends_on:
|
||||
@@ -183,7 +192,7 @@ services:
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
create-supervisor:
|
||||
image: theithollow/hollowapp-blog:curl
|
||||
@@ -260,5 +269,5 @@ services:
|
||||
QUIET_MODE: "${QUIET_MODE:-false}"
|
||||
LOCUST_OPTS: "--headless -u 10 -r 1"
|
||||
volumes:
|
||||
- ./locust-scripts:/locust
|
||||
- ../common/locust-scripts:/locust
|
||||
|
||||
@@ -135,9 +135,14 @@ services:
|
||||
- router
|
||||
env_file:
|
||||
- environment_small/router
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://router:8888/druid/coordinator/v1/datasources/flattened_spans"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
flatten-processor:
|
||||
image: signoz/flattener-processor:0.2.0
|
||||
image: signoz/flattener-processor:0.3.4
|
||||
container_name: flattener-processor
|
||||
|
||||
depends_on:
|
||||
@@ -153,7 +158,7 @@ services:
|
||||
|
||||
|
||||
query-service:
|
||||
image: signoz.docker.scarf.sh/signoz/query-service:0.2.2
|
||||
image: signoz.docker.scarf.sh/signoz/query-service:0.3.4
|
||||
container_name: query-service
|
||||
|
||||
depends_on:
|
||||
@@ -164,11 +169,15 @@ services:
|
||||
environment:
|
||||
- DruidClientUrl=http://router:8888
|
||||
- DruidDatasource=flattened_spans
|
||||
- STORAGE=druid
|
||||
- POSTHOG_API_KEY=H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w
|
||||
|
||||
depends_on:
|
||||
router:
|
||||
condition: service_healthy
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:0.2.3
|
||||
image: signoz/frontend:0.3.4
|
||||
container_name: frontend
|
||||
|
||||
depends_on:
|
||||
@@ -1,256 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
|
||||
is_command_present() {
|
||||
type "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
is_mac() {
|
||||
[[ $OSTYPE == darwin* ]]
|
||||
}
|
||||
|
||||
|
||||
check_k8s_setup() {
|
||||
echo "Checking your k8s setup status"
|
||||
if ! is_command_present kubectl; then
|
||||
echo "Please install kubectl on your machine"
|
||||
exit 1
|
||||
else
|
||||
|
||||
if ! is_command_present jq; then
|
||||
install_jq
|
||||
fi
|
||||
clusters=`kubectl config view -o json | jq -r '."current-context"'`
|
||||
if [[ ! -n $clusters ]]; then
|
||||
echo "Please setup a k8s cluster & config kubectl to connect to it"
|
||||
exit 1
|
||||
fi
|
||||
k8s_minor_version=`kubectl version --short -o json | jq ."serverVersion.minor" | sed 's/[^0-9]*//g'`
|
||||
# if [[ $k8s_minor_version < 18 ]]; then
|
||||
# echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
# echo "SigNoz deployments require Kubernetes >= v1.18. Found version: v1.$k8s_minor_version"
|
||||
# echo "+++++++++++ ++++++++++++++++++++++++++++"
|
||||
# exit 1
|
||||
# fi;
|
||||
fi
|
||||
}
|
||||
|
||||
install_jq(){
|
||||
if [ $package_manager == "brew" ]; then
|
||||
brew install jq
|
||||
elif [ $package_manager == "yum" ]; then
|
||||
yum_cmd="sudo yum --assumeyes --quiet"
|
||||
$yum_cmd install jq
|
||||
else
|
||||
apt_cmd="sudo apt-get --yes --quiet"
|
||||
$apt_cmd update
|
||||
$apt_cmd install jq
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
check_os() {
|
||||
if is_mac; then
|
||||
package_manager="brew"
|
||||
desired_os=1
|
||||
os="Mac"
|
||||
return
|
||||
fi
|
||||
|
||||
os_name="$(cat /etc/*-release | awk -F= '$1 == "NAME" { gsub(/"/, ""); print $2; exit }')"
|
||||
|
||||
case "$os_name" in
|
||||
Ubuntu*)
|
||||
desired_os=1
|
||||
os="ubuntu"
|
||||
package_manager="apt-get"
|
||||
;;
|
||||
Debian*)
|
||||
desired_os=1
|
||||
os="debian"
|
||||
package_manager="apt-get"
|
||||
;;
|
||||
Red\ Hat*)
|
||||
desired_os=1
|
||||
os="red hat"
|
||||
package_manager="yum"
|
||||
;;
|
||||
CentOS*)
|
||||
desired_os=1
|
||||
os="centos"
|
||||
package_manager="yum"
|
||||
;;
|
||||
*)
|
||||
desired_os=0
|
||||
os="Not Found"
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
echo_contact_support() {
|
||||
echo "Please contact <support@signoz.io> with your OS details and version${1:-.}"
|
||||
}
|
||||
|
||||
bye() { # Prints a friendly good bye message and exits the script.
|
||||
set +o errexit
|
||||
echo "Please share your email to receive support with the installation"
|
||||
read -rp 'Email: ' email
|
||||
|
||||
while [[ $email == "" ]]
|
||||
do
|
||||
read -rp 'Email: ' email
|
||||
done
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Support", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "email": "'"$email"'", "platform": "k8s", "k8s_minor_version": "'"$k8s_minor_version"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
|
||||
if has_curl; then
|
||||
curl -sfL -d "$DATA" --header "$HEADER" "$URL" > /dev/null 2>&1
|
||||
elif has_wget; then
|
||||
wget -q --post-data="$DATA" --header="$HEADER" "$URL" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
echo -e "\nExiting for now. Bye! \U1F44B\n"
|
||||
exit 1
|
||||
}
|
||||
|
||||
deploy_app() {
|
||||
kubectl apply -f "$install_dir/config-template"
|
||||
kubectl apply -f "$install_dir"
|
||||
}
|
||||
|
||||
wait_for_application_start() {
|
||||
local timeout=$1
|
||||
address=$custom_domain
|
||||
if [[ "$ssl_enable" == "true" ]]; then
|
||||
protocol="https"
|
||||
else
|
||||
protocol="http"
|
||||
fi
|
||||
# The while loop is important because for-loops don't work for dynamic values
|
||||
while [[ $timeout -gt 0 ]]; do
|
||||
if [[ $address == "" || $address == null ]]; then
|
||||
address=`kubectl get ingress appsmith-ingress -o json | jq -r '.status.loadBalancer.ingress[0].ip'`
|
||||
fi
|
||||
status_code="$(curl -s -o /dev/null -w "%{http_code}" $protocol://$address/api/v1 || true)"
|
||||
if [[ status_code -eq 401 ]]; then
|
||||
break
|
||||
else
|
||||
echo -ne "Waiting for all containers to start. This check will timeout in $timeout seconds...\r\c"
|
||||
fi
|
||||
((timeout--))
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
|
||||
echo -e "👋 Thank you for trying out SigNoz! "
|
||||
echo ""
|
||||
|
||||
|
||||
# Checking OS and assigning package manager
|
||||
desired_os=0
|
||||
os=""
|
||||
echo -e "🕵️ Detecting your OS"
|
||||
check_os
|
||||
SIGNOZ_INSTALLATION_ID=$(curl -s 'https://api64.ipify.org')
|
||||
|
||||
# Run bye if failure happens
|
||||
trap bye EXIT
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Started", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "platform": "k8s", "k8s_minor_version": "'"$k8s_minor_version"'" } }'
|
||||
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
if has_curl; then
|
||||
curl -sfL -d "$DATA" --header "$HEADER" "$URL" > /dev/null 2>&1
|
||||
elif has_wget; then
|
||||
wget -q --post-data="$DATA" --header="$HEADER" "$URL" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Check for kubernetes setup
|
||||
check_k8s_setup
|
||||
|
||||
echo ""
|
||||
echo "Deploy Appmisth on your cluster"
|
||||
echo ""
|
||||
|
||||
deploy_app
|
||||
|
||||
wait_for_application_start 60
|
||||
|
||||
|
||||
if [[ $status_code -ne 200 ]]; then
|
||||
echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
echo "The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo ""
|
||||
echo -e "sudo docker-compose -f docker/docker-compose-tiny.yaml ps -a"
|
||||
echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker#troubleshooting"
|
||||
echo "or reach us on SigNoz for support https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
|
||||
SUPERVISORS="$(curl -so - http://localhost:8888/druid/indexer/v1/supervisor)"
|
||||
|
||||
DATASOURCES="$(curl -so - http://localhost:8888/druid/coordinator/v1/datasources)"
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error - Checks", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "platform": "k8s", "error": "Containers not started", "SUPERVISORS": '"$SUPERVISORS"', "DATASOURCES": '"$DATASOURCES"' } }'
|
||||
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
if has_curl; then
|
||||
curl -sfL -d "$DATA" --header "$HEADER" "$URL" > /dev/null 2>&1
|
||||
elif has_wget; then
|
||||
wget -q --post-data="$DATA" --header="$HEADER" "$URL" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
exit 1
|
||||
|
||||
else
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Success", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'"} }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
if has_curl; then
|
||||
curl -sfL -d "$DATA" --header "$HEADER" "$URL" > /dev/null 2>&1
|
||||
elif has_wget; then
|
||||
wget -q --post-data="$DATA" --header="$HEADER" "$URL" > /dev/null 2>&1
|
||||
fi
|
||||
echo "++++++++++++++++++ SUCCESS ++++++++++++++++++++++"
|
||||
echo "Your installation is complete!"
|
||||
echo ""
|
||||
echo "Your frontend is running on 'http://localhost:3000'."
|
||||
|
||||
echo ""
|
||||
echo "+++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
echo "Need help Getting Started?"
|
||||
echo "Join us on Slack https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
echo ""
|
||||
echo "Please share your email to receive support & updates about SigNoz!"
|
||||
read -rp 'Email: ' email
|
||||
|
||||
while [[ $email == "" ]]
|
||||
do
|
||||
read -rp 'Email: ' email
|
||||
done
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Identify Successful Installation", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "email": "'"$email"'", "platform": "k8s" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
if has_curl; then
|
||||
curl -sfL -d "$DATA" --header "$HEADER" "$URL" > /dev/null 2>&1
|
||||
elif has_wget; then
|
||||
wget -q --post-data="$DATA" --header="$HEADER" "$URL" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
echo -e "\nThank you!\n"
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
set -o errexit
|
||||
|
||||
# Regular Colors
|
||||
Black='\033[0;30m' # Black
|
||||
Red='\[\e[0;31m\]' # Red
|
||||
Green='\033[0;32m' # Green
|
||||
Yellow='\033[0;33m' # Yellow
|
||||
Blue='\033[0;34m' # Blue
|
||||
Purple='\033[0;35m' # Purple
|
||||
Cyan='\033[0;36m' # Cyan
|
||||
White='\033[0;37m' # White
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
is_command_present() {
|
||||
type "$1" >/dev/null 2>&1
|
||||
@@ -88,7 +98,7 @@ check_os() {
|
||||
# The script should error out in case they aren't available
|
||||
check_ports_occupied() {
|
||||
local port_check_output
|
||||
local ports_pattern="80|443"
|
||||
local ports_pattern="80|3000|8080"
|
||||
|
||||
if is_mac; then
|
||||
port_check_output="$(netstat -anp tcp | awk '$6 == "LISTEN" && $4 ~ /^.*\.('"$ports_pattern"')$/')"
|
||||
@@ -192,7 +202,7 @@ install_docker_compose() {
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Docker Compose not found" } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Docker Compose not found", "setup_type": "'"$setup_type"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -212,8 +222,7 @@ install_docker_compose() {
|
||||
|
||||
start_docker() {
|
||||
echo "Starting Docker ..."
|
||||
if [ $os == "Mac" ]
|
||||
then
|
||||
if [ $os = "Mac" ]; then
|
||||
open --background -a Docker && while ! docker system info > /dev/null 2>&1; do sleep 1; done
|
||||
else
|
||||
if ! sudo systemctl is-active docker.service > /dev/null; then
|
||||
@@ -231,16 +240,17 @@ wait_for_containers_start() {
|
||||
if [[ status_code -eq 200 ]]; then
|
||||
break
|
||||
else
|
||||
SUPERVISORS="$(curl -so - http://localhost:8888/druid/indexer/v1/supervisor)"
|
||||
LEN_SUPERVISORS="${#SUPERVISORS}"
|
||||
if [ $setup_type == 'druid' ]; then
|
||||
SUPERVISORS="$(curl -so - http://localhost:8888/druid/indexer/v1/supervisor)"
|
||||
LEN_SUPERVISORS="${#SUPERVISORS}"
|
||||
|
||||
if [[ LEN_SUPERVISORS -ne 19 && $timeout -eq 50 ]];then
|
||||
echo "No Supervisors found... Re-applying docker compose\n"
|
||||
sudo docker-compose -f ./docker/docker-compose-tiny.yaml up -d
|
||||
if [[ LEN_SUPERVISORS -ne 19 && $timeout -eq 50 ]];then
|
||||
echo -e "\n🟠 Supervisors taking time to start ⏳ ... let's wait for some more time ⏱️\n\n"
|
||||
sudo docker-compose -f ./docker/druid-kafka-setup/docker-compose-tiny.yaml up -d
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
echo -ne "Waiting for all containers to start. This check will timeout in $timeout seconds...\r\c"
|
||||
echo -ne "Waiting for all containers to start. This check will timeout in $timeout seconds ...\r\c"
|
||||
fi
|
||||
((timeout--))
|
||||
sleep 1
|
||||
@@ -253,14 +263,18 @@ bye() { # Prints a friendly good bye message and exits the script.
|
||||
if [ "$?" -ne 0 ]; then
|
||||
set +o errexit
|
||||
|
||||
echo "The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo "🔴 The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo ""
|
||||
echo -e "sudo docker-compose -f docker/docker-compose-tiny.yaml ps -a"
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
echo -e "sudo docker-compose -f docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
else
|
||||
echo -e "sudo docker-compose -f docker/druid-kafka-setup/docker-compose-tiny.yaml ps -a"
|
||||
fi
|
||||
# echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker#troubleshooting"
|
||||
echo "or reach us on SigNoz for support https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
|
||||
echo "Please share your email to receive support with the installation"
|
||||
echo -e "\n📨 Please share your email to receive support with the installation"
|
||||
read -rp 'Email: ' email
|
||||
|
||||
while [[ $email == "" ]]
|
||||
@@ -268,7 +282,7 @@ bye() { # Prints a friendly good bye message and exits the script.
|
||||
read -rp 'Email: ' email
|
||||
done
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Support", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "email": "'"$email"'" } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Support", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "email": "'"$email"'", "setup_type": "'"$setup_type"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -294,17 +308,39 @@ echo ""
|
||||
# Checking OS and assigning package manager
|
||||
desired_os=0
|
||||
os=""
|
||||
echo -e "🕵️ Detecting your OS"
|
||||
echo -e "Detecting your OS ..."
|
||||
check_os
|
||||
|
||||
|
||||
SIGNOZ_INSTALLATION_ID=$(curl -s 'https://api64.ipify.org')
|
||||
|
||||
echo ""
|
||||
|
||||
echo -e "👉 ${RED}Two ways to go forward\n"
|
||||
echo -e "${RED}1) ClickHouse as database (default)\n"
|
||||
echo -e "${RED}2) Kafka + Druid setup to handle scale (recommended for production use)\n"
|
||||
read -p "⚙️ Enter your preference (1/2):" choice_setup
|
||||
|
||||
while [[ $choice_setup != "1" && $choice_setup != "2" && $choice_setup != "" ]]
|
||||
do
|
||||
# echo $choice_setup
|
||||
echo -e "\n❌ ${CYAN}Please enter either 1 or 2"
|
||||
read -p "⚙️ Enter your preference (1/2): " choice_setup
|
||||
# echo $choice_setup
|
||||
done
|
||||
|
||||
if [[ $choice_setup == "1" || $choice_setup == "" ]];then
|
||||
setup_type='clickhouse'
|
||||
else
|
||||
setup_type='druid'
|
||||
fi
|
||||
|
||||
echo -e "\n✅ ${CYAN}You have chosen: ${setup_type} setup\n"
|
||||
|
||||
# Run bye if failure happens
|
||||
trap bye EXIT
|
||||
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Started", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'" } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Started", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "setup_type": "'"$setup_type"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -316,7 +352,7 @@ fi
|
||||
|
||||
|
||||
if [[ $desired_os -eq 0 ]];then
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "OS Not Supported" } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "OS Not Supported", "setup_type": "'"$setup_type"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -340,7 +376,7 @@ if ! is_command_present docker; then
|
||||
echo "Docker Desktop must be installed manually on Mac OS to proceed. Docker can only be installed automatically on Ubuntu / openSUSE / SLES / Redhat / Cent OS"
|
||||
echo "https://docs.docker.com/docker-for-mac/install/"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Docker not installed" } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Docker not installed", "setup_type": "'"$setup_type"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -358,43 +394,59 @@ if ! is_command_present docker-compose; then
|
||||
install_docker_compose
|
||||
fi
|
||||
|
||||
# if ! is_command_present docker-compose; then
|
||||
# install_docker_machine
|
||||
# docker-machine create -d virtualbox --virtualbox-memory 3584 signoz
|
||||
|
||||
# fi
|
||||
|
||||
|
||||
start_docker
|
||||
|
||||
|
||||
# sudo docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml up -d --remove-orphans || true
|
||||
|
||||
|
||||
echo ""
|
||||
echo "Pulling the latest container images for SigNoz. To run as sudo it will ask for system password."
|
||||
sudo docker-compose -f ./docker/docker-compose-tiny.yaml pull
|
||||
echo -e "\n🟡 Pulling the latest container images for SigNoz. To run as sudo it may ask for system password\n"
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
sudo docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml pull
|
||||
else
|
||||
sudo docker-compose -f ./docker/druid-kafka-setup/docker-compose-tiny.yaml pull
|
||||
fi
|
||||
|
||||
|
||||
echo ""
|
||||
echo "Starting the SigNoz containers. It may take a few minute ..."
|
||||
echo "🟡 Starting the SigNoz containers. It may take a few minutes ..."
|
||||
echo
|
||||
# The docker-compose command does some nasty stuff for the `--detach` functionality. So we add a `|| true` so that the
|
||||
# script doesn't exit because this command looks like it failed to do it's thing.
|
||||
sudo docker-compose -f ./docker/docker-compose-tiny.yaml up --detach --remove-orphans || true
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
sudo docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml up --detach --remove-orphans || true
|
||||
else
|
||||
sudo docker-compose -f ./docker/druid-kafka-setup/docker-compose-tiny.yaml up --detach --remove-orphans || true
|
||||
fi
|
||||
|
||||
wait_for_containers_start 60
|
||||
echo ""
|
||||
|
||||
if [[ $status_code -ne 200 ]]; then
|
||||
echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
echo "The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo "🔴 The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo ""
|
||||
echo -e "sudo docker-compose -f docker/docker-compose-tiny.yaml ps -a"
|
||||
echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker#troubleshooting"
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
echo -e "sudo docker-compose -f docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
else
|
||||
echo -e "sudo docker-compose -f docker/druid-kafka-setup/docker-compose-tiny.yaml ps -a"
|
||||
fi
|
||||
echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker/#troubleshooting-of-common-issues"
|
||||
echo "or reach us on SigNoz for support https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
|
||||
SUPERVISORS="$(curl -so - http://localhost:8888/druid/indexer/v1/supervisor)"
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error - Checks", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Containers not started", "data": "some_checks", "setup_type": "'"$setup_type"'" } }'
|
||||
else
|
||||
SUPERVISORS="$(curl -so - http://localhost:8888/druid/indexer/v1/supervisor)"
|
||||
|
||||
DATASOURCES="$(curl -so - http://localhost:8888/druid/coordinator/v1/datasources)"
|
||||
DATASOURCES="$(curl -so - http://localhost:8888/druid/coordinator/v1/datasources)"
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error - Checks", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Containers not started", "SUPERVISORS": '"$SUPERVISORS"', "DATASOURCES": '"$DATASOURCES"' } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Error - Checks", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "error": "Containers not started", "SUPERVISORS": '"$SUPERVISORS"', "DATASOURCES": '"$DATASOURCES"', "setup_type": "'"$setup_type"'" } }'
|
||||
fi
|
||||
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
@@ -408,7 +460,7 @@ if [[ $status_code -ne 200 ]]; then
|
||||
exit 1
|
||||
|
||||
else
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Success", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'"} }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Installation Success", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'"}, "setup_type": "'"$setup_type"'" }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -418,17 +470,25 @@ else
|
||||
wget -q --post-data="$DATA" --header="$HEADER" "$URL" > /dev/null 2>&1
|
||||
fi
|
||||
echo "++++++++++++++++++ SUCCESS ++++++++++++++++++++++"
|
||||
echo "Your installation is complete!"
|
||||
echo ""
|
||||
echo "Your frontend is running on 'http://localhost:3000'."
|
||||
echo "🟢 Your installation is complete!"
|
||||
echo ""
|
||||
echo -e "🟢 Your frontend is running on http://localhost:3000"
|
||||
echo ""
|
||||
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
echo "ℹ️ To bring down SigNoz and clean volumes : sudo docker-compose -f docker/clickhouse-setup/docker-compose.yaml down -v"
|
||||
else
|
||||
echo "ℹ️ To bring down SigNoz and clean volumes : sudo docker-compose -f docker/druid-kafka-setup/docker-compose-tiny.yaml down -v"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "+++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
echo "Need help Getting Started?"
|
||||
echo "Join us on Slack https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
echo "👉 Need help Getting Started?"
|
||||
echo -e "Join us on Slack https://join.slack.com/t/signoz-community/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"
|
||||
echo ""
|
||||
echo "Please share your email to receive support & updates about SigNoz!"
|
||||
echo -e "\n📨 Please share your email to receive support & updates about SigNoz!"
|
||||
read -rp 'Email: ' email
|
||||
|
||||
while [[ $email == "" ]]
|
||||
@@ -436,7 +496,7 @@ else
|
||||
read -rp 'Email: ' email
|
||||
done
|
||||
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Identify Successful Installation", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "email": "'"$email"'" } }'
|
||||
DATA='{ "api_key": "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w", "type": "capture", "event": "Identify Successful Installation", "distinct_id": "'"$SIGNOZ_INSTALLATION_ID"'", "properties": { "os": "'"$os"'", "email": "'"$email"'", "setup_type": "'"$setup_type"'" } }'
|
||||
URL="https://app.posthog.com/capture"
|
||||
HEADER="Content-Type: application/json"
|
||||
|
||||
@@ -448,28 +508,4 @@ else
|
||||
|
||||
fi
|
||||
|
||||
echo -e "\nThank you!\n"
|
||||
|
||||
|
||||
##### Changing default memory limit of docker ############
|
||||
# # Check if memory is less and Confirm to increase size of docker machine
|
||||
# # https://github.com/docker/machine/releases
|
||||
# # On OS X
|
||||
|
||||
# $ curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-`uname -s`-`uname -m` >/usr/local/bin/docker-machine && \
|
||||
# chmod +x /usr/local/bin/docker-machine
|
||||
# # On Linux
|
||||
|
||||
# $ curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
|
||||
# chmod +x /tmp/docker-machine &&
|
||||
# sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
|
||||
|
||||
# VBoxManage list vms
|
||||
# docker-machine stop
|
||||
# VBoxManage modifyvm default --cpus 2
|
||||
# VBoxManage modifyvm default --memory 4096
|
||||
# docker-machine start
|
||||
|
||||
# VBoxManage showvminfo default | grep Memory
|
||||
# VBoxManage showvminfo default | grep CPU
|
||||
|
||||
echo -e "\n🙏 Thank you!\n"
|
||||
@@ -5,64 +5,72 @@ metadata:
|
||||
data:
|
||||
supervisor-spec.json: |
|
||||
{
|
||||
"type": "kafka",
|
||||
"dataSchema": {
|
||||
"dataSource": "flattened_spans",
|
||||
"parser": {
|
||||
"type": "string",
|
||||
"parseSpec": {
|
||||
"format": "json",
|
||||
"timestampSpec": {
|
||||
"column": "StartTimeUnixNano",
|
||||
"format": "nano"
|
||||
},
|
||||
"dimensionsSpec": {
|
||||
"dimensions": [
|
||||
"TraceId",
|
||||
"SpanId",
|
||||
"ParentSpanId",
|
||||
"Name",
|
||||
"ServiceName",
|
||||
"References",
|
||||
"Tags",
|
||||
{
|
||||
"type": "string",
|
||||
"name": "TagsKeys",
|
||||
"multiValueHandling": "ARRAY"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "TagsValues",
|
||||
"multiValueHandling": "ARRAY"
|
||||
},
|
||||
{ "name": "DurationNano", "type": "Long" },
|
||||
{ "name": "Kind", "type": "int" },
|
||||
{ "name": "StatusCode", "type": "int" }
|
||||
]
|
||||
"type": "kafka",
|
||||
"dataSchema": {
|
||||
"dataSource": "flattened_spans",
|
||||
"parser": {
|
||||
"type": "string",
|
||||
"parseSpec": {
|
||||
"format": "json",
|
||||
"timestampSpec": {
|
||||
"column": "StartTimeUnixNano",
|
||||
"format": "nano"
|
||||
},
|
||||
"dimensionsSpec": {
|
||||
"dimensions": [
|
||||
"TraceId",
|
||||
"SpanId",
|
||||
"ParentSpanId",
|
||||
"Name",
|
||||
"ServiceName",
|
||||
"References",
|
||||
"Tags",
|
||||
"ExternalHttpMethod",
|
||||
"ExternalHttpUrl",
|
||||
"Component",
|
||||
"DBSystem",
|
||||
"DBName",
|
||||
"DBOperation",
|
||||
"PeerService",
|
||||
{
|
||||
"type": "string",
|
||||
"name": "TagsKeys",
|
||||
"multiValueHandling": "ARRAY"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "TagsValues",
|
||||
"multiValueHandling": "ARRAY"
|
||||
},
|
||||
{ "name": "DurationNano", "type": "Long" },
|
||||
{ "name": "Kind", "type": "int" },
|
||||
{ "name": "StatusCode", "type": "int" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"metricsSpec" : [
|
||||
{ "type": "quantilesDoublesSketch", "name": "QuantileDuration", "fieldName": "DurationNano" }
|
||||
],
|
||||
"granularitySpec": {
|
||||
"type": "uniform",
|
||||
"segmentGranularity": "DAY",
|
||||
"queryGranularity": "NONE",
|
||||
"rollup": false
|
||||
}
|
||||
},
|
||||
"metricsSpec" : [
|
||||
{ "type": "quantilesDoublesSketch", "name": "QuantileDuration", "fieldName": "DurationNano" }
|
||||
],
|
||||
"granularitySpec": {
|
||||
"type": "uniform",
|
||||
"segmentGranularity": "DAY",
|
||||
"queryGranularity": "NONE",
|
||||
"rollup": false
|
||||
}
|
||||
},
|
||||
"tuningConfig": {
|
||||
"type": "kafka",
|
||||
"reportParseExceptions": true
|
||||
},
|
||||
"ioConfig": {
|
||||
"topic": "flattened_spans",
|
||||
"replicas": 1,
|
||||
"taskDuration": "PT20M",
|
||||
"completionTimeout": "PT30M",
|
||||
"consumerProperties": {
|
||||
"bootstrap.servers": "signoz-kafka:9092"
|
||||
"tuningConfig": {
|
||||
"type": "kafka",
|
||||
"reportParseExceptions": true
|
||||
},
|
||||
"ioConfig": {
|
||||
"topic": "flattened_spans",
|
||||
"replicas": 1,
|
||||
"taskDuration": "PT20M",
|
||||
"completionTimeout": "PT30M",
|
||||
"consumerProperties": {
|
||||
"bootstrap.servers": "signoz-kafka:9092"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ metadata:
|
||||
data:
|
||||
otel-collector-config: |
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
jaeger:
|
||||
protocols:
|
||||
grpc:
|
||||
thrift_http:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
@@ -36,9 +36,16 @@ data:
|
||||
health_check: {}
|
||||
zpages: {}
|
||||
exporters:
|
||||
kafka:
|
||||
kafka/traces:
|
||||
brokers:
|
||||
- signoz-kafka:9092
|
||||
topic: 'otlp_spans'
|
||||
protocol_version: 2.0.0
|
||||
|
||||
kafka/metrics:
|
||||
brokers:
|
||||
- signoz-kafka:9092
|
||||
topic: 'otlp_metrics'
|
||||
protocol_version: 2.0.0
|
||||
service:
|
||||
extensions: [health_check, zpages]
|
||||
@@ -46,8 +53,8 @@ data:
|
||||
traces:
|
||||
receivers: [jaeger, otlp]
|
||||
processors: [memory_limiter, batch, queued_retry]
|
||||
exporters: [kafka]
|
||||
exporters: [kafka/traces]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [kafka]
|
||||
exporters: [kafka/metrics]
|
||||
@@ -10,12 +10,12 @@ dependencies:
|
||||
version: 0.2.18
|
||||
- name: flattener-processor
|
||||
repository: file://./signoz-charts/flattener-processor
|
||||
version: 0.2.0
|
||||
version: 0.3.4
|
||||
- name: query-service
|
||||
repository: file://./signoz-charts/query-service
|
||||
version: 0.2.2
|
||||
version: 0.3.4
|
||||
- name: frontend
|
||||
repository: file://./signoz-charts/frontend
|
||||
version: 0.2.3
|
||||
digest: sha256:31c8e3a8a4c89d0e6071c6687f074e88b3eed8ce86310314e5b6f94e5d5017be
|
||||
generated: "2021-05-18T16:54:30.24831+05:30"
|
||||
version: 0.3.4
|
||||
digest: sha256:49f8b43acecdb7cb0fb8ed5af1488bfbef5b66be02e17bb716403750a6894844
|
||||
generated: "2021-08-10T23:37:01.176317+05:30"
|
||||
|
||||
@@ -15,12 +15,12 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.2.2
|
||||
version: 0.3.2
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 0.2.2
|
||||
appVersion: 0.3.2
|
||||
|
||||
dependencies:
|
||||
- name: zookeeper
|
||||
@@ -34,10 +34,10 @@ dependencies:
|
||||
version: 0.2.18
|
||||
- name: flattener-processor
|
||||
repository: "file://./signoz-charts/flattener-processor"
|
||||
version: 0.2.0
|
||||
version: 0.3.4
|
||||
- name: query-service
|
||||
repository: "file://./signoz-charts/query-service"
|
||||
version: 0.2.2
|
||||
version: 0.3.4
|
||||
- name: frontend
|
||||
repository: "file://./signoz-charts/frontend"
|
||||
version: 0.2.3
|
||||
version: 0.3.4
|
||||
@@ -14,8 +14,8 @@ type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.2.0
|
||||
version: 0.3.4
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: 0.2.0
|
||||
appVersion: 0.3.4
|
||||
|
||||
@@ -14,8 +14,8 @@ type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.2.3
|
||||
version: 0.3.4
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: 0.2.3
|
||||
appVersion: 0.3.4
|
||||
|
||||
@@ -9,6 +9,16 @@ data:
|
||||
server {
|
||||
listen {{ .Values.service.port }};
|
||||
server_name _;
|
||||
|
||||
gzip on;
|
||||
gzip_static on;
|
||||
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
gzip_proxied any;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
@@ -14,8 +14,8 @@ type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.2.2
|
||||
version: 0.3.4
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: 0.2.2
|
||||
appVersion: 0.3.4
|
||||
|
||||
@@ -36,7 +36,8 @@ spec:
|
||||
value: {{ .Values.configVars.DruidClientUrl }}
|
||||
- name: DruidDatasource
|
||||
value: {{ .Values.configVars.DruidDatasource }}
|
||||
|
||||
- name: STORAGE
|
||||
value: {{ .Values.configVars.STORAGE }}
|
||||
|
||||
# livenessProbe:
|
||||
# httpGet:
|
||||
|
||||
@@ -16,6 +16,7 @@ fullnameOverride: ""
|
||||
configVars:
|
||||
DruidClientUrl: http://signoz-druid-router:8888
|
||||
DruidDatasource: flattened_spans
|
||||
STORAGE: druid
|
||||
POSTHOG_API_KEY: "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w"
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ kafka:
|
||||
zookeeperConnectionTimeoutMs: 6000
|
||||
|
||||
druid:
|
||||
image:
|
||||
tag: 0.21.1-rc2
|
||||
|
||||
configVars:
|
||||
|
||||
# To store data on local disks attached
|
||||
@@ -45,3 +48,4 @@ query-service:
|
||||
configVars:
|
||||
DruidClientUrl: http://signoz-druid-router:8888
|
||||
DruidDatasource: flattened_spans
|
||||
STORAGE: druid
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
.vscode
|
||||
build
|
||||
build
|
||||
.env
|
||||
1
frontend/.npmrc
Normal file
1
frontend/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
registry = 'https://registry.npmjs.org/'
|
||||
1
frontend/.nvmrc
Normal file
1
frontend/.nvmrc
Normal file
@@ -0,0 +1 @@
|
||||
12.13.0
|
||||
@@ -1,5 +1,11 @@
|
||||
# stage1 as builder
|
||||
FROM node:12-alpine as builder
|
||||
FROM node:12.18.0 as builder
|
||||
|
||||
# Add Maintainer Info
|
||||
LABEL maintainer="signoz"
|
||||
|
||||
ARG TARGETOS=linux
|
||||
ARG TARGETARCH
|
||||
|
||||
WORKDIR /frontend
|
||||
|
||||
@@ -14,7 +20,7 @@ COPY . .
|
||||
# Build the project and copy the files
|
||||
RUN yarn build
|
||||
|
||||
FROM nginx:1.12-alpine
|
||||
FROM nginx:1.18-alpine
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
# Docker
|
||||
# Configuring Over Local
|
||||
1. Docker
|
||||
1. Without Docker
|
||||
|
||||
## With Docker
|
||||
|
||||
**Building image**
|
||||
|
||||
@@ -14,12 +18,21 @@ or
|
||||
docker tag signoz/frontend:latest 7296823551/signoz:latest
|
||||
```
|
||||
|
||||
**Running locally**
|
||||
|
||||
```
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
## Without Docker
|
||||
Follow the steps below
|
||||
|
||||
1. ```git clone https://github.com/SigNoz/signoz.git && cd signoz/frontend```
|
||||
1. change baseURL to ```<test environment URL>``` in file ```src/constants/env.ts```
|
||||
|
||||
1. ```yarn install```
|
||||
1. ```yarn dev```
|
||||
|
||||
```Note: Please ping us in #contributing channel in our slack community and we will DM you with <test environment URL>```
|
||||
|
||||
# Getting Started with Create React App
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
server {
|
||||
listen 3000;
|
||||
server_name _;
|
||||
|
||||
gzip on;
|
||||
gzip_static on;
|
||||
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
gzip_proxied any;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
24
frontend/eslintrc.js
Normal file
24
frontend/eslintrc.js
Normal file
@@ -0,0 +1,24 @@
|
||||
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,
|
||||
},
|
||||
};
|
||||
2
frontend/package-lock.json
generated
2
frontend/package-lock.json
generated
@@ -21587,4 +21587,4 @@
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,14 @@
|
||||
"description": "",
|
||||
"main": "webpack.config.js",
|
||||
"scripts": {
|
||||
"dev": "NODE_ENV=development webpack serve",
|
||||
"dev": "NODE_ENV=development webpack serve --progress",
|
||||
"start": "node scripts/start.js",
|
||||
"build": "webpack --config=webpack.config.prod.js",
|
||||
"prettify": "prettier --write ."
|
||||
"build": "webpack --config=webpack.config.prod.js --progress",
|
||||
"prettify": "prettier --write .",
|
||||
"lint": "eslint src"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.13.0"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
@@ -15,7 +19,6 @@
|
||||
"@ant-design/icons": "^4.6.2",
|
||||
"@auth0/auth0-react": "^1.2.0",
|
||||
"@babel/core": "7.12.3",
|
||||
"@material-ui/core": "^4.0.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "0.4.2",
|
||||
"@svgr/webpack": "5.4.0",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
@@ -48,13 +51,10 @@
|
||||
"chart.js": "^2.9.4",
|
||||
"css-loader": "4.3.0",
|
||||
"d3": "^6.2.0",
|
||||
"d3-array": "^2.8.0",
|
||||
"d3-ease": "^2.0.0",
|
||||
"d3-flame-graph": "^3.1.1",
|
||||
"d3-tip": "^0.9.1",
|
||||
"dotenv": "8.2.0",
|
||||
"dotenv-expand": "5.1.0",
|
||||
"eslint": "^7.11.0",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-config-react-app": "^6.0.0",
|
||||
"eslint-plugin-flowtype": "^5.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
@@ -72,11 +72,7 @@
|
||||
"jest-circus": "26.6.0",
|
||||
"jest-resolve": "26.6.0",
|
||||
"jest-watch-typeahead": "0.6.1",
|
||||
"material-ui-chip-input": "^2.0.0-beta.2",
|
||||
"mini-css-extract-plugin": "0.11.3",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.4",
|
||||
"pnp-webpack-plugin": "1.6.4",
|
||||
"postcss-flexbugs-fixes": "4.2.1",
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-normalize": "8.0.1",
|
||||
"postcss-preset-env": "6.7.0",
|
||||
@@ -96,7 +92,6 @@
|
||||
"react-refresh": "^0.8.3",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-vis": "^1.11.7",
|
||||
"recharts": "^1.8.5",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"resolve": "1.18.1",
|
||||
@@ -115,12 +110,6 @@
|
||||
"webpack-manifest-plugin": "2.2.0",
|
||||
"workbox-webpack-plugin": "5.1.4"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
@@ -140,8 +129,10 @@
|
||||
"@babel/preset-env": "^7.12.17",
|
||||
"@babel/preset-react": "^7.12.13",
|
||||
"@babel/preset-typescript": "^7.12.17",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"autoprefixer": "^9.0.0",
|
||||
"babel-plugin-styled-components": "^1.12.0",
|
||||
"compression-webpack-plugin": "^8.0.0",
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-csso": "^4.0.1",
|
||||
@@ -151,6 +142,8 @@
|
||||
"husky": "4.3.8",
|
||||
"less-plugin-npm-import": "^2.1.0",
|
||||
"lint-staged": "10.5.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"portfinder-sync": "^0.0.2",
|
||||
"prettier": "2.2.1",
|
||||
"react-hot-loader": "^4.13.0",
|
||||
"react-is": "^17.0.1",
|
||||
|
||||
266
frontend/src/assets/NotFound.tsx
Normal file
266
frontend/src/assets/NotFound.tsx
Normal file
@@ -0,0 +1,266 @@
|
||||
import React from "react";
|
||||
|
||||
const NotFound = (): JSX.Element => {
|
||||
return (
|
||||
<svg
|
||||
width="360"
|
||||
height="196"
|
||||
viewBox="0 0 360 196"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clip-path="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"
|
||||
/>
|
||||
<path
|
||||
d="M174.381 55.9605C145.583 55.9605 124.907 74.4362 124.907 117.546C124.907 166.404 145.583 179.337 174.381 179.337C203.178 179.337 225.086 165.173 225.086 117.546C225.086 66.6354 203.178 55.9605 174.381 55.9605ZM174.57 163.12C154.624 163.12 144.204 151.418 144.204 117.578C144.204 87.7188 155.051 71.9728 174.997 71.9728C194.942 71.9728 205.789 82.3158 205.789 117.578C205.789 150.565 194.516 163.12 174.57 163.12Z"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
d="M107.663 145.26H95.7562V110.198C95.7562 108.336 95.0164 106.55 93.6996 105.233C92.3828 103.916 90.5968 103.176 88.7345 103.176H85.9445C85.0224 103.176 84.1094 103.358 83.2574 103.711C82.4055 104.064 81.6315 104.581 80.9794 105.233C80.3274 105.885 79.8102 106.659 79.4573 107.511C79.1044 108.363 78.9228 109.276 78.9228 110.198V145.26H45.3384C44.6475 145.26 43.9683 145.081 43.3667 144.741C42.7652 144.402 42.2617 143.912 41.9051 143.32C41.5484 142.729 41.3508 142.055 41.3314 141.364C41.3119 140.673 41.4713 139.99 41.7941 139.379L77.3395 72.1025C77.7826 71.2638 78.0512 70.3439 78.1291 69.3985C78.2069 68.453 78.0924 67.5016 77.7924 66.6017C77.4924 65.7017 77.0131 64.8719 76.3835 64.1623C75.754 63.4527 74.9871 62.878 74.1293 62.4729L72.031 61.482C70.4017 60.7126 68.5389 60.599 66.8282 61.1647C65.1174 61.7304 63.6896 62.9321 62.8402 64.5211L19.4879 145.62C18.7497 147.001 18.3635 148.543 18.3635 150.108V150.108C18.3635 151.359 18.6097 152.597 19.0882 153.752C19.5667 154.907 20.2681 155.957 21.1522 156.841C22.0364 157.725 23.086 158.427 24.2412 158.905C25.3964 159.384 26.6345 159.63 27.8848 159.63H78.9228V181.801C78.9228 182.906 79.1405 184.001 79.5635 185.022C79.9865 186.043 80.6064 186.971 81.388 187.752C82.1695 188.534 83.0974 189.154 84.1186 189.577C85.1397 190 86.2342 190.217 87.3395 190.217H87.3395C88.4448 190.217 89.5393 190 90.5605 189.577C91.5816 189.154 92.5095 188.534 93.291 187.752C94.0726 186.971 94.6926 186.043 95.1155 185.022C95.5385 184.001 95.7562 182.906 95.7562 181.801V159.63H107.663C109.568 159.63 111.396 158.873 112.743 157.525C114.091 156.178 114.848 154.35 114.848 152.445V152.445C114.848 150.539 114.091 148.712 112.743 147.364C111.396 146.017 109.568 145.26 107.663 145.26V145.26Z"
|
||||
fill="#002B76"
|
||||
/>
|
||||
<path
|
||||
d="M328.14 145.26H316.233V110.198C316.233 108.336 315.493 106.55 314.177 105.233C312.86 103.916 311.074 103.176 309.212 103.176H306.422C305.499 103.176 304.586 103.358 303.734 103.711C302.883 104.064 302.108 104.581 301.456 105.233C300.804 105.885 300.287 106.659 299.934 107.511C299.581 108.363 299.4 109.276 299.4 110.198V145.26H265.815C265.125 145.26 264.445 145.081 263.844 144.741C263.242 144.402 262.739 143.912 262.382 143.32C262.025 142.729 261.828 142.055 261.808 141.364C261.789 140.673 261.948 139.99 262.271 139.379L297.817 72.1025C298.26 71.2638 298.528 70.3439 298.606 69.3985C298.684 68.453 298.569 67.5016 298.269 66.6017C297.969 65.7017 297.49 64.8719 296.861 64.1623C296.231 63.4527 295.464 62.878 294.606 62.4729L292.508 61.482C290.879 60.7126 289.016 60.599 287.305 61.1647C285.594 61.7304 284.167 62.9321 283.317 64.5211L239.965 145.62C239.227 147.001 238.84 148.543 238.84 150.108V150.108C238.84 152.634 239.844 155.055 241.629 156.841C243.415 158.627 245.837 159.63 248.362 159.63H299.4V181.801C299.4 184.033 300.287 186.174 301.865 187.752C303.443 189.331 305.584 190.217 307.817 190.217V190.217C310.049 190.217 312.19 189.331 313.768 187.752C315.346 186.174 316.233 184.033 316.233 181.801V159.63H328.14C330.045 159.63 331.873 158.873 333.22 157.525C334.568 156.178 335.325 154.35 335.325 152.445V152.445C335.325 150.539 334.568 148.712 333.22 147.364C331.873 146.017 330.045 145.26 328.14 145.26Z"
|
||||
fill="#002B76"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
d="M168.41 31.4197C175.107 31.4197 180.535 24.3861 180.535 15.7098C180.535 7.03353 175.107 0 168.41 0C161.714 0 156.285 7.03353 156.285 15.7098C156.285 24.3861 161.714 31.4197 168.41 31.4197Z"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
opacity="0.1"
|
||||
d="M168.41 26.6751C162.336 26.6751 157.306 20.8882 156.423 13.3375C156.331 14.1249 156.285 14.9171 156.285 15.7098C156.285 24.3861 161.714 31.4196 168.41 31.4196C175.107 31.4196 180.535 24.3861 180.535 15.7098C180.536 14.9171 180.49 14.1249 180.398 13.3375C179.515 20.8882 174.484 26.6751 168.41 26.6751Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M193.083 61.7167C192.823 62.7868 191.7 63.6437 190.457 64.2425C187.843 65.5013 184.618 65.8769 181.49 66.003C180.692 66.0515 179.892 66.0367 179.096 65.9588C177.555 65.8097 176.108 65.1449 174.992 64.0719C174.912 64.0199 174.847 63.9486 174.802 63.8645C174.757 63.7805 174.734 63.6865 174.736 63.5914C174.737 63.4962 174.763 63.403 174.81 63.3203C174.857 63.2377 174.925 63.1684 175.006 63.119C176.671 61.2898 179.45 60.1683 182.249 59.3607C184.372 58.7484 188.073 57.1624 190.388 57.3764C192.63 57.5837 193.412 60.3657 193.083 61.7167Z"
|
||||
fill="#3F3D56"
|
||||
/>
|
||||
<path
|
||||
opacity="0.1"
|
||||
d="M193.083 61.7167C192.823 62.7868 191.7 63.6437 190.457 64.2425C187.843 65.5013 184.618 65.8769 181.49 66.003C180.692 66.0515 179.892 66.0367 179.096 65.9588C177.555 65.8097 176.108 65.1449 174.992 64.0719C174.912 64.0199 174.847 63.9486 174.802 63.8645C174.757 63.7805 174.734 63.6865 174.736 63.5914C174.737 63.4962 174.763 63.403 174.81 63.3203C174.857 63.2377 174.925 63.1684 175.006 63.119C176.671 61.2898 179.45 60.1683 182.249 59.3607C184.372 58.7484 188.073 57.1624 190.388 57.3764C192.63 57.5837 193.412 60.3657 193.083 61.7167Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M159.845 53.7194C159.047 55.2833 158.902 57.1001 159.443 58.7705C159.993 60.4283 161.023 61.8856 162.401 62.9579C165.784 65.6692 170.439 66.0423 174.774 66.0046C178.573 65.9716 182.367 65.7116 186.135 65.226C187.397 65.1141 188.638 64.826 189.821 64.3701C191.236 63.758 192.479 62.6352 192.983 61.1783C193.486 59.7213 193.129 57.9373 191.933 56.965C190.882 56.1106 189.432 55.9931 188.08 55.9119L180.344 55.447C181.108 54.6735 182.126 54.236 183.057 53.6737C184.291 52.9277 185.112 51.6751 186.01 50.5459C187.393 48.8925 188.898 47.345 190.513 45.9162C190.764 47.3605 191.678 48.5465 192.753 49.543C193.829 50.5396 195.068 51.3418 196.186 52.2907C198.893 54.5887 200.842 57.7078 203.689 59.83C205.647 59.3153 207.478 58.4013 209.066 57.1453L207.96 55.1411C207.868 54.9348 207.724 54.7556 207.543 54.6208C207.23 54.4281 206.826 54.5274 206.462 54.4728C205.49 54.3271 205.066 53.2049 204.684 52.2991C203.637 49.8123 201.632 47.8829 199.92 45.7974C198.657 44.258 197.536 42.6067 196.571 40.8642C195.996 39.8249 195.469 38.7428 194.689 37.8474C193.908 36.9521 192.814 36.2481 191.627 36.2456C190.577 36.2434 189.609 36.7762 188.707 37.3122C185.958 38.9447 183.314 40.7463 180.789 42.7065C179.467 43.7324 178.154 44.8163 176.604 45.4454C175.952 45.7102 175.264 45.8912 174.637 46.2134C173.541 46.7778 172.708 47.7328 171.812 48.5804C168.617 51.6039 164.241 53.5627 159.845 53.7194Z"
|
||||
fill="#3F3D56"
|
||||
/>
|
||||
<path
|
||||
d="M176.021 32.1999C175.985 33.124 175.788 34.0349 175.44 34.8916C175.263 35.3189 175 35.7052 174.668 36.0265C174.335 36.3478 173.94 36.5971 173.507 36.7589C172.892 36.9237 172.247 36.9446 171.623 36.82C171.078 36.7632 170.554 36.5844 170.088 36.2971C169.362 35.7984 169.001 34.9085 168.869 34.0376C168.737 33.1677 168.796 32.2789 168.712 31.4028C168.63 30.6951 168.495 29.9945 168.309 29.3067C168.252 29.0779 168.194 28.8502 168.137 28.6225C168.081 28.3947 168.026 28.167 167.976 27.9392C167.929 27.7252 167.886 27.5101 167.849 27.294C167.819 27.1116 167.791 26.9281 167.771 26.7436C167.753 26.1966 167.662 25.6545 167.5 25.1315C167.349 24.7923 167.159 24.4715 166.935 24.1752C166.839 24.0381 166.746 23.9011 166.661 23.7587C166.414 23.3888 166.299 22.9463 166.335 22.503C166.345 22.4345 166.362 22.367 166.385 22.3016C166.393 22.2763 166.403 22.251 166.413 22.2268C166.508 22.201 166.595 22.1525 166.667 22.0854C166.739 22.0184 166.793 21.9348 166.826 21.8419C166.862 21.6424 166.845 21.4369 166.776 21.2462C166.697 20.9797 166.589 20.7226 166.454 20.4797C166.366 20.3194 166.065 20.0305 166.063 19.8471C166.059 19.478 166.78 19.1807 167.072 19.0352C167.964 18.5888 168.958 18.3872 169.953 18.4511C170.591 18.4943 171.282 18.6904 171.635 19.225C171.951 19.7068 171.909 20.331 172.044 20.8909C172.058 20.9723 172.092 21.0488 172.144 21.1133C172.213 21.176 172.299 21.2158 172.392 21.2272C172.548 21.2583 172.708 21.2647 172.866 21.2462H172.867C172.909 21.2429 172.95 21.2369 172.991 21.2283C173.238 21.1828 173.471 21.0823 173.673 20.9341C173.803 20.8993 173.935 20.8708 174.068 20.8487C174.073 20.8482 174.079 20.8471 174.084 20.8455C174.612 22.5125 174.681 24.2996 175.113 25.9971C175.327 26.8416 175.634 27.6756 175.677 28.5444C175.68 28.5824 175.681 28.6214 175.682 28.6604C175.689 28.9398 175.666 29.2213 175.678 29.4996C175.682 29.625 175.696 29.7498 175.72 29.8729C175.767 30.0708 175.826 30.2659 175.896 30.457L175.899 30.4665C175.919 30.5276 175.938 30.5899 175.954 30.6521C175.966 30.6974 175.976 30.7417 175.985 30.787L175.986 30.7902C176.064 31.2561 176.076 31.7307 176.021 32.1999V32.1999Z"
|
||||
fill="#FBBEBE"
|
||||
/>
|
||||
<path
|
||||
d="M168.621 21.2979C172.057 21.2979 174.842 18.5128 174.842 15.0772C174.842 11.6417 172.057 8.85657 168.621 8.85657C165.186 8.85657 162.4 11.6417 162.4 15.0772C162.4 18.5128 165.186 21.2979 168.621 21.2979Z"
|
||||
fill="#FBBEBE"
|
||||
/>
|
||||
<path
|
||||
d="M208.115 48.9704C207.935 47.2732 207.331 45.6484 206.361 44.2448C206.522 45.2043 206.684 46.1634 206.846 47.1221C206.644 47.1804 206.43 47.1786 206.23 47.117C206.029 47.0554 205.851 46.9366 205.717 46.7752C205.455 46.4482 205.255 46.0763 205.126 45.6777C204.419 43.9232 203.495 42.2644 202.375 40.7401C198.415 40.4101 194.5 38.7685 191.018 36.8549C187.534 34.9423 184.274 32.649 180.837 30.6553C180.241 30.2951 179.62 29.9779 178.979 29.7063C177.904 29.2751 176.696 29.0516 175.677 28.5444C175.608 28.5107 175.54 28.4749 175.472 28.438C175.242 28.3127 175.024 28.1662 174.821 28.0004C174.711 27.9113 174.607 27.8155 174.509 27.7136C174 27.1218 173.597 26.4471 173.316 25.7188C172.769 24.5084 172.574 23.0481 172.028 21.8377C172.279 21.6031 172.561 21.4041 172.866 21.2462H172.867C172.911 21.223 172.956 21.2009 173.001 21.1798C173.217 21.078 173.442 20.9958 173.673 20.9341C173.803 20.8993 173.935 20.8709 174.068 20.8487C174.073 20.8482 174.079 20.8471 174.084 20.8456C174.7 20.7452 175.331 20.7951 175.924 20.9911C176.79 21.2842 177.521 21.8693 178.249 22.4229C179.433 23.2567 180.568 24.1572 181.65 25.1199C182.251 25.6956 182.799 26.3282 183.445 26.8512C183.982 27.2657 184.549 27.6409 185.14 27.974C188.637 30.0574 192.135 32.1405 195.633 34.2232C196.817 34.9285 198.002 35.6339 199.159 36.3804C200.918 37.5149 202.613 38.7442 204.308 39.9726C205.306 40.6958 206.304 41.4195 207.302 42.1435C207.63 42.3523 207.917 42.618 208.151 42.9279C208.358 43.2798 208.486 43.6722 208.527 44.0782C208.778 45.7186 208.636 47.395 208.115 48.9704V48.9704Z"
|
||||
fill="#FBBEBE"
|
||||
/>
|
||||
<path
|
||||
d="M177.563 36.878C177.143 38.7601 175.241 39.8977 174.247 41.5509C173.011 43.6027 173.515 45.9876 173.979 48.3378C173.132 49.0684 172.284 49.7991 171.435 50.5298C170.967 50.9315 170.499 51.3353 169.995 51.6906C169.26 52.183 168.492 52.6241 167.696 53.0107C166.946 53.3966 166.195 53.7828 165.444 54.1694C164.747 54.5618 164.007 54.8751 163.24 55.1035C161.76 55.4831 160.19 55.2174 158.726 54.7777C158.553 54.7325 158.388 54.6648 158.233 54.5764C158.141 54.5219 158.062 54.4499 157.999 54.3644C157.854 54.1058 157.802 53.8059 157.85 53.5136C157.999 51.0506 158.601 48.6393 159.201 46.2459C159.521 44.8101 159.952 43.4011 160.49 42.0317C161.017 40.8583 161.624 39.7219 162.305 38.6304C163.056 37.257 163.946 35.9643 164.962 34.7725C165.456 34.3138 165.872 33.7774 166.193 33.1846C166.567 32.3306 166.423 31.3511 166.499 30.4212C166.557 29.7225 166.742 29.0404 167.046 28.4084V28.4074C167.208 28.067 167.404 27.7435 167.63 27.4416C167.732 27.6799 167.835 27.9178 167.937 28.1554C168.004 28.3114 168.071 28.4671 168.137 28.6225C168.224 28.8228 168.309 29.0224 168.394 29.2214C168.64 29.7928 168.885 30.3639 169.13 30.9347C169.395 31.6536 169.772 32.3258 170.248 32.9264C170.465 33.2339 170.759 33.4797 171.1 33.6399C171.441 33.8002 171.817 33.8692 172.193 33.8404C172.568 33.8117 172.93 33.686 173.242 33.4757C173.555 33.2654 173.807 32.9777 173.975 32.6406C174.33 32.0115 174.586 31.3321 174.736 30.6258C174.945 29.7657 174.973 28.872 174.821 28.0004C174.567 26.3219 173.853 24.6075 173.334 23.0481C173.123 22.5282 173.001 21.9765 172.972 21.416C172.974 21.353 172.98 21.2902 172.991 21.2283C172.995 21.2125 172.998 21.1956 173.001 21.1798C173.217 21.0781 173.442 20.9958 173.673 20.9342C173.803 20.8994 173.935 20.8709 174.068 20.8488C174.524 23.3202 174.982 25.7916 175.44 28.2629C175.45 28.3209 175.462 28.3789 175.472 28.438C175.538 28.7922 175.604 29.1465 175.678 29.4997C175.744 29.8202 175.816 30.1397 175.896 30.4571L175.899 30.4665C175.927 30.5741 175.955 30.6806 175.985 30.7871L175.986 30.7902C176.067 31.0812 176.158 31.3701 176.26 31.6548C176.88 33.3702 177.961 35.0972 177.563 36.878Z"
|
||||
fill="#002B76"
|
||||
/>
|
||||
<path
|
||||
d="M202.809 63.3263C202.789 63.6889 202.86 64.0506 203.013 64.3795C203.403 65.0911 204.337 65.2528 205.145 65.3194C209.867 65.7075 214.618 65.5628 219.307 64.8879C219.562 64.8705 219.809 64.7939 220.028 64.6642C220.695 64.1967 220.284 63.0575 219.556 62.6928C218.828 62.328 217.964 62.4159 217.165 62.258C216.371 62.0582 215.616 61.7305 214.927 61.2876C213.307 60.3568 211.711 59.3864 210.138 58.3764C209.202 57.7751 208.097 57.1334 207.042 57.4899C204.186 58.4562 202.79 60.2449 202.809 63.3263Z"
|
||||
fill="#3F3D56"
|
||||
/>
|
||||
<path
|
||||
d="M168 27.8074V27.8085C167.993 27.8528 167.985 27.896 167.976 27.9392C167.964 28.0109 167.951 28.0837 167.937 28.1554C167.806 28.8249 167.646 29.4912 167.461 30.1534C166.955 31.9826 166.277 33.7824 165.605 35.5558C163.8 40.311 161.994 45.0664 160.188 49.8223C159.733 51.02 159.279 52.2188 158.761 53.3923C158.588 53.7835 158.41 54.1778 158.233 54.5763C157.598 56.0029 156.989 57.4758 156.786 58.9941C156.597 59.9933 156.576 61.0169 156.722 62.0232C156.924 63.0185 157.528 63.9906 158.474 64.3586C158.936 64.5389 159.597 64.7803 159.47 65.2601C159.402 65.5236 159.102 65.6523 158.834 65.6966C158.479 65.7531 158.115 65.7309 157.77 65.6314C157.424 65.5319 157.105 65.3576 156.835 65.1209C156.33 64.6728 155.942 63.9759 155.27 63.901C154.805 63.8504 154.377 64.1288 153.951 64.3238C152.213 65.1177 150.189 64.5621 148.364 63.998C148.507 63.2589 149.25 62.7718 149.987 62.6242C150.724 62.4755 151.486 62.581 152.238 62.5609C152.478 62.5738 152.717 62.5123 152.922 62.3849C153.105 62.2165 153.234 61.9968 153.291 61.7544C153.775 60.3195 154.135 58.8457 154.367 57.3493C154.61 55.7857 154.711 54.1978 155.057 52.6532C155.326 51.4481 155.741 50.2809 156.098 49.0979C156.787 46.6622 157.353 44.1933 157.793 41.7006C158.016 40.665 158.175 39.6168 158.271 38.5618C158.331 37.6867 158.302 36.8074 158.387 35.9354C158.528 34.801 158.765 33.6805 159.094 32.5857C159.417 31.3912 159.739 30.1973 160.061 29.0041C160.538 27.2381 161.051 25.4035 162.261 24.0307C162.682 23.5475 163.197 23.1557 163.775 22.8796C164.353 22.6036 164.981 22.4492 165.622 22.426C165.862 22.4257 166.101 22.4515 166.335 22.503C166.374 22.5125 166.413 22.522 166.452 22.5325C166.708 22.5993 166.953 22.7008 167.181 22.8341C167.554 22.5968 167.744 22.6801 167.992 23.046C168.209 23.4332 168.311 23.8742 168.287 24.3175C168.308 25.4875 168.212 26.6566 168 27.8074Z"
|
||||
fill="#FBBEBE"
|
||||
/>
|
||||
<path
|
||||
d="M168.41 29.2055L168.394 29.2214L168.309 29.3068L167.461 30.1534L167.046 28.4084L165.622 22.4261C165.862 22.4258 166.101 22.4516 166.335 22.503C166.345 22.4345 166.362 22.3671 166.385 22.3016L166.452 22.5325L166.935 24.1752L167.849 27.294L168 27.8075V27.8085L168.41 29.2055Z"
|
||||
fill="#002B76"
|
||||
/>
|
||||
<path
|
||||
d="M173.79 10.1201C173.789 10.6741 173.679 11.2225 173.466 11.7339C173.253 12.2454 172.942 12.7099 172.55 13.1009C172.408 13.2432 172.255 13.375 172.094 13.4951C171.366 14.0435 170.48 14.3404 169.569 14.3408H164.511C163.393 14.3391 162.322 13.8939 161.532 13.1029C160.742 12.312 160.298 11.2399 160.298 10.1222C160.298 9.00447 160.742 7.93243 161.532 7.14147C162.322 6.35051 163.393 5.90529 164.511 5.90356H169.569C170.687 5.90647 171.758 6.35152 172.549 7.14154C173.339 7.93155 173.786 9.00236 173.79 10.1201V10.1201Z"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
d="M178.532 10.4381C180.919 10.4381 182.855 8.5027 182.855 6.11526C182.855 3.72782 180.919 1.79242 178.532 1.79242C176.145 1.79242 174.209 3.72782 174.209 6.11526C174.209 8.5027 176.145 10.4381 178.532 10.4381Z"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
opacity="0.1"
|
||||
d="M178.427 1.79242C178.374 1.79242 178.321 1.79452 178.268 1.79642C179.387 1.83707 180.446 2.30989 181.222 3.11539C181.999 3.92088 182.433 4.99626 182.433 6.11526C182.433 7.23426 181.999 8.30964 181.222 9.11513C180.446 9.92063 179.387 10.3934 178.268 10.4341C178.321 10.436 178.374 10.4381 178.427 10.4381C179.573 10.4381 180.673 9.98266 181.483 9.17197C182.294 8.36128 182.749 7.26175 182.749 6.11526C182.749 4.96877 182.294 3.86924 181.483 3.05855C180.673 2.24786 179.573 1.79242 178.427 1.79242V1.79242Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
opacity="0.1"
|
||||
d="M157.867 1.79242C157.92 1.79242 157.972 1.79452 158.025 1.79642C156.907 1.83707 155.848 2.30989 155.071 3.11539C154.294 3.92088 153.86 4.99626 153.86 6.11526C153.86 7.23426 154.294 8.30964 155.071 9.11513C155.848 9.92063 156.907 10.3934 158.025 10.4341C157.972 10.436 157.92 10.4381 157.867 10.4381C156.721 10.4371 155.622 9.9812 154.813 9.17062C154.003 8.36004 153.548 7.26109 153.548 6.11526C153.548 4.96943 154.003 3.87048 154.813 3.0599C155.622 2.24932 156.721 1.79343 157.867 1.79242Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
opacity="0.1"
|
||||
d="M172.094 13.4951C171.366 14.0435 170.48 14.3404 169.569 14.3408H164.511C163.599 14.3404 162.713 14.0435 161.986 13.4951H172.094Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M204.758 44.818C204.758 44.818 205.848 47.9582 206.846 47.1221L206.051 43.0175L204.758 44.818Z"
|
||||
fill="#FBBEBE"
|
||||
/>
|
||||
<path
|
||||
d="M337.373 140.58C338.388 140.949 339.475 141.077 340.548 140.954C341.621 140.832 342.651 140.461 343.556 139.873C344.462 139.284 345.218 138.493 345.766 137.562C346.314 136.632 346.638 135.586 346.713 134.509C346.787 133.431 346.611 132.351 346.197 131.354C345.783 130.356 345.144 129.468 344.328 128.76C343.513 128.052 342.544 127.543 341.498 127.273C340.452 127.003 339.358 126.98 338.302 127.205L338.476 130.795L336.778 127.719C335.111 128.502 333.824 129.915 333.198 131.647C332.976 132.253 332.841 132.888 332.797 133.533C332.69 135.045 333.079 136.551 333.904 137.823C334.73 139.095 335.948 140.063 337.373 140.58V140.58Z"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#57B894"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
d="M192.146 114.466C195.292 114.466 197.843 111.166 197.843 107.095C197.843 103.023 195.292 99.723 192.146 99.723C189 99.723 186.45 103.023 186.45 107.095C186.45 111.166 189 114.466 192.146 114.466Z"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<path
|
||||
d="M187.79 128.874C187.79 132.205 183.14 134.906 177.403 134.906C171.667 134.906 167.016 132.205 167.016 128.874C167.016 125.989 170.504 123.577 175.165 122.987C175.907 122.889 176.655 122.841 177.403 122.843C178.657 122.839 179.908 122.974 181.133 123.245C185.026 124.113 187.79 126.308 187.79 128.874Z"
|
||||
fill="#2F2E41"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M162.492 104.917C163.418 104.917 164.168 104.167 164.168 103.241C164.168 102.316 163.418 101.566 162.492 101.566C161.567 101.566 160.817 102.316 160.817 103.241C160.817 104.167 161.567 104.917 162.492 104.917Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M193.654 104.917C194.58 104.917 195.33 104.167 195.33 103.241C195.33 102.316 194.58 101.566 193.654 101.566C192.729 101.566 191.979 102.316 191.979 103.241C191.979 104.167 192.729 104.917 193.654 104.917Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
opacity="0.3"
|
||||
d="M195.33 120.665C196.255 120.665 197.005 119.915 197.005 118.99C197.005 118.064 196.255 117.314 195.33 117.314C194.404 117.314 193.654 118.064 193.654 118.99C193.654 119.915 194.404 120.665 195.33 120.665Z"
|
||||
fill="#002B76"
|
||||
/>
|
||||
<path
|
||||
opacity="0.3"
|
||||
d="M154.451 120.665C155.376 120.665 156.126 119.915 156.126 118.99C156.126 118.064 155.376 117.314 154.451 117.314C153.525 117.314 152.775 118.064 152.775 118.99C152.775 119.915 153.525 120.665 154.451 120.665Z"
|
||||
fill="#002B76"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="360" height="195.76" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFound;
|
||||
@@ -1,25 +1,8 @@
|
||||
@import "~antd/dist/antd.dark.css";
|
||||
@import "~antd/dist/antd.compact.css";
|
||||
|
||||
.ant-space-item {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
/* #components-layout-demo-side .logo {
|
||||
height: 32px;
|
||||
margin: 16px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.site-layout .site-layout-background {
|
||||
background: #fff;
|
||||
} */
|
||||
.instrument-card{
|
||||
border-radius: 4px;
|
||||
background: #313131;
|
||||
padding: 33px 23px;
|
||||
max-width: 800px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
#chart svg{
|
||||
width: 100%;
|
||||
|
||||
25
frontend/src/components/NotFound/index.tsx
Normal file
25
frontend/src/components/NotFound/index.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
|
||||
import { Button, Text, TextContainer, Container } from "./styles";
|
||||
|
||||
import NotFoundImage from "Src/assets/NotFound";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
const NotFound = (): JSX.Element => {
|
||||
return (
|
||||
<Container>
|
||||
<NotFoundImage />
|
||||
|
||||
<TextContainer>
|
||||
<Text>Ah, seems like we reached a dead end!</Text>
|
||||
<Text>Page Not Found</Text>
|
||||
</TextContainer>
|
||||
|
||||
<Button to={ROUTES.APPLICATION} tabIndex={0}>
|
||||
Return To Metrics Page
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFound;
|
||||
61
frontend/src/components/NotFound/styles.ts
Normal file
61
frontend/src/components/NotFound/styles.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import styled from "styled-components";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export const Button = styled(Link)`
|
||||
height: 100%;
|
||||
border: 2px solid #2f80ed;
|
||||
box-sizing: border-box;
|
||||
border-radius: 10px;
|
||||
width: 400px;
|
||||
|
||||
background: inherit;
|
||||
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
line-height: 20px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 14px;
|
||||
padding-bottom: 14px;
|
||||
|
||||
color: #2f80ed;
|
||||
`;
|
||||
|
||||
export const Container = styled.div`
|
||||
min-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const Text = styled.p`
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-size: 18px;
|
||||
line-height: 20px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
color: #828282;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const TextContainer = styled.div`
|
||||
min-height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
margin-bottom: 30px;
|
||||
margin-top: 20px;
|
||||
`;
|
||||
42
frontend/src/components/Spiner.tsx
Normal file
42
frontend/src/components/Spiner.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import { Spin } from 'antd';
|
||||
import styled from "styled-components";
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
|
||||
|
||||
const SpinerStyle = styled.div`
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
height: 4em;
|
||||
// width: 4em;
|
||||
overflow: visible;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
`;
|
||||
|
||||
export const CustomSpinner = ({
|
||||
size,
|
||||
tip,
|
||||
}:{
|
||||
size:string,
|
||||
tip:string,
|
||||
})=>{
|
||||
return(
|
||||
<>
|
||||
<SpinerStyle>
|
||||
<Spin size={size} tip={tip} indicator={antIcon}/>
|
||||
</SpinerStyle>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const DefaultSpinner = ()=>{
|
||||
return(
|
||||
<>
|
||||
<Spin indicator={antIcon}/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
export const ENVIRONMENT = {
|
||||
baseURL: "",
|
||||
baseURL: process?.env?.FRONTEND_API_ENDPOINT || "",
|
||||
};
|
||||
|
||||
@@ -5,4 +5,5 @@ export enum METRICS_PAGE_QUERY_PARAM {
|
||||
service = "service",
|
||||
error = "error",
|
||||
operation = "operation",
|
||||
kind = "kind"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { Suspense } from "react";
|
||||
import { Spin } from "antd";
|
||||
import { useThemeSwitcher } from "react-css-theme-switcher";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
import { IS_LOGGED_IN } from "Src/constants/auth";
|
||||
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
|
||||
import { CustomSpinner } from "./../components/Spiner";
|
||||
|
||||
import BaseLayout from "./BaseLayout";
|
||||
import {
|
||||
@@ -15,22 +15,24 @@ import {
|
||||
ServicesTable,
|
||||
Signup,
|
||||
SettingsPage,
|
||||
IntstrumentationPage,
|
||||
InstrumentationPage,
|
||||
} from "Src/pages";
|
||||
import { RouteProvider } from "./RouteProvider";
|
||||
import NotFound from "Src/components/NotFound";
|
||||
|
||||
const App = () => {
|
||||
const { status } = useThemeSwitcher();
|
||||
|
||||
if (status === "loading") {
|
||||
return null;
|
||||
return <CustomSpinner size="large" tip="Loading..." />;
|
||||
}
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Suspense fallback={<Spin size="large" />}>
|
||||
<Route path={"/"}>
|
||||
<Switch>
|
||||
<BaseLayout>
|
||||
<RouteProvider>
|
||||
<BaseLayout>
|
||||
<Suspense fallback={<CustomSpinner size="large" tip="Loading..." />}>
|
||||
<Switch>
|
||||
<Route path={ROUTES.SIGN_UP} exact component={Signup} />
|
||||
<Route path={ROUTES.APPLICATION} exact component={ServicesTable} />
|
||||
<Route path={ROUTES.SERVICE_METRICS} exact component={ServiceMetrics} />
|
||||
@@ -41,13 +43,9 @@ const App = () => {
|
||||
<Route
|
||||
path={ROUTES.INSTRUMENTATION}
|
||||
exact
|
||||
component={IntstrumentationPage}
|
||||
/>
|
||||
<Route
|
||||
path={ROUTES.USAGE_EXPLORER}
|
||||
exactexact
|
||||
component={UsageExplorer}
|
||||
component={InstrumentationPage}
|
||||
/>
|
||||
<Route path={ROUTES.USAGE_EXPLORER} exact component={UsageExplorer} />
|
||||
<Route
|
||||
path="/"
|
||||
exact
|
||||
@@ -59,10 +57,12 @@ const App = () => {
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</BaseLayout>
|
||||
</Switch>
|
||||
</Route>
|
||||
</Suspense>
|
||||
|
||||
<Route path="*" exact component={NotFound} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</BaseLayout>
|
||||
</RouteProvider>
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import React, { ReactNode, useEffect } from "react";
|
||||
|
||||
import { Layout } from "antd";
|
||||
import SideNav from "./Nav/SideNav";
|
||||
import TopNav from "./Nav/TopNav";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useRoute } from "./RouteProvider";
|
||||
|
||||
const { Content, Footer } = Layout;
|
||||
|
||||
interface BaseLayoutProps {
|
||||
@@ -10,6 +13,13 @@ interface BaseLayoutProps {
|
||||
}
|
||||
|
||||
const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => {
|
||||
const location = useLocation();
|
||||
const { dispatch } = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: "ROUTE_IS_LOADED", payload: location.pathname });
|
||||
}, [location]);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: "100vh" }}>
|
||||
<SideNav />
|
||||
@@ -19,7 +29,7 @@ const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => {
|
||||
{children}
|
||||
</Content>
|
||||
<Footer style={{ textAlign: "center", fontSize: 10 }}>
|
||||
SigNoz Inc. ©2020{" "}
|
||||
SigNoz Inc. ©2020
|
||||
</Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { RouteComponentProps } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
import { metricItem } from "../../store/actions/metrics";
|
||||
import { metricItem } from "../../store/actions/MetricsActions";
|
||||
|
||||
const ChartPopUpUnique = styled.div<{
|
||||
ycoordinate: number;
|
||||
@@ -55,7 +55,7 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
|
||||
xcoordinate: 0,
|
||||
ycoordinate: 0,
|
||||
showpopUp: false,
|
||||
firstpoint_ts: 0
|
||||
firstpoint_ts: 0,
|
||||
// graphInfo:{}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
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 { getOptions, borderColors } from "./graphConfig";
|
||||
import { externalMetricsItem } from "../../store/actions/metrics";
|
||||
import { externalMetricsItem } from "../../../store/actions/MetricsActions";
|
||||
import { uniqBy, filter } from "lodash";
|
||||
|
||||
const theme = "dark";
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Bar, Line as ChartJSLine } from "react-chartjs-2";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { customMetricsItem } from "../../store/actions/metrics";
|
||||
import { customMetricsItem } from "../../store/actions/MetricsActions";
|
||||
|
||||
const GenVisualizationWrapper = styled.div`
|
||||
height: 160px;
|
||||
|
||||
@@ -4,9 +4,7 @@ import { ChartOptions } from "chart.js";
|
||||
import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
import { metricItem } from "../../store/actions/metrics";
|
||||
import { metricItem } from "../../store/actions/MetricsActions";
|
||||
|
||||
const ChartPopUpUnique = styled.div<{
|
||||
ycoordinate: number;
|
||||
@@ -39,11 +37,8 @@ interface LatencyLineChartProps extends RouteComponentProps<any> {
|
||||
popupClickHandler: Function;
|
||||
}
|
||||
|
||||
interface LatencyLineChart {
|
||||
chartRef: any;
|
||||
}
|
||||
|
||||
class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
private chartRef: React.RefObject<HTMLElement>;
|
||||
constructor(props: LatencyLineChartProps) {
|
||||
super(props);
|
||||
this.chartRef = React.createRef();
|
||||
@@ -54,7 +49,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
ycoordinate: 0,
|
||||
showpopUp: false,
|
||||
firstpoint_ts: 0,
|
||||
// graphInfo:{}
|
||||
};
|
||||
|
||||
onClickhandler = async (e: any, event: any) => {
|
||||
@@ -69,7 +63,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
ycoordinate: e.offsetY,
|
||||
showpopUp: true,
|
||||
firstpoint_ts: this.props.data[firstPoint._index].timestamp,
|
||||
// graphInfo:{...event}
|
||||
});
|
||||
} else {
|
||||
// if clicked outside of the graph line, then firstpoint is undefined -> close popup.
|
||||
@@ -80,15 +73,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
}
|
||||
};
|
||||
|
||||
gotoTracesHandler = (xc: any) => {
|
||||
this.props.history.push(ROUTES.TRACES);
|
||||
};
|
||||
|
||||
gotoAlertsHandler = () => {
|
||||
this.props.history.push(ROUTES.SERVICE_MAP);
|
||||
// PNOTE - Keeping service map for now, will replace with alerts when alert page is made
|
||||
};
|
||||
|
||||
options_charts: ChartOptions = {
|
||||
onClick: this.onClickhandler,
|
||||
|
||||
@@ -161,9 +145,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
xAxes: [
|
||||
{
|
||||
type: "time",
|
||||
// time: {
|
||||
// unit: 'second'
|
||||
// },
|
||||
distribution: "linear",
|
||||
//'linear': data are spread according to their time (distances can vary)
|
||||
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
|
||||
@@ -193,7 +174,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
|
||||
>
|
||||
View Traces
|
||||
</PopUpElements>
|
||||
{/* <PopUpElements onClick={this.gotoAlertsHandler}>Set Alerts</PopUpElements> */}
|
||||
</ChartPopUpUnique>
|
||||
);
|
||||
} else return null;
|
||||
@@ -239,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}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { withRouter } from "react-router";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { metricItem } from "../../store/actions/metrics";
|
||||
import { metricItem } from "../../store/actions/MetricsActions";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
const ChartPopUpUnique = styled.div<{
|
||||
|
||||
@@ -4,23 +4,24 @@ import { connect } from "react-redux";
|
||||
import { useParams, RouteComponentProps } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
import { GlobalTime, updateTimeInterval } from "Src/store/actions";
|
||||
import {
|
||||
getServicesMetrics,
|
||||
metricItem,
|
||||
getTopEndpoints,
|
||||
getDbOverViewMetrics,
|
||||
getExternalMetrics,
|
||||
externalMetricsAvgDurationItem,
|
||||
externalErrCodeMetricsItem,
|
||||
externalMetricsItem,
|
||||
dbOverviewMetricsItem,
|
||||
topEndpointListItem,
|
||||
} from "../../store/actions/MetricsActions";
|
||||
import {
|
||||
getServicesMetrics,
|
||||
getTopEndpoints,
|
||||
getDbOverViewMetrics,
|
||||
getExternalMetrics,
|
||||
getExternalAvgDurationMetrics,
|
||||
getExternalErrCodeMetrics,
|
||||
topEndpointListItem,
|
||||
GlobalTime,
|
||||
updateTimeInterval,
|
||||
} from "Src/store/actions";
|
||||
} from "../../store/actions/MetricsActions";
|
||||
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import LatencyLineChart from "./LatencyLineChart";
|
||||
import RequestRateChart from "./RequestRateChart";
|
||||
@@ -92,7 +93,7 @@ const _ServiceMetrics = (props: ServicesMetricsProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Tabs defaultActiveKey="1">
|
||||
<Tabs defaultActiveKey="1" tabBarGutter={48}>
|
||||
<TabPane tab="Application Metrics" key="1">
|
||||
<Row gutter={32} style={{ margin: 20 }}>
|
||||
<Col span={12}>
|
||||
@@ -223,13 +224,13 @@ const mapStateToProps = (
|
||||
globalTime: GlobalTime;
|
||||
} => {
|
||||
return {
|
||||
externalErrCodeMetrics: state.externalErrCodeMetrics,
|
||||
serviceMetrics: state.serviceMetrics,
|
||||
topEndpointsList: state.topEndpointsList,
|
||||
externalMetrics: state.externalMetrics,
|
||||
externalErrCodeMetrics: state.metricsData.externalErrCodeMetricsItem,
|
||||
serviceMetrics: state.metricsData.metricItems,
|
||||
topEndpointsList: state.metricsData.topEndpointListItem,
|
||||
externalMetrics: state.metricsData.externalMetricsItem,
|
||||
globalTime: state.globalTime,
|
||||
dbOverviewMetrics: state.dbOverviewMetrics,
|
||||
externalAvgDurationMetrics: state.externalAvgDurationMetrics,
|
||||
dbOverviewMetrics: state.metricsData.dbOverviewMetricsItem,
|
||||
externalAvgDurationMetrics: state.metricsData.externalMetricsAvgDurationItem,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { Button, Space, Spin, Table } from "antd";
|
||||
import { Button, Space, Table } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { connect } from "react-redux";
|
||||
import { SKIP_ONBOARDING } from "Src/constants/onboarding";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
import {
|
||||
getServicesList,
|
||||
GlobalTime,
|
||||
servicesListItem,
|
||||
} from "../../store/actions";
|
||||
import { getServicesList, GlobalTime } from "../../store/actions";
|
||||
import { servicesListItem } from "../../store/actions/MetricsActions";
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import { CustomModal } from "../../components/Modal";
|
||||
import { CustomSpinner,DefaultSpinner } from "../../components/Spiner";
|
||||
|
||||
interface ServicesTableProps {
|
||||
servicesList: servicesListItem[];
|
||||
@@ -75,7 +71,7 @@ const columns = [
|
||||
key: "errorRate",
|
||||
sorter: (a: any, b: any) => a.errorRate - b.errorRate,
|
||||
// sortDirections: ['descend', 'ascend'],
|
||||
render: (value: number) => (value).toFixed(2),
|
||||
render: (value: number) => value.toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "Requests Per Second",
|
||||
@@ -88,8 +84,6 @@ const columns = [
|
||||
];
|
||||
|
||||
const _ServicesTable = (props: ServicesTableProps) => {
|
||||
const search = useLocation().search;
|
||||
const time_interval = new URLSearchParams(search).get("time");
|
||||
const [initialDataFetch, setDataFetched] = useState(false);
|
||||
const [errorObject, setErrorObject] = useState({
|
||||
message: "",
|
||||
@@ -131,10 +125,7 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
|
||||
if (!initialDataFetch) {
|
||||
return (
|
||||
<TableLoadingWrapper>
|
||||
<Spin />
|
||||
<LoadingText>Fetching data</LoadingText>
|
||||
</TableLoadingWrapper>
|
||||
<CustomSpinner size="large" tip="Fetching data..."/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -161,7 +152,7 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
<div style={{ margin: "20px 0" }}>
|
||||
<Spin />
|
||||
<DefaultSpinner/>
|
||||
</div>
|
||||
<div>
|
||||
No instrumentation data.
|
||||
@@ -210,7 +201,10 @@ const _ServicesTable = (props: ServicesTableProps) => {
|
||||
const mapStateToProps = (
|
||||
state: StoreState,
|
||||
): { servicesList: servicesListItem[]; globalTime: GlobalTime } => {
|
||||
return { servicesList: state.servicesList, globalTime: state.globalTime };
|
||||
return {
|
||||
servicesList: state.metricsData.serviceList,
|
||||
globalTime: state.globalTime,
|
||||
};
|
||||
};
|
||||
|
||||
export const ServicesTable = connect(mapStateToProps, {
|
||||
|
||||
12
frontend/src/modules/Metrics/TopEndpointsTable.css
Normal file
12
frontend/src/modules/Metrics/TopEndpointsTable.css
Normal file
@@ -0,0 +1,12 @@
|
||||
@media only screen and (min-width: 768px) {
|
||||
.topEndpointsButton {
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.topEndpointsButton span {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
import React from "react";
|
||||
import { Table, Button } from "antd";
|
||||
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/metrics";
|
||||
import { topEndpointListItem } from "../../store/actions/MetricsActions";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "Src/constants/query";
|
||||
import { GlobalTime } from "Src/store/actions";
|
||||
import { StoreState } from "Src/store/reducers";
|
||||
import "./TopEndpointsTable.css";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
@media only screen and (max-width: 767px) {
|
||||
padding: 0;
|
||||
}
|
||||
.ant-table table {
|
||||
font-size: 12px;
|
||||
}
|
||||
@@ -22,6 +26,9 @@ const Wrapper = styled.div`
|
||||
.ant-table-thead > tr > th {
|
||||
padding: 10px;
|
||||
}
|
||||
.ant-table-column-sorters {
|
||||
padding: 6px;
|
||||
}
|
||||
`;
|
||||
|
||||
interface TopEndpointsTableProps {
|
||||
@@ -58,9 +65,15 @@ const _TopEndpointsTable = (props: TopEndpointsTableProps) => {
|
||||
key: "name",
|
||||
|
||||
render: (text: string) => (
|
||||
<Button type="link" onClick={() => handleOnClick(text)}>
|
||||
{text}
|
||||
</Button>
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
<Button
|
||||
className="topEndpointsButton"
|
||||
type="link"
|
||||
onClick={() => handleOnClick(text)}
|
||||
>
|
||||
{text}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -72,10 +85,10 @@ const _TopEndpointsTable = (props: TopEndpointsTableProps) => {
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: "P90 (in ms)",
|
||||
dataIndex: "p90",
|
||||
key: "p90",
|
||||
sorter: (a: any, b: any) => a.p90 - b.p90,
|
||||
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),
|
||||
},
|
||||
|
||||
83
frontend/src/modules/RouteProvider.tsx
Normal file
83
frontend/src/modules/RouteProvider.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React, { useContext, createContext, ReactNode, Dispatch } from "react";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
type State = {
|
||||
[key: string]: {
|
||||
route: string;
|
||||
isLoaded: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
enum ActionTypes {
|
||||
UPDATE_IS_LOADED = "ROUTE_IS_LOADED",
|
||||
}
|
||||
|
||||
type Action = {
|
||||
type: ActionTypes;
|
||||
payload: string;
|
||||
};
|
||||
|
||||
interface ContextType {
|
||||
state: State;
|
||||
dispatch: Dispatch<Action>;
|
||||
}
|
||||
|
||||
const RouteContext = createContext<ContextType | null>(null);
|
||||
|
||||
interface RouteProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
interface RouteObj {
|
||||
[key: string]: {
|
||||
route: string;
|
||||
isLoaded: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
const updateLocation = (state: State, action: Action): State => {
|
||||
if (action.type === ActionTypes.UPDATE_IS_LOADED) {
|
||||
/*
|
||||
Update the isLoaded property in routes obj
|
||||
if the route matches the current pathname
|
||||
|
||||
Why: Checkout this issue https://github.com/SigNoz/signoz/issues/110
|
||||
To avoid calling the api's twice for Date picker,
|
||||
We will only call once the route is changed
|
||||
*/
|
||||
Object.keys(ROUTES).map((items) => {
|
||||
state[items].isLoaded = state[items].route === action.payload;
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
};
|
||||
|
||||
const getInitialState = () => {
|
||||
const routes: RouteObj = {};
|
||||
Object.keys(ROUTES).map((items) => {
|
||||
routes[items] = {
|
||||
route: `${ROUTES[items]}`,
|
||||
isLoaded: false,
|
||||
};
|
||||
});
|
||||
return routes;
|
||||
};
|
||||
|
||||
const RouteProvider: React.FC<RouteProviderProps> = ({ children }) => {
|
||||
const [state, dispatch] = React.useReducer(updateLocation, getInitialState());
|
||||
const value = { state, dispatch };
|
||||
return <RouteContext.Provider value={value}>{children}</RouteContext.Provider>;
|
||||
};
|
||||
|
||||
const useRoute = (): ContextType => {
|
||||
const context = useContext(RouteContext);
|
||||
if (context === undefined) {
|
||||
throw new Error("useRoute must be used within a RouteProvider");
|
||||
}
|
||||
return context as ContextType;
|
||||
};
|
||||
export { RouteProvider, useRoute };
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import {
|
||||
@@ -7,13 +7,14 @@ import {
|
||||
getServiceMapItems,
|
||||
getDetailedServiceMapItems,
|
||||
} from "Src/store/actions";
|
||||
import { Spin } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { StoreState } from "../../store/reducers";
|
||||
|
||||
import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils";
|
||||
import SelectService from "./SelectService";
|
||||
import { ForceGraph2D } from "react-force-graph";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
import { CustomSpinner } from "../../components/Spiner";
|
||||
|
||||
const Container = styled.div`
|
||||
.force-graph-container .graph-tooltip {
|
||||
@@ -53,6 +54,8 @@ export interface graphDataType {
|
||||
|
||||
const ServiceMap = (props: ServiceMapProps) => {
|
||||
const fgRef = useRef();
|
||||
const { state } = useRoute();
|
||||
|
||||
const {
|
||||
getDetailedServiceMapItems,
|
||||
getServiceMapItems,
|
||||
@@ -61,15 +64,21 @@ const ServiceMap = (props: ServiceMapProps) => {
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
getServiceMapItems(globalTime);
|
||||
getDetailedServiceMapItems(globalTime);
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.SERVICE_MAP.isLoaded) {
|
||||
getServiceMapItems(globalTime);
|
||||
getDetailedServiceMapItems(globalTime);
|
||||
}
|
||||
}, [globalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
fgRef.current && fgRef.current.d3Force("charge").strength(-400);
|
||||
});
|
||||
if (!serviceMap.items.length || !serviceMap.services.length) {
|
||||
return <Spin />;
|
||||
return <CustomSpinner size="large" tip="Loading..."/>;
|
||||
}
|
||||
|
||||
const zoomToService = (value: string) => {
|
||||
|
||||
@@ -83,6 +83,7 @@ export const getZoomPx = (): number => {
|
||||
} else if (width > 1700) {
|
||||
return 470;
|
||||
}
|
||||
return 190;
|
||||
};
|
||||
|
||||
export const getTooltip = (node: {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
const Test = () => {
|
||||
return <div>INSIDE PUBLIC CODE</div>;
|
||||
};
|
||||
|
||||
export default Test;
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { Modal, Form, InputNumber, Col, Row } from "antd";
|
||||
import { Store } from "antd/lib/form/interface";
|
||||
import { NamePath, Store } from "antd/lib/form/interface";
|
||||
|
||||
interface LatencyModalFormProps {
|
||||
onCreate: (values: Store) => void; //Store is defined in antd forms library
|
||||
@@ -13,13 +13,32 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
onCancel,
|
||||
latencyFilterValues,
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
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 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
|
||||
@@ -31,7 +50,7 @@ const LatencyModalForm: React.FC<LatencyModalFormProps> = ({
|
||||
.catch((info) => {
|
||||
console.log("Validate Failed:", info);
|
||||
});
|
||||
}}
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
@@ -44,14 +63,19 @@ 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!' }]}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="max" label="Max (in ms)">
|
||||
<Form.Item
|
||||
name="max"
|
||||
label="Max (in ms)"
|
||||
rules = {[validateMaxValue]}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
@@ -1,48 +1,101 @@
|
||||
import React from "react";
|
||||
import { Card, Tabs } from "antd";
|
||||
import { Card, Space, Tabs, Typography } from "antd";
|
||||
import styled from "styled-components";
|
||||
import { pushDStree } from "Src/store/actions";
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
interface spanTagItem {
|
||||
key: string;
|
||||
type: string;
|
||||
value: string;
|
||||
}
|
||||
const { Text, Title, Paragraph } = Typography;
|
||||
|
||||
interface SelectedSpanDetailsProps {
|
||||
clickedSpanTags: spanTagItem[];
|
||||
data: pushDStree;
|
||||
}
|
||||
|
||||
// Check this discussion for antd with styled components
|
||||
// https://gist.github.com/newswim/fa916c66477ddd5952f7d6548e6a0605
|
||||
|
||||
const CustomTitle = styled(Title)`
|
||||
&&& {
|
||||
color: #f2f2f2;
|
||||
font-size: 14px;
|
||||
}
|
||||
`;
|
||||
|
||||
const CustomText = styled(Text)`
|
||||
&&& {
|
||||
color: #2d9cdb;
|
||||
font-size: 14px;
|
||||
}
|
||||
`;
|
||||
|
||||
const CustomSubTitle = styled(Title)`
|
||||
&&& {
|
||||
color: #bdbdbd;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const CustomSubText = styled(Paragraph)`
|
||||
&&& {
|
||||
background: #4f4f4f;
|
||||
color: #2d9cdb;
|
||||
font-size: 12px;
|
||||
padding: 6px 8px;
|
||||
word-break: break-all;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const SelectedSpanDetails = (props: SelectedSpanDetailsProps) => {
|
||||
const callback = (key: any) => {};
|
||||
const spanTags = props.data?.tags;
|
||||
const service = props.data?.name?.split(":")[0];
|
||||
const operation = props.data?.name?.split(":")[1];
|
||||
|
||||
return (
|
||||
<Card style={{ height: 320 }}>
|
||||
<Tabs defaultActiveKey="1" onChange={callback}>
|
||||
<Card
|
||||
style={{ border: "none", background: "transparent", padding: 0 }}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
<strong> Details for selected Span </strong>
|
||||
<Space direction="vertical" size={2}>
|
||||
<CustomTitle style={{ marginTop: "18px" }}>Service</CustomTitle>
|
||||
<CustomText>{service}</CustomText>
|
||||
</Space>
|
||||
<Space direction="vertical" size={2}>
|
||||
<CustomTitle>Operation</CustomTitle>
|
||||
<CustomText>{operation}</CustomText>
|
||||
</Space>
|
||||
</Space>
|
||||
<Tabs defaultActiveKey="1">
|
||||
<TabPane tab="Tags" key="1">
|
||||
<strong> Details for selected Span </strong>
|
||||
{props.clickedSpanTags.map((tags, index) => (
|
||||
<li
|
||||
key={index}
|
||||
style={{ color: "grey", fontSize: "13px", listStyle: "none" }}
|
||||
>
|
||||
<span className="mr-1">{tags.key}</span>:
|
||||
<span className="ml-1">
|
||||
{tags.key === "error" ? "true" : tags.value}
|
||||
</span>
|
||||
</li>
|
||||
))}{" "}
|
||||
{spanTags &&
|
||||
spanTags.map((tags, index) => {
|
||||
return (
|
||||
<>
|
||||
{tags.value && (
|
||||
<>
|
||||
<CustomSubTitle>{tags.key}</CustomSubTitle>
|
||||
<CustomSubText>
|
||||
{tags.key === "error" ? "true" : tags.value}
|
||||
</CustomSubText>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</TabPane>
|
||||
<TabPane tab="Errors" key="2">
|
||||
{props.clickedSpanTags
|
||||
.filter((tags) => tags.key === "error")
|
||||
.map((error) => (
|
||||
<div className="ml-5">
|
||||
<p style={{ color: "grey", fontSize: "10px" }}>
|
||||
<span className="mr-1">{error.key}</span>:
|
||||
<span className="ml-1">true</span>
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
{spanTags &&
|
||||
spanTags
|
||||
.filter((tags) => tags.key === "error")
|
||||
.map((error) => (
|
||||
<>
|
||||
<CustomSubTitle>{error.key}</CustomSubTitle>
|
||||
<CustomSubText>true</CustomSubText>
|
||||
</>
|
||||
))}
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</Card>
|
||||
|
||||
@@ -2,15 +2,11 @@ import React, { useState, useEffect } from "react";
|
||||
import GenericVisualizations from "../Metrics/GenericVisualization";
|
||||
import { Select, Card, Space, Form } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import {
|
||||
customMetricsItem,
|
||||
getFilteredTraceMetrics,
|
||||
GlobalTime,
|
||||
TraceFilters,
|
||||
} from "../../store/actions";
|
||||
|
||||
import { GlobalTime, TraceFilters } from "../../store/actions";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
import { getFilteredTraceMetrics } from "../../store/actions/MetricsActions";
|
||||
import { customMetricsItem } from "../../store/actions/MetricsActions";
|
||||
const { Option } = Select;
|
||||
|
||||
const entity = [
|
||||
@@ -48,10 +44,10 @@ const aggregation_options = [
|
||||
{
|
||||
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:'p90', dataindex:'p90'}, {title:'p95', dataindex:'p95'}]
|
||||
// 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: "p90", dataindex: "p90" },
|
||||
{ title: "p95", dataindex: "p95" },
|
||||
{ title: "p99", dataindex: "p99" },
|
||||
],
|
||||
},
|
||||
@@ -80,7 +76,10 @@ interface TraceCustomVisualizationsProps {
|
||||
const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
const [selectedEntity, setSelectedEntity] = useState("calls");
|
||||
const [selectedAggOption, setSelectedAggOption] = useState("count");
|
||||
const [selectedStep, setSelectedStep] = useState("60");
|
||||
const { state } = useRoute();
|
||||
const [form] = Form.useForm();
|
||||
const selectedStep = "60";
|
||||
|
||||
// Step should be multiples of 60, 60 -> 1 min
|
||||
|
||||
useEffect(() => {
|
||||
@@ -92,7 +91,9 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
"&maxDuration=" +
|
||||
props.traceFilters.latency?.max +
|
||||
"&minDuration=" +
|
||||
props.traceFilters.latency?.min;
|
||||
props.traceFilters.latency?.min +
|
||||
"&kind=" +
|
||||
props.traceFilters.kind;
|
||||
if (props.traceFilters.tags)
|
||||
request_string =
|
||||
request_string +
|
||||
@@ -109,21 +110,18 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
minTime: props.globalTime.minTime - 15 * 60 * 1000000000,
|
||||
maxTime: props.globalTime.maxTime + 15 * 60 * 1000000000,
|
||||
};
|
||||
props.getFilteredTraceMetrics(request_string, plusMinus15);
|
||||
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.TRACES.isLoaded) {
|
||||
props.getFilteredTraceMetrics(request_string, plusMinus15);
|
||||
}
|
||||
}, [selectedEntity, selectedAggOption, props.traceFilters, props.globalTime]);
|
||||
|
||||
//Custom metrics API called if time, tracefilters, selected entity or agg option changes
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
function handleChange(value: string) {
|
||||
// console.log(value);
|
||||
}
|
||||
|
||||
function handleFinish(value: string) {
|
||||
// console.log(value);
|
||||
}
|
||||
|
||||
// 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];
|
||||
@@ -152,11 +150,9 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
|
||||
return (
|
||||
<Card>
|
||||
{/* <Space direction="vertical"> */}
|
||||
<div>Custom Visualizations</div>
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={handleFinish}
|
||||
onValuesChange={handleFormValuesChange}
|
||||
initialValues={{
|
||||
agg_options: "Count",
|
||||
@@ -189,7 +185,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="chart_style">
|
||||
<Select style={{ width: 120 }} onChange={handleChange} allowClear>
|
||||
<Select style={{ width: 120 }} allowClear>
|
||||
<Option value="line">Line Chart</Option>
|
||||
<Option value="bar">Bar Chart</Option>
|
||||
<Option value="area">Area Chart</Option>
|
||||
@@ -197,7 +193,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="interval">
|
||||
<Select style={{ width: 120 }} onChange={handleChange} allowClear>
|
||||
<Select style={{ width: 120 }} allowClear>
|
||||
<Option value="1m">1 min</Option>
|
||||
<Option value="5m">5 min</Option>
|
||||
<Option value="30m">30 min</Option>
|
||||
@@ -206,7 +202,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
|
||||
|
||||
{/* Need heading for each option */}
|
||||
<Form.Item name="group_by">
|
||||
<Select style={{ width: 120 }} onChange={handleChange} allowClear>
|
||||
<Select style={{ width: 120 }} allowClear>
|
||||
<Option value="none">Group By</Option>
|
||||
<Option value="status">Status Code</Option>
|
||||
<Option value="protocol">Protocol</Option>
|
||||
@@ -229,7 +225,7 @@ const mapStateToProps = (
|
||||
traceFilters: TraceFilters;
|
||||
} => {
|
||||
return {
|
||||
filteredTraceMetrics: state.filteredTraceMetrics,
|
||||
filteredTraceMetrics: state.metricsData.customMetricsItem,
|
||||
globalTime: state.globalTime,
|
||||
traceFilters: state.traceFilters,
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import FormItem from "antd/lib/form/FormItem";
|
||||
import api, { apiV1 } from "../../api";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { METRICS_PAGE_QUERY_PARAM } from "Src/constants/query";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@@ -39,12 +40,29 @@ interface TagKeyOptionItem {
|
||||
tagCount: number;
|
||||
}
|
||||
|
||||
interface ISpanKind {
|
||||
label: "SERVER" | "CLIENT";
|
||||
value: string;
|
||||
}
|
||||
|
||||
const _TraceFilter = (props: TraceFilterProps) => {
|
||||
const [serviceList, setServiceList] = useState<string[]>([]);
|
||||
const [operationList, setOperationsList] = useState<string[]>([]);
|
||||
const [tagKeyOptions, setTagKeyOptions] = useState<TagKeyOptionItem[]>([]);
|
||||
const location = useLocation();
|
||||
const urlParams = new URLSearchParams(location.search.split("?")[1]);
|
||||
const { state } = useRoute();
|
||||
|
||||
const spanKindList: ISpanKind[] = [
|
||||
{
|
||||
label: "SERVER",
|
||||
value: "2"
|
||||
},
|
||||
{
|
||||
label: "CLIENT",
|
||||
value: "3"
|
||||
}
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
handleApplyFilterForm({
|
||||
@@ -52,6 +70,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
tags: [],
|
||||
operation: "",
|
||||
latency: { min: "", max: "" },
|
||||
kind: ""
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -74,6 +93,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
...props.traceFilters,
|
||||
operation: operationName,
|
||||
service: serviceName,
|
||||
kind: ""
|
||||
});
|
||||
populateData(serviceName);
|
||||
} else if (serviceName && errorTag) {
|
||||
@@ -87,6 +107,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
operator: "equals",
|
||||
},
|
||||
],
|
||||
kind: ""
|
||||
});
|
||||
} else {
|
||||
if (operationName) {
|
||||
@@ -115,14 +136,22 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
"&maxDuration=" +
|
||||
props.traceFilters.latency?.max +
|
||||
"&minDuration=" +
|
||||
props.traceFilters.latency?.min;
|
||||
props.traceFilters.latency?.min +
|
||||
"&kind=" +
|
||||
props.traceFilters.kind;
|
||||
if (props.traceFilters.tags)
|
||||
request_string =
|
||||
request_string +
|
||||
"&tags=" +
|
||||
encodeURIComponent(JSON.stringify(props.traceFilters.tags));
|
||||
|
||||
props.fetchTraces(props.globalTime, request_string);
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.TRACES.isLoaded) {
|
||||
props.fetchTraces(props.globalTime, request_string);
|
||||
}
|
||||
}, [props.traceFilters, props.globalTime]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -165,6 +194,10 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
form_basefilter.setFieldsValue({ operation: props.traceFilters.operation });
|
||||
}, [props.traceFilters.operation]);
|
||||
|
||||
useEffect(() => {
|
||||
form_basefilter.setFieldsValue({ kind: props.traceFilters.kind });
|
||||
}, [props.traceFilters.kind]);
|
||||
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [loading] = useState(false);
|
||||
|
||||
@@ -249,6 +282,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
operator: values.operator,
|
||||
},
|
||||
],
|
||||
kind: props.traceFilters.kind
|
||||
});
|
||||
} else {
|
||||
props.updateTraceFilters({
|
||||
@@ -262,6 +296,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
operator: values.operator,
|
||||
},
|
||||
],
|
||||
kind: props.traceFilters.kind
|
||||
});
|
||||
}
|
||||
|
||||
@@ -326,6 +361,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
max: "",
|
||||
min: "",
|
||||
},
|
||||
kind: values.kind
|
||||
});
|
||||
};
|
||||
|
||||
@@ -336,10 +372,15 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
operation: "",
|
||||
tags: [],
|
||||
latency: { min: "", max: "" },
|
||||
kind: ""
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleChangeSpanKind = (value:string = '') => {
|
||||
props.updateTraceFilters({ ...props.traceFilters, kind: value });
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>Filter Traces</div>
|
||||
@@ -388,6 +429,20 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem name="spanKind">
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: 180 }}
|
||||
onChange={handleChangeSpanKind}
|
||||
placeholder="Select Span Kind"
|
||||
allowClear
|
||||
>
|
||||
{spanKindList.map(spanKind => (
|
||||
<Option value={spanKind.value} key={spanKind.value}>{spanKind.label}</Option>
|
||||
))}
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
{/* <FormItem>
|
||||
<Button type="primary" htmlType="submit">Apply Filters</Button>
|
||||
</FormItem> */}
|
||||
@@ -426,6 +481,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
|
||||
<Select style={{ width: 120, textAlign: "center" }}>
|
||||
<Option value="equals">EQUAL</Option>
|
||||
<Option value="contains">CONTAINS</Option>
|
||||
<Option value="regex">REGEX</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
.row-styles {
|
||||
cursor: pointer;
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
.ant-tabs-nav-list {
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.ant-table-body table {
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
341
frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx
Normal file
341
frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx
Normal file
@@ -0,0 +1,341 @@
|
||||
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 "Src/store/actions";
|
||||
import traverseTreeData from "Src/modules/Traces/TraceGanttChart/TraceGanttChartHelpers";
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
color: #f2f2f2;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
`;
|
||||
|
||||
interface TraceGanttChartProps {
|
||||
treeData: pushDStree[];
|
||||
clickedSpan: pushDStree;
|
||||
selectedSpan: pushDStree;
|
||||
resetZoom: () => {};
|
||||
setSpanTagsInfo: (p: { data: any }) => {};
|
||||
}
|
||||
|
||||
const TraceGanttChart = ({
|
||||
treeData,
|
||||
clickedSpan,
|
||||
selectedSpan,
|
||||
resetZoom,
|
||||
setSpanTagsInfo,
|
||||
}: TraceGanttChartProps) => {
|
||||
let checkStrictly = true;
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const [clickedSpanData, setClickedSpanData] = useState(clickedSpan);
|
||||
const [defaultExpandedRows, setDefaultExpandedRows] = useState([]);
|
||||
const [sortedTreeData, setSortedTreeData] = useState(treeData);
|
||||
const [isReset, setIsReset] = useState(false);
|
||||
const [tabsContainerWidth, setTabsContainerWidth] = useState(0);
|
||||
const tableRef = useRef("");
|
||||
let tabsContainer = document.querySelector("#collapsable .ant-tabs-nav-list");
|
||||
|
||||
let tabs = document.querySelectorAll("#collapsable .ant-tabs-tab");
|
||||
|
||||
const { id } = treeData || "id";
|
||||
let maxGlobal = 0;
|
||||
let minGlobal = 0;
|
||||
let medianGlobal = 0;
|
||||
let endTimeArray: [] = [];
|
||||
|
||||
useEffect(() => {
|
||||
if (id !== "empty") {
|
||||
setSortedTreeData(treeData);
|
||||
if (clickedSpan) {
|
||||
setClickedSpanData(clickedSpan);
|
||||
}
|
||||
setTabsContainerWidth(tabsContainer?.offsetWidth);
|
||||
}
|
||||
handleScroll(selectedSpan?.id);
|
||||
}, [sortedTreeData, treeData, clickedSpan]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!isEmpty(clickedSpanData) &&
|
||||
clickedSpan &&
|
||||
!selectedRows.includes(clickedSpan.id) &&
|
||||
!isReset
|
||||
) {
|
||||
setSelectedRows([clickedSpan.id]);
|
||||
getParentKeys(clickedSpan);
|
||||
handleFocusOnSelectedPath("", [clickedSpan.id], clickedSpan);
|
||||
}
|
||||
}, [clickedSpan, selectedRows, isReset, clickedSpanData]);
|
||||
|
||||
let parentKeys = [];
|
||||
let childrenKeys = [];
|
||||
const getParentKeys = (obj) => {
|
||||
if (has(obj, "parent")) {
|
||||
parentKeys.push(obj.parent.id);
|
||||
getParentKeys(obj.parent);
|
||||
}
|
||||
};
|
||||
|
||||
const getChildrenKeys = (obj) => {
|
||||
if (has(obj, "children")) {
|
||||
childrenKeys.push(obj.id);
|
||||
if (!isEmpty(obj.children)) {
|
||||
obj.children.map((item) => {
|
||||
getChildrenKeys(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEmpty(selectedSpan) && isEmpty(clickedSpan)) {
|
||||
getParentKeys(selectedSpan);
|
||||
let keys = [selectedSpan?.id, ...parentKeys];
|
||||
setDefaultExpandedRows(keys);
|
||||
setSelectedRows([selectedSpan.id, clickedSpan]);
|
||||
// setSpanTagsInfo({data: selectedSpan})
|
||||
} else {
|
||||
setSelectedRows([treeData?.[0]?.id]);
|
||||
setDefaultExpandedRows([treeData?.[0]?.id]);
|
||||
// /.setSpanTagsInfo({data: treeData?.[0]})
|
||||
}
|
||||
}, [selectedSpan, treeData]);
|
||||
|
||||
const getMaxEndTime = (treeData) => {
|
||||
if (treeData.length > 0) {
|
||||
if (treeData?.id !== "empty") {
|
||||
return Array.from(treeData).map((item, key) => {
|
||||
if (!isEmpty(item.children)) {
|
||||
endTimeArray.push(item.time / 1000000 + item.startTime);
|
||||
getMaxEndTime(item.children);
|
||||
} else {
|
||||
endTimeArray.push(item.time / 1000000 + item.startTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (id !== "empty") {
|
||||
getMaxEndTime(treeData);
|
||||
maxGlobal = max(endTimeArray);
|
||||
minGlobal = treeData?.[0]?.startTime;
|
||||
medianGlobal = (minGlobal + maxGlobal) / 2;
|
||||
}
|
||||
|
||||
/*
|
||||
timeDiff = maxGlobal - startTime
|
||||
totalTime = maxGlobal - minGlobal
|
||||
totalWidth = width of container
|
||||
*/
|
||||
const getPaddingLeft = (timeDiff, totalTime, totalWidth) => {
|
||||
return ((timeDiff / totalTime) * totalWidth).toFixed(0);
|
||||
};
|
||||
|
||||
let tabMinVal = 0;
|
||||
let tabMedianVal = (medianGlobal - minGlobal).toFixed(0);
|
||||
let tabMaxVal = (maxGlobal - minGlobal).toFixed(0);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
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" />
|
||||
</Tabs>
|
||||
),
|
||||
dataIndex: "trace",
|
||||
name: "trace",
|
||||
render: (_, record: pushDStree) => {
|
||||
let widths = [];
|
||||
let length;
|
||||
|
||||
if (widths.length < tabs.length) {
|
||||
Array.from(tabs).map((tab) => {
|
||||
widths.push(tab.offsetWidth);
|
||||
});
|
||||
}
|
||||
|
||||
let paddingLeft = 0;
|
||||
let startTime = parseFloat(record.startTime);
|
||||
let duration = parseFloat((record.time / 1000000).toFixed(2));
|
||||
paddingLeft = parseInt(
|
||||
getPaddingLeft(
|
||||
startTime - minGlobal,
|
||||
maxGlobal - minGlobal,
|
||||
tabsContainerWidth,
|
||||
),
|
||||
);
|
||||
let textPadding = paddingLeft;
|
||||
if (paddingLeft === tabsContainerWidth - 20) {
|
||||
textPadding = tabsContainerWidth - 40;
|
||||
}
|
||||
length = ((duration / (maxGlobal - startTime)) * 100).toFixed(2);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ paddingLeft: textPadding + "px" }}>{duration}ms</div>
|
||||
<Progress
|
||||
percent={length}
|
||||
showInfo={false}
|
||||
style={{ paddingLeft: paddingLeft + "px" }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const handleFocusOnSelectedPath = (event, selectedRowsList = selectedRows) => {
|
||||
if (!isEmpty(selectedRowsList)) {
|
||||
let node = {};
|
||||
traverseTreeData(treeData, (item: pushDStree) => {
|
||||
if (item.id === selectedRowsList[0]) {
|
||||
node = item;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
setSpanTagsInfo({ data: node });
|
||||
} catch (e) {
|
||||
// TODO: error logging.
|
||||
console.error("Node not found in Tree Data.");
|
||||
}
|
||||
|
||||
getParentKeys(node);
|
||||
getChildrenKeys(node);
|
||||
|
||||
let rows = document.querySelectorAll("#collapsable table tbody tr");
|
||||
Array.from(rows).map((row) => {
|
||||
let attribKey = row.getAttribute("data-row-key");
|
||||
if (!selectedRowsList.includes(attribKey)) {
|
||||
row.classList.add("hide");
|
||||
}
|
||||
});
|
||||
setDefaultExpandedRows([...parentKeys, ...childrenKeys]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleResetFocus = () => {
|
||||
const rows = document.querySelectorAll("#collapsable table tbody tr");
|
||||
Array.from(rows).map((row) => {
|
||||
row.classList.remove("hide");
|
||||
});
|
||||
|
||||
resetZoom(true);
|
||||
};
|
||||
|
||||
const handleScroll = (id: string): void => {
|
||||
if (!isEmpty(id)) {
|
||||
const selectedRow = document.querySelectorAll<HTMLElement>(
|
||||
`[data-row-key='${id}']`,
|
||||
);
|
||||
selectedRow?.[0]?.scrollIntoView();
|
||||
}
|
||||
};
|
||||
|
||||
const rowSelection = {
|
||||
onChange: (selectedRowKeys: []) => {
|
||||
setSelectedRows(selectedRowKeys);
|
||||
setClickedSpanData({});
|
||||
if (isEmpty(selectedRowKeys)) {
|
||||
setIsReset(true);
|
||||
} else {
|
||||
setIsReset(false);
|
||||
}
|
||||
},
|
||||
onSelect: (record) => {
|
||||
handleRowOnClick(record);
|
||||
},
|
||||
selectedRowKeys: selectedRows,
|
||||
};
|
||||
|
||||
const handleRowOnClick = (record) => {
|
||||
let node = {};
|
||||
traverseTreeData(treeData, (item: pushDStree) => {
|
||||
if (item.id === record.id) {
|
||||
node = item;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
setSpanTagsInfo({ data: node });
|
||||
} catch (e) {
|
||||
// TODO: error logging.
|
||||
console.error("Node not found in TreeData.");
|
||||
}
|
||||
|
||||
const selectedRowKeys = selectedRows;
|
||||
if (selectedRowKeys.indexOf(record.id) >= 0) {
|
||||
selectedRowKeys.splice(selectedRowKeys.indexOf(record.key), 1);
|
||||
} else {
|
||||
selectedRowKeys.push(record.id);
|
||||
}
|
||||
setSelectedRows([record.id]);
|
||||
};
|
||||
|
||||
const handleOnExpandedRowsChange = (item) => {
|
||||
setDefaultExpandedRows(item);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{id !== "empty" && (
|
||||
<>
|
||||
<Row
|
||||
justify="end"
|
||||
gutter={32}
|
||||
style={{
|
||||
marginBottom: "24px",
|
||||
}}
|
||||
>
|
||||
<Col>
|
||||
<StyledButton onClick={handleFocusOnSelectedPath}>
|
||||
{" "}
|
||||
Focus on selected path{" "}
|
||||
</StyledButton>
|
||||
</Col>
|
||||
<Col>
|
||||
<StyledButton onClick={handleResetFocus}> Reset Focus </StyledButton>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Table
|
||||
refs={tableRef}
|
||||
hideSelectAll={true}
|
||||
columns={columns}
|
||||
rowSelection={{ ...rowSelection, checkStrictly, type: "radio" }}
|
||||
dataSource={sortedTreeData}
|
||||
rowKey="id"
|
||||
sticky={true}
|
||||
onRow={(record, rowIndex) => {
|
||||
return {
|
||||
onClick: () => handleRowOnClick(record, rowIndex), // click row
|
||||
};
|
||||
}}
|
||||
expandedRowKeys={defaultExpandedRows}
|
||||
onExpandedRowsChange={handleOnExpandedRowsChange}
|
||||
pagination={false}
|
||||
scroll={{ y: 540 }}
|
||||
rowClassName="row-styles"
|
||||
filterMultiple={false}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TraceGanttChart;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { pushDStree } from "Src/store/actions";
|
||||
|
||||
interface itemProps {
|
||||
treeData: pushDStree[];
|
||||
marked: boolean;
|
||||
}
|
||||
|
||||
// Doing DFS traversal on the tree.
|
||||
// Callback to be called for each element in the tree once.
|
||||
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];
|
||||
|
||||
while (!isEmpty(stk)) {
|
||||
let x = stk[stk.length - 1];
|
||||
|
||||
// marked means seeing the node for the second time.
|
||||
if (x.marked) {
|
||||
x.marked = false;
|
||||
stk.pop();
|
||||
x.treeData.map((item: pushDStree) => {
|
||||
callback(item);
|
||||
});
|
||||
} else {
|
||||
x.marked = true;
|
||||
x.treeData.map((item) => {
|
||||
if (item.children.length > 0) {
|
||||
stk.push({ treeData: item.children, marked: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default traverseTreeData;
|
||||
1
frontend/src/modules/Traces/TraceGanttChart/index.js
Normal file
1
frontend/src/modules/Traces/TraceGanttChart/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from "./TraceGanttChart";
|
||||
@@ -36,10 +36,16 @@
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
/* Prevent text vertical shift on hover */
|
||||
.d3-flame-graph-label {
|
||||
border: 1px dotted transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Transparency simulates sub pixel border https://stackoverflow.com/questions/13891177/css-border-less-than-1px */
|
||||
|
||||
.d3-flame-graph-label:hover {
|
||||
border: 1px dotted;
|
||||
border-color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
/*
|
||||
@@ -47,3 +53,7 @@
|
||||
border: 1px solid;
|
||||
border-color: rgba(255, 255, 255, 0.75);
|
||||
} */
|
||||
|
||||
.fade:not(.show) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@@ -1,30 +1,65 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useParams, useLocation } from "react-router-dom";
|
||||
import { flamegraph } from "d3-flame-graph";
|
||||
import { connect } from "react-redux";
|
||||
import { Card, Button, Row, Col, Space } from "antd";
|
||||
import { Card, Row, Col, Space, Affix } from "antd";
|
||||
import * as d3 from "d3";
|
||||
import * as d3Tip from "d3-tip";
|
||||
|
||||
//import * as d3Tip from 'd3-tip';
|
||||
// PNOTE - uninstall @types/d3-tip. issues with importing d3-tip https://github.com/Caged/d3-tip/issues/181
|
||||
|
||||
import "./TraceGraph.css";
|
||||
import { spanToTreeUtil } from "../../utils/spanToTree";
|
||||
import { fetchTraceItem, spansWSameTraceIDResponse } from "../../store/actions";
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import { TraceGraphColumn } from "./TraceGraphColumn";
|
||||
import { spanToTreeUtil } from "Src/utils/spanToTree";
|
||||
import {
|
||||
fetchTraceItem,
|
||||
pushDStree,
|
||||
spansWSameTraceIDResponse,
|
||||
} from "../../store/actions";
|
||||
import { StoreState } from "Src/store/reducers";
|
||||
import SelectedSpanDetails from "./SelectedSpanDetails";
|
||||
import TraceGanttChart from "./TraceGanttChart";
|
||||
import styled from "styled-components";
|
||||
import { isEmpty, sortBy } from "lodash-es";
|
||||
|
||||
interface TraceGraphProps {
|
||||
traceItem: spansWSameTraceIDResponse;
|
||||
fetchTraceItem: Function;
|
||||
}
|
||||
|
||||
const TraceGanttChartContainer = styled(Card)`
|
||||
background: #333333;
|
||||
border-radius: 5px;
|
||||
`;
|
||||
|
||||
const _TraceGraph = (props: TraceGraphProps) => {
|
||||
let location = useLocation();
|
||||
const spanId = location?.state?.spanId;
|
||||
const params = useParams<{ id?: string }>();
|
||||
const [clickedSpanTags, setClickedSpanTags] = useState([]);
|
||||
const [clickedSpanTags, setClickedSpanTags] = useState<pushDStree>([]);
|
||||
const [selectedSpan, setSelectedSpan] = useState({});
|
||||
const [clickedSpan, setClickedSpan] = useState(null);
|
||||
const [resetZoom, setResetZoom] = useState(false);
|
||||
const [sortedTreeData, setSortedTreeData] = useState<pushDStree[]>([]);
|
||||
|
||||
let sortedData = {};
|
||||
|
||||
const getSortedData = (treeData: pushDStree[], parent = {}) => {
|
||||
if (!isEmpty(treeData)) {
|
||||
if (treeData[0].id !== "empty") {
|
||||
return Array.from(treeData).map((item, key) => {
|
||||
if (!isEmpty(item.children)) {
|
||||
getSortedData(item.children, item);
|
||||
sortedData = sortBy(item.children, (i) => i.startTime);
|
||||
treeData[key].children = sortedData;
|
||||
}
|
||||
if (!isEmpty(parent)) {
|
||||
treeData[key].parent = parent;
|
||||
}
|
||||
return treeData;
|
||||
});
|
||||
}
|
||||
return treeData;
|
||||
}
|
||||
};
|
||||
|
||||
const tree = spanToTreeUtil(props.traceItem[0].events);
|
||||
|
||||
useEffect(() => {
|
||||
//sets span width based on value - which is mapped to duration
|
||||
@@ -32,16 +67,31 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.traceItem || resetZoom) {
|
||||
const tree = spanToTreeUtil(props.traceItem[0].events);
|
||||
if (props.traceItem) {
|
||||
let 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").datum(tree).call(chart);
|
||||
setResetZoom(false);
|
||||
d3.select("#chart").datum(tree).call(chart).sort(item=>item.startTime);
|
||||
}
|
||||
}, [props.traceItem, resetZoom]);
|
||||
}, [props.traceItem]);
|
||||
// if this monitoring of props.traceItem.data is removed then zoom on click doesn't work
|
||||
// Doesn't work if only do initial check, works if monitor an element - as it may get updated in sometime
|
||||
|
||||
useEffect(() => {
|
||||
if(!isEmpty(sortedTreeData) && sortedTreeData?.id !== "empty" && isEmpty(clickedSpanTags)) {
|
||||
setClickedSpanTags(sortedTreeData?.[0]);
|
||||
}
|
||||
}, [sortedTreeData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (resetZoom) {
|
||||
// This is causing element to change ref. Can use both useRef or this approach.
|
||||
d3.select("#chart").datum(tree).call(chart).sort(item=>item.startTime);
|
||||
setResetZoom(false);
|
||||
}
|
||||
}, [resetZoom]);
|
||||
|
||||
const tip = d3Tip
|
||||
.default()
|
||||
.attr("class", "d3-tip")
|
||||
@@ -50,34 +100,59 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
});
|
||||
|
||||
const onClick = (z: any) => {
|
||||
setClickedSpanTags(z.data.tags);
|
||||
setClickedSpanTags(z.data);
|
||||
setClickedSpan(z.data);
|
||||
setSelectedSpan([]);
|
||||
console.log(`Clicked on ${z.data.name}, id: "${z.id}"`);
|
||||
};
|
||||
|
||||
const setSpanTagsInfo = (z: any) => {
|
||||
setClickedSpanTags(z.data);
|
||||
};
|
||||
|
||||
const getSpanInfo = (data: [pushDStree], spanId: string): void => {
|
||||
if (resetZoom) {
|
||||
setSelectedSpan({});
|
||||
return;
|
||||
}
|
||||
if (data?.[0]?.id !== "empty") {
|
||||
Array.from(data).map((item) => {
|
||||
if (item.id === spanId) {
|
||||
setSelectedSpan(item);
|
||||
setClickedSpanTags(item);
|
||||
return item;
|
||||
} else if (!isEmpty(item.children)) {
|
||||
getSpanInfo(item.children, spanId);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const chart = flamegraph()
|
||||
.cellHeight(18)
|
||||
.transitionDuration(500)
|
||||
.inverted(true)
|
||||
.tooltip(tip)
|
||||
.minFrameSize(10)
|
||||
.minFrameSize(4)
|
||||
.elided(false)
|
||||
.differential(false)
|
||||
.sort(true)
|
||||
.sort((item) => item.startTime)
|
||||
//Use self value=true when we're using not using aggregated option, Which is not our case.
|
||||
// In that case it's doing step function sort of stuff thru computation.
|
||||
// Source flamegraph.js line 557 and 573.
|
||||
// .selfValue(true)
|
||||
.onClick(onClick);
|
||||
.onClick(onClick)
|
||||
.width(800);
|
||||
|
||||
const handleResetZoom = (value) => {
|
||||
setResetZoom(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
{/*<Col md={8} sm={24}>*/}
|
||||
{/* <TraceGraphColumn />*/}
|
||||
{/*</Col>*/}
|
||||
<Col md={24} sm={24}>
|
||||
{/* <Card style={{ width: 640 }}> */}
|
||||
<Col md={18} sm={18}>
|
||||
<Space direction="vertical" size="middle" style={{ width: "100%" }}>
|
||||
<Card bodyStyle={{ padding: 80 }} style={{ height: 320 }}>
|
||||
<Card bodyStyle={{ padding: 24 }} style={{ height: 320 }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@@ -89,20 +164,27 @@ const _TraceGraph = (props: TraceGraphProps) => {
|
||||
<div style={{ textAlign: "center" }}>
|
||||
Trace Graph component ID is {params.id}{" "}
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={setResetZoom.bind(this, true)}
|
||||
style={{ width: 160 }}
|
||||
>
|
||||
Reset Zoom
|
||||
</Button>
|
||||
<div id="chart" style={{ fontSize: 12, marginTop: 20 }}></div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<SelectedSpanDetails clickedSpanTags={clickedSpanTags} />
|
||||
<Affix offsetTop={24}>
|
||||
<TraceGanttChartContainer id={"collapsable"}>
|
||||
<TraceGanttChart
|
||||
treeData={sortedTreeData}
|
||||
clickedSpan={clickedSpan}
|
||||
selectedSpan={selectedSpan}
|
||||
resetZoom={handleResetZoom}
|
||||
setSpanTagsInfo={setSpanTagsInfo}
|
||||
/>
|
||||
</TraceGanttChartContainer>
|
||||
</Affix>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col md={6} sm={6}>
|
||||
<Affix offsetTop={24}>
|
||||
<SelectedSpanDetails data={clickedSpanTags} />
|
||||
</Affix>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { useHistory} from "react-router-dom";
|
||||
import { Space, Table } from "antd";
|
||||
import ROUTES from "Src/constants/routes";
|
||||
|
||||
@@ -10,9 +10,14 @@ import { isOnboardingSkipped } from "../../utils/app";
|
||||
import moment from "moment";
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledTable = styled(Table)`
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
const TraceHeader = styled.div`
|
||||
margin: 16px 0;
|
||||
`;
|
||||
|
||||
interface TraceListProps {
|
||||
traces: traceResponseNew;
|
||||
fetchTraces: Function;
|
||||
@@ -25,26 +30,17 @@ interface TableDataSourceItem {
|
||||
operationName: string;
|
||||
startTime: number;
|
||||
duration: number;
|
||||
service: string;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
useEffect(() => {
|
||||
props.fetchTraces();
|
||||
}, []);
|
||||
|
||||
// PNOTE - code snippet -
|
||||
// renderList(): JSX.Element[] {
|
||||
// return this.props.todos.map((todo: Todo) => {
|
||||
// return (
|
||||
// <div onClick={() => this.onTodoClick(todo.id)} key={todo.id}>
|
||||
// {todo.title}
|
||||
// </div>
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: "Start Time",
|
||||
@@ -57,12 +53,9 @@ const _TraceList = (props: TraceListProps) => {
|
||||
// new Date() assumes input in milliseconds. Start Time stamp returned by druid api for span list is in ms
|
||||
},
|
||||
{
|
||||
title: "Duration (in ms)",
|
||||
dataIndex: "duration",
|
||||
key: "duration",
|
||||
sorter: (a: any, b: any) => a.duration - b.duration,
|
||||
sortDirections: ["descend", "ascend"],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
title: "Service",
|
||||
dataIndex: "service",
|
||||
key: "service",
|
||||
},
|
||||
{
|
||||
title: "Operation",
|
||||
@@ -70,13 +63,12 @@ const _TraceList = (props: TraceListProps) => {
|
||||
key: "operationName",
|
||||
},
|
||||
{
|
||||
title: "TraceID",
|
||||
dataIndex: "traceid",
|
||||
key: "traceid",
|
||||
render: (text: string) => (
|
||||
<NavLink to={ROUTES.TRACES + "/" + text}>{text.slice(-16)}</NavLink>
|
||||
),
|
||||
//only last 16 chars have traceID, druid makes it 32 by adding zeros
|
||||
title: "Duration (in ms)",
|
||||
dataIndex: "duration",
|
||||
key: "duration",
|
||||
sorter: (a: any, b: any) => a.duration - b.duration,
|
||||
sortDirections: ["descend", "ascend"],
|
||||
render: (value: number) => (value / 1000000).toFixed(2),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -87,8 +79,6 @@ const _TraceList = (props: TraceListProps) => {
|
||||
typeof props.traces[0] !== "undefined" &&
|
||||
props.traces[0].events.length > 0
|
||||
) {
|
||||
//PNOTE - Template literal should be wrapped in curly braces for it to be evaluated
|
||||
|
||||
props.traces[0].events.map(
|
||||
(item: (number | string | string[] | pushDStree[])[], index) => {
|
||||
if (
|
||||
@@ -96,7 +86,8 @@ const _TraceList = (props: TraceListProps) => {
|
||||
typeof item[4] === "string" &&
|
||||
typeof item[6] === "string" &&
|
||||
typeof item[1] === "string" &&
|
||||
typeof item[2] === "string"
|
||||
typeof item[2] === "string" &&
|
||||
typeof item[3] === "string"
|
||||
)
|
||||
dataSource.push({
|
||||
startTime: item[0],
|
||||
@@ -105,13 +96,30 @@ const _TraceList = (props: TraceListProps) => {
|
||||
spanid: item[1],
|
||||
traceid: item[2],
|
||||
key: index.toString(),
|
||||
service: item[3],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
//antd table in typescript - https://codesandbox.io/s/react-typescript-669cv
|
||||
|
||||
return <Table dataSource={dataSource} columns={columns} size="middle" />;
|
||||
return <StyledTable
|
||||
dataSource={dataSource}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
rowClassName=""
|
||||
onRow={(record) => ({
|
||||
onClick: () => {
|
||||
history.push({
|
||||
pathname: ROUTES.TRACES + "/" + record.traceid,
|
||||
state: {
|
||||
spanId: record.spanid,
|
||||
},
|
||||
});
|
||||
}
|
||||
})}
|
||||
/>
|
||||
;
|
||||
} else {
|
||||
if (isOnboardingSkipped()) {
|
||||
return (
|
||||
@@ -136,7 +144,7 @@ const _TraceList = (props: TraceListProps) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TraceHeader>List of traces with spanID</TraceHeader>
|
||||
<TraceHeader>List of filtered spans</TraceHeader>
|
||||
<div>{renderTraces()}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Bar } from "react-chartjs-2";
|
||||
import { Card, Form, Select, Space } from "antd";
|
||||
import { Card, Select, Space } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import {
|
||||
getServicesList,
|
||||
getUsageData,
|
||||
GlobalTime,
|
||||
servicesListItem,
|
||||
usageDataItem,
|
||||
} from "../../store/actions";
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import moment from "moment";
|
||||
import { isOnboardingSkipped } from "../../utils/app";
|
||||
import { useRoute } from "../RouteProvider";
|
||||
import { servicesListItem } from "../../store/actions/MetricsActions";
|
||||
const { Option } = Select;
|
||||
|
||||
interface UsageExplorerProps {
|
||||
@@ -48,7 +49,6 @@ const interval = [
|
||||
label: "Hours",
|
||||
applicableOn: [timeDaysOptions[2], timeDaysOptions[1]],
|
||||
},
|
||||
,
|
||||
];
|
||||
|
||||
const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
@@ -56,6 +56,8 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
const [selectedInterval, setSelectedInterval] = useState(interval[2]);
|
||||
const [selectedService, setSelectedService] = useState<string>("");
|
||||
|
||||
const { state } = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTime && selectedInterval) {
|
||||
const maxTime = new Date().getTime() * 1000000;
|
||||
@@ -71,7 +73,13 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
|
||||
}, [selectedTime, selectedInterval, selectedService]);
|
||||
|
||||
useEffect(() => {
|
||||
props.getServicesList(props.globalTime);
|
||||
/*
|
||||
Call the apis only when the route is loaded.
|
||||
Check this issue: https://github.com/SigNoz/signoz/issues/110
|
||||
*/
|
||||
if (state.USAGE_EXPLORER.isLoaded) {
|
||||
props.getServicesList(props.globalTime);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const data = {
|
||||
@@ -203,7 +211,7 @@ const mapStateToProps = (
|
||||
totalCount: totalCount,
|
||||
usageData: state.usageDate,
|
||||
globalTime: state.globalTime,
|
||||
servicesList: state.servicesList,
|
||||
servicesList: state.metricsData.serviceList,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,43 +1,42 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Form, Input, Space } from "antd";
|
||||
import React from "react";
|
||||
import { Space } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { Tooltip } from "antd";
|
||||
import {
|
||||
InfoCircleOutlined,
|
||||
EyeTwoTone,
|
||||
EyeInvisibleOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { StoreState } from "../../store/reducers";
|
||||
import { useThemeSwitcher } from "react-css-theme-switcher";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { Alert } from "antd";
|
||||
const InstrumentCard = styled.div<{
|
||||
currentThemeStatus: string | undefined;
|
||||
}>`
|
||||
border-radius: 4px;
|
||||
background: ${({ currentThemeStatus }) => currentThemeStatus === 'dark' ? '#313131' : '#ddd'};
|
||||
padding: 33px 23px;
|
||||
max-width: 800px;
|
||||
margin-top: 40px;
|
||||
`;
|
||||
|
||||
interface InstrumentationPageProps {}
|
||||
|
||||
|
||||
const InstrumentationPage = (props: InstrumentationPageProps) => {
|
||||
|
||||
const { currentTheme } = useThemeSwitcher();
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
|
||||
|
||||
<Space style={{ marginLeft: 60, marginTop: 48, display: 'block' }}>
|
||||
<div>
|
||||
<h2>
|
||||
Instrument your application
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className={"instrument-card"}>
|
||||
<InstrumentCard currentThemeStatus={currentTheme}>
|
||||
Congrats, you have successfully installed SigNoz!<br/>
|
||||
To start seeing YOUR application data here, follow the instructions in the docs -
|
||||
<a href={"https://signoz.io/docs/instrumentation/overview"} target="_blank"> https://signoz.io/docs/instrumentation/overview</a>
|
||||
<br/>
|
||||
If you face any issues, join our <a href={"https://signoz-community.slack.com/join/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA"} target="_blank">
|
||||
slack community</a> to ask any questions or mail us at <a href={"mailto:support@signoz.io"} target="_blank">
|
||||
support@signoz.io
|
||||
</a>
|
||||
</div>
|
||||
support@signoz.io</a>
|
||||
</InstrumentCard>
|
||||
</Space>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -23,6 +23,6 @@ export const SettingsPage = React.lazy(
|
||||
() => import("Src/modules/Settings/settingsPage"),
|
||||
);
|
||||
|
||||
export const IntstrumentationPage = React.lazy(
|
||||
export const InstrumentationPage = React.lazy(
|
||||
() => import("Src/modules/add-instrumentation/instrumentationPage"),
|
||||
);
|
||||
|
||||
3
frontend/src/store/actions/MetricsActions/index.ts
Normal file
3
frontend/src/store/actions/MetricsActions/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./metricsInterfaces";
|
||||
export * from "./metricsActionTypes";
|
||||
export * from "./metricsActions";
|
||||
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
externalErrCodeMetricsActions,
|
||||
externalMetricsAvgDurationAction,
|
||||
getDbOverViewMetricsAction,
|
||||
getExternalMetricsAction,
|
||||
getFilteredTraceMetricsAction,
|
||||
getServiceMetricsAction,
|
||||
getServicesListAction,
|
||||
getTopEndpointsAction,
|
||||
} 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",
|
||||
}
|
||||
|
||||
export type MetricsActions =
|
||||
| getServicesListAction
|
||||
| getServiceMetricsAction
|
||||
| getTopEndpointsAction
|
||||
| getFilteredTraceMetricsAction
|
||||
| getExternalMetricsAction
|
||||
| externalErrCodeMetricsActions
|
||||
| getDbOverViewMetricsAction
|
||||
| externalMetricsAvgDurationAction;
|
||||
190
frontend/src/store/actions/MetricsActions/metricsActions.ts
Normal file
190
frontend/src/store/actions/MetricsActions/metricsActions.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
import { Dispatch } from "redux";
|
||||
import api, { apiV1 } from "../../../api";
|
||||
|
||||
import { GlobalTime } from "../global";
|
||||
import { toUTCEpoch } from "../../../utils/timeUtils";
|
||||
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 response = await api.get<MetricsInterfaces.servicesListItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
|
||||
dispatch<MetricsInterfaces.getServicesListAction>({
|
||||
type: MetricsActionTypes.getServicesList,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getDbOverViewMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/dbOverview?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<MetricsInterfaces.dbOverviewMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
dispatch<MetricsInterfaces.getDbOverViewMetricsAction>({
|
||||
type: MetricsActionTypes.getDbOverviewMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getExternalMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/external?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<MetricsInterfaces.externalMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
dispatch<MetricsInterfaces.getExternalMetricsAction>({
|
||||
type: MetricsActionTypes.getExternalMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getExternalAvgDurationMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/externalAvgDuration?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
|
||||
const response = await api.get<
|
||||
MetricsInterfaces.externalMetricsAvgDurationItem[]
|
||||
>(apiV1 + request_string);
|
||||
dispatch<MetricsInterfaces.externalMetricsAvgDurationAction>({
|
||||
type: MetricsActionTypes.getAvgDurationMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
export const getExternalErrCodeMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/externalErrors?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<
|
||||
MetricsInterfaces.externalErrCodeMetricsItem[]
|
||||
>(apiV1 + request_string);
|
||||
|
||||
dispatch<MetricsInterfaces.externalErrCodeMetricsActions>({
|
||||
type: MetricsActionTypes.getErrCodeMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getServicesMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/overview?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<MetricsInterfaces.metricItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
|
||||
dispatch<MetricsInterfaces.getServiceMetricsAction>({
|
||||
type: MetricsActionTypes.getServiceMetrics,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getTopEndpoints = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/top_endpoints?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime;
|
||||
const response = await api.get<MetricsInterfaces.topEndpointListItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
|
||||
dispatch<MetricsInterfaces.getTopEndpointsAction>({
|
||||
type: MetricsActionTypes.getTopEndpoints,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getFilteredTraceMetrics = (
|
||||
filter_params: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/spans/aggregates?start=" +
|
||||
toUTCEpoch(globalTime.minTime) +
|
||||
"&end=" +
|
||||
toUTCEpoch(globalTime.maxTime) +
|
||||
"&" +
|
||||
filter_params;
|
||||
const response = await api.get<MetricsInterfaces.customMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
|
||||
dispatch<MetricsInterfaces.getFilteredTraceMetricsAction>({
|
||||
type: MetricsActionTypes.getFilteredTraceMetrics,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
import { MetricsActionTypes } from "./metricsActionTypes";
|
||||
|
||||
export interface servicesListItem {
|
||||
serviceName: string;
|
||||
p99: number;
|
||||
avgDuration: number;
|
||||
numCalls: number;
|
||||
callRate: number;
|
||||
numErrors: number;
|
||||
errorRate: number;
|
||||
}
|
||||
|
||||
export interface metricItem {
|
||||
timestamp: number;
|
||||
p50: number;
|
||||
p95: number;
|
||||
p99: number;
|
||||
numCalls: number;
|
||||
callRate: number;
|
||||
numErrors: number;
|
||||
errorRate: number;
|
||||
}
|
||||
|
||||
export interface externalMetricsAvgDurationItem {
|
||||
avgDuration: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface externalErrCodeMetricsItem {
|
||||
externalHttpUrl: string;
|
||||
numCalls: number;
|
||||
timestamp: number;
|
||||
callRate: number;
|
||||
}
|
||||
export interface topEndpointListItem {
|
||||
p50: number;
|
||||
p95: number;
|
||||
p99: number;
|
||||
numCalls: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface externalMetricsItem {
|
||||
avgDuration: number;
|
||||
callRate: number;
|
||||
externalHttpUrl: string;
|
||||
numCalls: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface dbOverviewMetricsItem {
|
||||
avgDuration: number;
|
||||
callRate: number;
|
||||
dbSystem: string;
|
||||
numCalls: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface customMetricsItem {
|
||||
timestamp: number;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface getServicesListAction {
|
||||
type: MetricsActionTypes.getServicesList;
|
||||
payload: servicesListItem[];
|
||||
}
|
||||
|
||||
export interface externalErrCodeMetricsActions {
|
||||
type: MetricsActionTypes.getErrCodeMetrics;
|
||||
payload: externalErrCodeMetricsItem[];
|
||||
}
|
||||
export interface externalMetricsAvgDurationAction {
|
||||
type: MetricsActionTypes.getAvgDurationMetrics;
|
||||
payload: externalMetricsAvgDurationItem[];
|
||||
}
|
||||
export interface getServiceMetricsAction {
|
||||
type: MetricsActionTypes.getServiceMetrics;
|
||||
payload: metricItem[];
|
||||
}
|
||||
export interface getExternalMetricsAction {
|
||||
type: MetricsActionTypes.getExternalMetrics;
|
||||
payload: externalMetricsItem[];
|
||||
}
|
||||
|
||||
export interface getDbOverViewMetricsAction {
|
||||
type: MetricsActionTypes.getDbOverviewMetrics;
|
||||
payload: dbOverviewMetricsItem[];
|
||||
}
|
||||
export interface getTopEndpointsAction {
|
||||
type: MetricsActionTypes.getTopEndpoints;
|
||||
payload: topEndpointListItem[];
|
||||
}
|
||||
|
||||
export interface getFilteredTraceMetricsAction {
|
||||
type: MetricsActionTypes.getFilteredTraceMetrics;
|
||||
payload: customMetricsItem[];
|
||||
}
|
||||
@@ -2,6 +2,6 @@ export * from "./types";
|
||||
export * from "./traceFilters";
|
||||
export * from "./serviceMap";
|
||||
export * from "./traces";
|
||||
export * from "./metrics";
|
||||
export * from "./MetricsActions";
|
||||
export * from "./usage";
|
||||
export * from "./global";
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
import { Dispatch } from "redux";
|
||||
import api, { apiV1 } from "../../api";
|
||||
|
||||
import { GlobalTime } from "./global";
|
||||
import { ActionTypes } from "./types";
|
||||
import { Token } from "../../utils/token";
|
||||
import { toUTCEpoch } from "../../utils/timeUtils";
|
||||
|
||||
export interface servicesListItem {
|
||||
serviceName: string;
|
||||
p99: number;
|
||||
avgDuration: number;
|
||||
numCalls: number;
|
||||
callRate: number;
|
||||
numErrors: number;
|
||||
errorRate: number;
|
||||
}
|
||||
|
||||
export interface metricItem {
|
||||
timestamp: number;
|
||||
p50: number;
|
||||
p95: number;
|
||||
p99: number;
|
||||
numCalls: number;
|
||||
callRate: number;
|
||||
numErrors: number;
|
||||
errorRate: number;
|
||||
}
|
||||
|
||||
export interface externalMetricsAvgDurationItem {
|
||||
avgDuration: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface externalErrCodeMetricsItem {
|
||||
errorRate: number;
|
||||
externalHttpUrl: string;
|
||||
numErrors: number;
|
||||
timestamp: number;
|
||||
}
|
||||
export interface topEndpointListItem {
|
||||
p50: number;
|
||||
p90: number;
|
||||
p99: number;
|
||||
numCalls: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface externalMetricsItem {
|
||||
avgDuration: number;
|
||||
callRate: number;
|
||||
externalHttpUrl: string;
|
||||
numCalls: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface dbOverviewMetricsItem {
|
||||
avgDuration: number;
|
||||
callRate: number;
|
||||
dbSystem: string;
|
||||
numCalls: number;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface customMetricsItem {
|
||||
timestamp: number;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface getServicesListAction {
|
||||
type: ActionTypes.getServicesList;
|
||||
payload: servicesListItem[];
|
||||
}
|
||||
|
||||
export interface externalErrCodeMetricsActions {
|
||||
type: ActionTypes.getErrCodeMetrics;
|
||||
payload: externalErrCodeMetricsItem[];
|
||||
}
|
||||
export interface externalMetricsAvgDurationAction {
|
||||
type: ActionTypes.getAvgDurationMetrics;
|
||||
payload: externalMetricsAvgDurationItem[];
|
||||
}
|
||||
export interface getServiceMetricsAction {
|
||||
type: ActionTypes.getServiceMetrics;
|
||||
payload: metricItem[];
|
||||
}
|
||||
export interface getExternalMetricsAction {
|
||||
type: ActionTypes.getExternalMetrics;
|
||||
payload: externalMetricsItem[];
|
||||
}
|
||||
|
||||
export interface getDbOverViewMetricsAction {
|
||||
type: ActionTypes.getDbOverviewMetrics;
|
||||
payload: dbOverviewMetricsItem[];
|
||||
}
|
||||
export interface getTopEndpointsAction {
|
||||
type: ActionTypes.getTopEndpoints;
|
||||
payload: topEndpointListItem[];
|
||||
}
|
||||
|
||||
export interface getFilteredTraceMetricsAction {
|
||||
type: ActionTypes.getFilteredTraceMetrics;
|
||||
payload: customMetricsItem[];
|
||||
}
|
||||
|
||||
export const getServicesList = (globalTime: GlobalTime) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime;
|
||||
|
||||
const response = await api.get<servicesListItem[]>(apiV1 + request_string);
|
||||
|
||||
dispatch<getServicesListAction>({
|
||||
type: ActionTypes.getServicesList,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getDbOverViewMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/dbOverview?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<dbOverviewMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
dispatch<getDbOverViewMetricsAction>({
|
||||
type: ActionTypes.getDbOverviewMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getExternalMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/external?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<externalMetricsItem[]>(apiV1 + request_string);
|
||||
dispatch<getExternalMetricsAction>({
|
||||
type: ActionTypes.getExternalMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getExternalAvgDurationMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/externalAvgDuration?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
|
||||
const response = await api.get<externalMetricsAvgDurationItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
dispatch<externalMetricsAvgDurationAction>({
|
||||
type: ActionTypes.getAvgDurationMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
export const getExternalErrCodeMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/externalErrors?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<externalErrCodeMetricsItem[]>(
|
||||
apiV1 + request_string,
|
||||
);
|
||||
|
||||
dispatch<externalErrCodeMetricsActions>({
|
||||
type: ActionTypes.getErrCodeMetrics,
|
||||
payload: response.data,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getServicesMetrics = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/overview?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime +
|
||||
"&step=60";
|
||||
const response = await api.get<metricItem[]>(apiV1 + request_string);
|
||||
|
||||
dispatch<getServiceMetricsAction>({
|
||||
type: ActionTypes.getServiceMetrics,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getTopEndpoints = (
|
||||
serviceName: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/service/top_endpoints?service=" +
|
||||
serviceName +
|
||||
"&start=" +
|
||||
globalTime.minTime +
|
||||
"&end=" +
|
||||
globalTime.maxTime;
|
||||
const response = await api.get<topEndpointListItem[]>(apiV1 + request_string);
|
||||
|
||||
dispatch<getTopEndpointsAction>({
|
||||
type: ActionTypes.getTopEndpoints,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const getFilteredTraceMetrics = (
|
||||
filter_params: string,
|
||||
globalTime: GlobalTime,
|
||||
) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
let request_string =
|
||||
"/spans/aggregates?start=" +
|
||||
toUTCEpoch(globalTime.minTime) +
|
||||
"&end=" +
|
||||
toUTCEpoch(globalTime.maxTime) +
|
||||
"&" +
|
||||
filter_params;
|
||||
const response = await api.get<customMetricsItem[]>(apiV1 + request_string);
|
||||
|
||||
dispatch<getFilteredTraceMetricsAction>({
|
||||
type: ActionTypes.getFilteredTraceMetrics,
|
||||
payload: response.data,
|
||||
//PNOTE - response.data in the axios response has the actual API response
|
||||
});
|
||||
};
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user