Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e03daa7207 | ||
|
|
c48f72781e |
10
.github/CODEOWNERS
vendored
10
.github/CODEOWNERS
vendored
@@ -2,12 +2,6 @@
|
||||
# Owners are automatically requested for review for PRs that changes code
|
||||
# that they own.
|
||||
* @ankitnayan
|
||||
|
||||
/frontend/ @palashgdev
|
||||
/frontend/ @palashgdev @pranshuchittora
|
||||
/deploy/ @prashant-shahi
|
||||
/sample-apps/ @prashant-shahi
|
||||
**/query-service/ @srikanthccv
|
||||
Makefile @srikanthccv
|
||||
go.* @srikanthccv
|
||||
.git* @srikanthccv
|
||||
.github @prashant-shahi
|
||||
/pkg/query-service/ @srikanthccv
|
||||
|
||||
2
.github/config.yml
vendored
2
.github/config.yml
vendored
@@ -17,7 +17,7 @@ newPRWelcomeComment: >
|
||||
# Comment to be posted to on pull requests merged by a first time user
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request!
|
||||
|
||||
|
||||

|
||||
|
||||
We here at SigNoz are proud of you! 🥳
|
||||
|
||||
6
.github/workflows/build.yaml
vendored
6
.github/workflows/build.yaml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
run: cd frontend && yarn install
|
||||
- name: Run ESLint
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Build EE query-service image
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
8
.github/workflows/codeql.yaml
vendored
8
.github/workflows/codeql.yaml
vendored
@@ -39,11 +39,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -68,4 +68,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
9
.github/workflows/commitlint.yml
vendored
9
.github/workflows/commitlint.yml
vendored
@@ -7,7 +7,12 @@ jobs:
|
||||
lint-commits:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.3.1
|
||||
with:
|
||||
# we actually need "github.event.pull_request.commits + 1" commit
|
||||
fetch-depth: 0
|
||||
- uses: wagoid/commitlint-github-action@v5
|
||||
- uses: actions/setup-node@v2.1.0
|
||||
# or just "yarn" if you depend on "@commitlint/cli" already
|
||||
- run: yarn add @commitlint/cli
|
||||
- run: yarn add @commitlint/config-conventional
|
||||
- run: yarn run commitlint --config ./node_modules/@commitlint/config-conventional/index.js --from HEAD~${{ github.event.pull_request.commits }} --to HEAD
|
||||
|
||||
@@ -12,11 +12,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Codebase
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: signoz/gh-bot
|
||||
- name: Use Node v16
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Setup Cache & Install Dependencies
|
||||
|
||||
12
.github/workflows/e2e-k3s.yaml
vendored
12
.github/workflows/e2e-k3s.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
DOCKER_TAG: pull-${{ github.event.number }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build query-service image
|
||||
env:
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
kubectl create ns sample-application
|
||||
|
||||
# apply hotrod k8s manifest file
|
||||
kubectl -n sample-application apply -f https://raw.githubusercontent.com/SigNoz/signoz/develop/sample-apps/hotrod/hotrod.yaml
|
||||
kubectl -n sample-application apply -f https://raw.githubusercontent.com/SigNoz/signoz/main/sample-apps/hotrod/hotrod.yaml
|
||||
|
||||
# wait for all deployments in sample-application namespace to be READY
|
||||
kubectl -n sample-application get deploy --output name | xargs -r -n1 -t kubectl -n sample-application rollout status --timeout=300s
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
--set frontend.service.type=LoadBalancer \
|
||||
--set queryService.image.tag=$DOCKER_TAG \
|
||||
--set frontend.image.tag=$DOCKER_TAG
|
||||
|
||||
|
||||
# get pods, services and the container images
|
||||
kubectl get pods -n platform
|
||||
kubectl get svc -n platform
|
||||
@@ -69,14 +69,12 @@ jobs:
|
||||
--restart='OnFailure' -i --rm --command -- curl -X POST -F \
|
||||
'locust_count=6' -F 'hatch_rate=2' http://locust-master:8089/swarm
|
||||
|
||||
- name: Get short commit SHA, display tunnel URL and IP Address of the worker node
|
||||
- name: Get short commit SHA and display tunnel URL
|
||||
id: get-subdomain
|
||||
run: |
|
||||
subdomain="pr-$(git rev-parse --short HEAD)"
|
||||
echo "URL for tunnelling: https://$subdomain.loca.lt"
|
||||
echo "subdomain=$subdomain" >> $GITHUB_OUTPUT
|
||||
worker_ip="$(curl -4 -s ipconfig.io/ip)"
|
||||
echo "Worker node IP address: $worker_ip"
|
||||
echo "::set-output name=subdomain::$subdomain"
|
||||
|
||||
- name: Start tunnel
|
||||
env:
|
||||
|
||||
4
.github/workflows/playwright.yaml
vendored
4
.github/workflows/playwright.yaml
vendored
@@ -9,8 +9,8 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16.x"
|
||||
- name: Install dependencies
|
||||
|
||||
5
.github/workflows/pr_verify_linked_issue.yml
vendored
5
.github/workflows/pr_verify_linked_issue.yml
vendored
@@ -5,7 +5,7 @@ name: VerifyIssue
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [edited, opened]
|
||||
types: [edited, synchronize, opened, reopened]
|
||||
check_run:
|
||||
|
||||
jobs:
|
||||
@@ -14,6 +14,7 @@ jobs:
|
||||
name: Ensure Pull Request has a linked issue.
|
||||
steps:
|
||||
- name: Verify Linked Issue
|
||||
uses: srikanthccv/verify-linked-issue-action@v0.71
|
||||
uses: hattan/verify-linked-issue-action@v1.1.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
28
.github/workflows/push.yaml
vendored
28
.github/workflows/push.yaml
vendored
@@ -14,19 +14,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- uses: benjlevesque/short-sha@v2.2
|
||||
- uses: benjlevesque/short-sha@v1.2
|
||||
id: short-sha
|
||||
- name: Get branch name
|
||||
id: branch-name
|
||||
@@ -49,19 +49,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- uses: benjlevesque/short-sha@v2.2
|
||||
- uses: benjlevesque/short-sha@v1.2
|
||||
id: short-sha
|
||||
- name: Get branch name
|
||||
id: branch-name
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
working-directory: frontend
|
||||
run: yarn install
|
||||
@@ -97,15 +97,15 @@ jobs:
|
||||
run: npm run lint
|
||||
continue-on-error: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- uses: benjlevesque/short-sha@v2.2
|
||||
- uses: benjlevesque/short-sha@v1.2
|
||||
id: short-sha
|
||||
- name: Get branch name
|
||||
id: branch-name
|
||||
|
||||
6
.github/workflows/release-drafter.yml
vendored
6
.github/workflows/release-drafter.yml
vendored
@@ -12,12 +12,6 @@ on:
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
permissions:
|
||||
# write permission is required to create a github release
|
||||
contents: write
|
||||
# write permission is required for autolabeler
|
||||
# otherwise, read permission is required at least
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# (Optional) GitHub Enterprise requires GHE_HOST variable set
|
||||
|
||||
12
.github/workflows/remove-label.yaml
vendored
12
.github/workflows/remove-label.yaml
vendored
@@ -8,15 +8,9 @@ jobs:
|
||||
remove:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Remove label ok-to-test from PR
|
||||
uses: buildsville/add-remove-label@v2.0.0
|
||||
- name: Remove label
|
||||
uses: buildsville/add-remove-label@v1
|
||||
with:
|
||||
label: ok-to-test
|
||||
type: remove
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Remove label testing-deploy from PR
|
||||
uses: buildsville/add-remove-label@v2.0.0
|
||||
with:
|
||||
label: testing-deploy
|
||||
label: ok-to-test,testing-deploy
|
||||
type: remove
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
25
.github/workflows/repo-stats.yml
vendored
Normal file
25
.github/workflows/repo-stats.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
on:
|
||||
schedule:
|
||||
# Run this once per day, towards the end of the day for keeping the most
|
||||
# recent data point most meaningful (hours are interpreted in UTC).
|
||||
- cron: "0 8 * * *"
|
||||
workflow_dispatch: # Allow for running this manually.
|
||||
|
||||
jobs:
|
||||
j1:
|
||||
name: repostats
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: run-ghrs
|
||||
uses: jgehrcke/github-repo-stats@v1.1.0
|
||||
with:
|
||||
# Define the stats repository (the repo to fetch
|
||||
# stats for and to generate the report for).
|
||||
# Remove the parameter when the stats repository
|
||||
# and the data repository are the same.
|
||||
repository: signoz/signoz
|
||||
# Set a GitHub API token that can read the stats
|
||||
# repository, and that can push to the data
|
||||
# repository (which this workflow file lives in),
|
||||
# to store data and the report files.
|
||||
ghtoken: ${{ github.token }}
|
||||
5
.github/workflows/sonar.yml
vendored
5
.github/workflows/sonar.yml
vendored
@@ -3,7 +3,7 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
- v*
|
||||
paths:
|
||||
- 'frontend/**'
|
||||
defaults:
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Sonar analysis
|
||||
@@ -24,3 +24,4 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
||||
6
.github/workflows/staging-deployment.yaml
vendored
6
.github/workflows/staging-deployment.yaml
vendored
@@ -11,23 +11,21 @@ jobs:
|
||||
environment: staging
|
||||
steps:
|
||||
- name: Executing remote ssh commands using ssh key
|
||||
uses: appleboy/ssh-action@v0.1.8
|
||||
uses: appleboy/ssh-action@v0.1.6
|
||||
env:
|
||||
GITHUB_BRANCH: develop
|
||||
GITHUB_SHA: ${{ github.sha }}
|
||||
with:
|
||||
host: ${{ secrets.HOST_DNS }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
key: ${{ secrets.EC2_SSH_KEY }}
|
||||
envs: GITHUB_BRANCH,GITHUB_SHA
|
||||
command_timeout: 60m
|
||||
script: |
|
||||
echo "GITHUB_BRANCH: ${GITHUB_BRANCH}"
|
||||
echo "GITHUB_SHA: ${GITHUB_SHA}"
|
||||
export DOCKER_TAG="${GITHUB_SHA:0:7}" # needed for child process to access it
|
||||
export OTELCOL_TAG="main"
|
||||
docker system prune --force
|
||||
docker pull signoz/signoz-otel-collector:main
|
||||
cd ~/signoz
|
||||
git status
|
||||
git add .
|
||||
|
||||
4
.github/workflows/testing-deployment.yaml
vendored
4
.github/workflows/testing-deployment.yaml
vendored
@@ -11,14 +11,14 @@ jobs:
|
||||
if: ${{ github.event.label.name == 'testing-deploy' }}
|
||||
steps:
|
||||
- name: Executing remote ssh commands using ssh key
|
||||
uses: appleboy/ssh-action@v0.1.8
|
||||
uses: appleboy/ssh-action@v0.1.6
|
||||
env:
|
||||
GITHUB_BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||
GITHUB_SHA: ${{ github.sha }}
|
||||
with:
|
||||
host: ${{ secrets.HOST_DNS }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
key: ${{ secrets.EC2_SSH_KEY }}
|
||||
envs: GITHUB_BRANCH,GITHUB_SHA
|
||||
command_timeout: 60m
|
||||
script: |
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
|
||||
node_modules
|
||||
yarn.lock
|
||||
package.json
|
||||
|
||||
deploy/docker/environment_tiny/common_test
|
||||
frontend/node_modules
|
||||
@@ -50,6 +52,4 @@ ee/query-service/tests/test-deploy/data/
|
||||
*.db
|
||||
/deploy/docker/clickhouse-setup/data/
|
||||
/deploy/docker-swarm/clickhouse-setup/data/
|
||||
bin/
|
||||
|
||||
*/query-service/queries.active
|
||||
bin/
|
||||
@@ -80,7 +80,7 @@ Before sending us a pull request, please ensure that,
|
||||
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
|
||||
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
|
||||
|
||||
**Note:** Unless your change is small, **please** consider submitting different Pull Request(s):
|
||||
**Note:** Unless your change is small, **please** consider submitting different Pull Rrequest(s):
|
||||
|
||||
* 1️⃣ First PR should include the overall structure of the new component:
|
||||
* Readme, configuration, interfaces or base classes, etc...
|
||||
@@ -338,7 +338,7 @@ to make SigNoz UI available at [localhost:3301](http://localhost:3301)
|
||||
**5.1.1 To install the HotROD sample app:**
|
||||
|
||||
```bash
|
||||
curl -sL https://github.com/SigNoz/signoz/raw/develop/sample-apps/hotrod/hotrod-install.sh \
|
||||
curl -sL https://github.com/SigNoz/signoz/raw/main/sample-apps/hotrod/hotrod-install.sh \
|
||||
| HELM_RELEASE=my-release SIGNOZ_NAMESPACE=platform bash
|
||||
```
|
||||
|
||||
@@ -361,7 +361,7 @@ kubectl -n sample-application run strzal --image=djbingham/curl \
|
||||
**5.1.4 To delete the HotROD sample app:**
|
||||
|
||||
```bash
|
||||
curl -sL https://github.com/SigNoz/signoz/raw/develop/sample-apps/hotrod/hotrod-delete.sh \
|
||||
curl -sL https://github.com/SigNoz/signoz/raw/main/sample-apps/hotrod/hotrod-delete.sh \
|
||||
| HOTROD_NAMESPACE=sample-application bash
|
||||
```
|
||||
|
||||
|
||||
19
Makefile
19
Makefile
@@ -54,7 +54,7 @@ build-push-frontend:
|
||||
@echo "--> Building and pushing frontend docker image"
|
||||
@echo "------------------"
|
||||
@cd $(FRONTEND_DIRECTORY) && \
|
||||
docker buildx build --file Dockerfile --progress plain --push --platform linux/arm64,linux/amd64 \
|
||||
docker buildx build --file Dockerfile --progress plane --push --platform linux/arm64,linux/amd64 \
|
||||
--tag $(REPONAME)/$(FRONTEND_DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||
|
||||
# Steps to build and push docker image of query service
|
||||
@@ -73,7 +73,7 @@ build-push-query-service:
|
||||
@echo "------------------"
|
||||
@echo "--> Building and pushing query-service docker image"
|
||||
@echo "------------------"
|
||||
@docker buildx build --file $(QUERY_SERVICE_DIRECTORY)/Dockerfile --progress plain \
|
||||
@docker buildx build --file $(QUERY_SERVICE_DIRECTORY)/Dockerfile --progress plane \
|
||||
--push --platform linux/arm64,linux/amd64 --build-arg LD_FLAGS="$(LD_FLAGS)" \
|
||||
--tag $(REPONAME)/$(QUERY_SERVICE_DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||
|
||||
@@ -98,7 +98,7 @@ build-push-ee-query-service:
|
||||
@echo "--> Building and pushing query-service docker image"
|
||||
@echo "------------------"
|
||||
@docker buildx build --file $(EE_QUERY_SERVICE_DIRECTORY)/Dockerfile \
|
||||
--progress plain --push --platform linux/arm64,linux/amd64 \
|
||||
--progress plane --push --platform linux/arm64,linux/amd64 \
|
||||
--build-arg LD_FLAGS="$(LD_FLAGS)" --tag $(REPONAME)/$(QUERY_SERVICE_DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||
|
||||
dev-setup:
|
||||
@@ -136,18 +136,5 @@ clear-swarm-data:
|
||||
@docker run --rm -v "$(PWD)/$(SWARM_DIRECTORY)/data:/pwd" busybox \
|
||||
sh -c "cd /pwd && rm -rf alertmanager/* clickhouse*/* signoz/* zookeeper-*/*"
|
||||
|
||||
clear-standalone-ch:
|
||||
@docker run --rm -v "$(PWD)/$(STANDALONE_DIRECTORY)/data:/pwd" busybox \
|
||||
sh -c "cd /pwd && rm -rf clickhouse*/* zookeeper-*/*"
|
||||
|
||||
clear-swarm-ch:
|
||||
@docker run --rm -v "$(PWD)/$(SWARM_DIRECTORY)/data:/pwd" busybox \
|
||||
sh -c "cd /pwd && rm -rf clickhouse*/* zookeeper-*/*"
|
||||
|
||||
test:
|
||||
go test ./pkg/query-service/app/metrics/...
|
||||
go test ./pkg/query-service/cache/...
|
||||
go test ./pkg/query-service/app/...
|
||||
go test ./pkg/query-service/app/querier/...
|
||||
go test ./pkg/query-service/converter/...
|
||||
go test ./pkg/query-service/formatter/...
|
||||
|
||||
168
README.de-de.md
168
README.de-de.md
@@ -1,75 +1,40 @@
|
||||
<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">Überwache deine Anwendungen und behebe Probleme in deinen bereitgestellten Anwendungen. SigNoz ist eine Open Source Alternative zu DataDog, New Relic, etc.</p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Downloads" src="https://img.shields.io/docker/pulls/signoz/query-service?label=Downloads"> </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>
|
||||
<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>Dokumentation</b></a> •
|
||||
<a href="https://github.com/SigNoz/signoz/blob/develop/README.md"><b>Readme auf Englisch </b></a> •
|
||||
<a href="https://github.com/SigNoz/signoz/blob/develop/README.zh-cn.md"><b>ReadMe auf Chinesisch</b></a> •
|
||||
<a href="https://github.com/SigNoz/signoz/blob/develop/README.pt-br.md"><b>ReadMe auf Portugiesisch</b></a> •
|
||||
<a href="https://signoz.io/slack"><b>Slack Community</b></a> •
|
||||
<a href="https://twitter.com/SigNozHq"><b>Twitter</b></a>
|
||||
<a href="https://twitter.com/SigNozHQ"><b>Twitter</b></a>
|
||||
</h3>
|
||||
|
||||
##
|
||||
##
|
||||
|
||||
SigNoz hilft Entwicklern, Anwendungen zu überwachen und Probleme in ihren bereitgestellten Anwendungen zu beheben. Mit SigNoz können Sie Folgendes tun:
|
||||
SigNoz hilft Entwicklern, Anwendungen zu überwachen und Probleme in ihren bereitgestellten Anwendungen zu beheben. SigNoz benutzt verteilte Einzelschritt-Fehlersuchen, um Einblick in deinen Software-Stack zu bekommen.
|
||||
|
||||
👉 Visualisieren Sie Metriken, Traces und Logs in einer einzigen Oberfläche.
|
||||
👉 Du kannst Werte wie die P99-Latenz und die Fehler Häufigkeit von deinen Services, externen API Aufrufen und einzelnen Endpunkten sehen.
|
||||
|
||||
👉 Sie können Metriken wie die p99-Latenz, Fehlerquoten für Ihre Dienste, externe API-Aufrufe und individuelle Endpunkte anzeigen.
|
||||
👉 Du kannst die Ursache des Problems finden, indem du zu dem Einzelschritt gehst, der das Problem verursacht und dir detaillierte Flamegraphs von einzelnen Abfragefehlersuchen anzeigen lassen.
|
||||
|
||||
👉 Sie können die Ursache des Problems ermitteln, indem Sie zu den genauen Traces gehen, die das Problem verursachen, und detaillierte Flammenbilder einzelner Anfragetraces anzeigen.
|
||||
|
||||
👉 Führen Sie Aggregationen auf Trace-Daten durch, um geschäftsrelevante Metriken zu erhalten.
|
||||
|
||||
👉 Filtern und Abfragen von Logs, Erstellen von Dashboards und Benachrichtigungen basierend auf Attributen in den Logs.
|
||||
|
||||
👉 Automatische Aufzeichnung von Ausnahmen in Python, Java, Ruby und Javascript.
|
||||
|
||||
👉 Einfache Einrichtung von Benachrichtigungen mit dem selbst erstellbaren Abfrage-Builder.
|
||||
|
||||
##
|
||||
### Anwendung Metriken
|
||||
|
||||

|
||||
|
||||
|
||||
### Verteiltes Tracing
|
||||
<img width="2068" alt="distributed_tracing_2 2" src="https://user-images.githubusercontent.com/83692067/226536447-bae58321-6a22-4ed3-af80-e3e964cb3489.png">
|
||||
|
||||
<img width="2068" alt="distributed_tracing_1" src="https://user-images.githubusercontent.com/83692067/226536462-939745b6-4f9d-45a6-8016-814837e7f7b4.png">
|
||||
|
||||
### Log Verwaltung
|
||||
|
||||
<img width="2068" alt="logs_management" src="https://user-images.githubusercontent.com/83692067/226536482-b8a5c4af-b69c-43d5-969c-338bd5eaf1a5.png">
|
||||
|
||||
### Infrastruktur Überwachung
|
||||
|
||||
<img width="2068" alt="infrastructure_monitoring" src="https://user-images.githubusercontent.com/83692067/226536496-f38c4dbf-e03c-4158-8be0-32d4a61158c7.png">
|
||||
|
||||
### Exceptions Monitoring
|
||||
|
||||

|
||||
|
||||
|
||||
### Alarme
|
||||
|
||||
<img width="2068" alt="alerts_management" src="https://user-images.githubusercontent.com/83692067/226536548-2c81e2e8-c12d-47e8-bad7-c6be79055def.png">
|
||||
👉 Erstelle Aggregate auf Basis von Fehlersuche Daten, um geschäftsrelevante Metriken zu erhalten.
|
||||
|
||||

|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## Werde Teil unserer Slack Community
|
||||
|
||||
@@ -77,22 +42,20 @@ Sag Hi zu uns auf [Slack](https://signoz.io/slack) 👋
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Features.svg" width="50px" />
|
||||
|
||||
## Funktionen:
|
||||
|
||||
- Einheitliche Benutzeroberfläche für Metriken, Traces und Logs. Keine Notwendigkeit, zwischen Prometheus und Jaeger zu wechseln, um Probleme zu debuggen oder ein separates Log-Tool wie Elastic neben Ihrer Metriken- und Traces-Stack zu verwenden.
|
||||
- Überblick über Anwendungsmetriken wie RPS, Latenzzeiten des 50tes/90tes/99tes Perzentils und Fehlerquoten.
|
||||
- Langsamste Endpunkte in Ihrer Anwendung.
|
||||
- Zeigen Sie genaue Anfragetraces an, um Probleme in nachgelagerten Diensten, langsamen Datenbankabfragen oder Aufrufen von Drittanbieterdiensten wie Zahlungsgateways zu identifizieren.
|
||||
- Filtern Sie Traces nach Dienstname, Operation, Latenz, Fehler, Tags/Annotationen.
|
||||
- Führen Sie Aggregationen auf Trace-Daten (Ereignisse/Spans) durch, um geschäftsrelevante Metriken zu erhalten. Beispielsweise können Sie die Fehlerquote und die 99tes Perzentillatenz für `customer_type: gold` oder `deployment_version: v2` oder `external_call: paypal` erhalten.
|
||||
- Native Unterstützung für OpenTelemetry-Logs, erweiterten Log-Abfrage-Builder und automatische Log-Sammlung aus dem Kubernetes-Cluster.
|
||||
- Blitzschnelle Log-Analytik ([Logs Perf. Benchmark](https://signoz.io/blog/logs-performance-benchmark/))
|
||||
- End-to-End-Sichtbarkeit der Infrastrukturleistung, Aufnahme von Metriken aus allen Arten von Host-Umgebungen.
|
||||
- Einfache Einrichtung von Benachrichtigungen mit dem selbst erstellbaren Abfrage-Builder.
|
||||
- Übersichtsmetriken deiner Anwendung wie RPS, 50tes/90tes/99tes Quantil Latenzen und Fehler Häufigkeiten.
|
||||
- Übersicht der langsamsten Endpunkte deiner Anwendung.
|
||||
- Sieh dir die genaue Einzelschritt-Fehlersuche deiner Abfrage an, um Fehler in nachgelagerten Diensten, langsamen Datenbank Abfragen und Aufrufen von Drittanbieter Diensten wie Zahlungsportalen, etc. zu finden.
|
||||
- Filtere Einzelschritt-Fehlersuchen nach Dienstname, Latenz, Fehler, Stichworten/ Anmerkungen.
|
||||
- Führe Aggregate auf Basis von Einzelschritt-Fehlersuche Daten (Ereignisse/Abstände) aus, um geschäftsrelevante Metriken zu erhalten. Du kannst dir z. B. die Fehlerrate und 99tes Quantil Latenz von `customer_type: gold`, `deployment_version: v2` oder `external_call: paypal` ausgeben lassen.
|
||||
- Einheitliche Benutzeroberfläche für Metriken und Einzelschritt-Fehlersuchen. Du musst nicht zwischen Prometheus und Jaeger hin und her wechseln, um Fehler zu beheben.
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/WhatsCool.svg" width="50px" />
|
||||
|
||||
## Wieso SigNoz?
|
||||
|
||||
@@ -102,46 +65,45 @@ Wir wollten eine selbst gehostete, Open Source Variante von Lösungen wie DataDo
|
||||
|
||||
Open Source gibt dir außerdem die totale Kontrolle über deine Konfiguration, Stichprobenentnahme und Betriebszeit. Du kannst des Weiteren neue Module auf Basis von SigNoz bauen, die erweiterte, geschäftsspezifische Funktionen anbieten.
|
||||
|
||||
### Languages supported:
|
||||
### Unterstützte Programmiersprachen:
|
||||
|
||||
Wir unterstützen [OpenTelemetry](https://opentelemetry.io) als Bibliothek, mit der Sie Ihre Anwendungen instrumentieren können. Daher wird jedes von OpenTelemetry unterstützte Framework und jede Sprache auch von SignNoz unterstützt. Einige der wichtigsten unterstützten Sprachen sind:
|
||||
Wir unterstützen [OpenTelemetry](https://opentelemetry.io) als die Software Library, die du nutzen kannst um deine Anwendungen auszuführen. Jedes Framework und jede Sprache die von OpenTelemetry unterstützt wird, wird auch von SigNoz unterstützt. Einige der unterstützten, größeren Programmiersprachen sind:
|
||||
|
||||
- Java
|
||||
- Python
|
||||
- NodeJS
|
||||
- Go
|
||||
- PHP
|
||||
- .NET
|
||||
- Ruby
|
||||
- Elixir
|
||||
- Rust
|
||||
|
||||
|
||||
Hier findest du die vollständige Liste von unterstützten Programmiersprachen - https://opentelemetry.io/docs/
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Philosophy.svg" width="50px" />
|
||||
|
||||
## Erste Schritte mit SigNoz
|
||||
|
||||
|
||||
|
||||
### Bereitstellung mit Docker
|
||||
|
||||
Bitte folge den [hier](https://signoz.io/docs/install/docker/) aufgelisteten Schritten um deine Anwendung mit Docker bereitzustellen.
|
||||
Bitte folge den [hier](https://signoz.io/docs/deployment/docker/) aufgelisteten Schritten um deine Anwendung mit Docker bereitzustellen.
|
||||
|
||||
Die [Anleitungen zur Fehlerbehebung](https://signoz.io/docs/install/troubleshooting/) könnten hilfreich sein, falls du auf irgendwelche Schwierigkeiten stößt.
|
||||
Die [Anleitungen zur Fehlerbehebung](https://signoz.io/docs/deployment/troubleshooting) könnten hilfreich sein, falls du auf irgendwelche Schwierigkeiten stößt.
|
||||
|
||||
<p>  </p>
|
||||
|
||||
### Deploy in Kubernetes using Helm
|
||||
|
||||
|
||||
### Bereitstellung mit Kubernetes und Helm
|
||||
|
||||
Bitte folge den [hier](https://signoz.io/docs/deployment/helm_chart) aufgelisteten Schritten, um deine Anwendung mit Helm Charts bereitzustellen.
|
||||
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/UseSigNoz.svg" width="50px" />
|
||||
|
||||
## Vergleiche mit bekannten Tools
|
||||
## Vergleiche mit anderen Lösungen
|
||||
|
||||
### SigNoz vs Prometheus
|
||||
### SigNoz vs. Prometheus
|
||||
|
||||
Prometheus ist gut, falls du dich nur für Metriken interessierst. Wenn du eine nahtlose Integration von Metriken und Einzelschritt-Fehlersuchen haben möchtest, ist die Kombination aus Prometheus und Jaeger nicht das Richtige für dich.
|
||||
|
||||
@@ -149,79 +111,49 @@ Unser Ziel ist es, eine integrierte Benutzeroberfläche aus Metriken und Einzels
|
||||
|
||||
<p>  </p>
|
||||
|
||||
### SigNoz vs Jaeger
|
||||
### SigNoz vs. Jaeger
|
||||
|
||||
Jaeger kümmert sich nur um verteilte Einzelschritt-Fehlersuche. SigNoz erstellt sowohl Metriken als auch Einzelschritt-Fehlersuche, daneben haben wir auch Protokoll Verwaltung auf unserem Plan.
|
||||
|
||||
Außerdem hat SigNoz noch mehr spezielle Funktionen im Vergleich zu Jaeger:
|
||||
|
||||
- Jaeger UI zeigt keine Metriken für Einzelschritt-Fehlersuchen oder für gefilterte Einzelschritt-Fehlersuchen an.
|
||||
- Jaeger erstellt keine Aggregate für gefilterte Einzelschritt-Fehlersuchen, z. B. die P99 Latenz von Abfragen mit dem Tag `customer_type=premium`, was hingegen mit SigNoz leicht umsetzbar ist.
|
||||
|
||||
<p>  </p>
|
||||
|
||||
### SigNoz vs Elastic
|
||||
|
||||
- Die Verwaltung von SigNoz-Protokollen basiert auf 'ClickHouse', einem spaltenbasierten OLAP-Datenspeicher, der aggregierte Protokollanalyseabfragen wesentlich effizienter macht.
|
||||
- 50 % geringerer Ressourcenbedarf im Vergleich zu Elastic während der Aufnahme.
|
||||
|
||||
Wir haben Benchmarks veröffentlicht, die Elastic mit SignNoz vergleichen. Schauen Sie es sich [hier](https://signoz.io/blog/logs-performance-benchmark/?utm_source=github-readme&utm_medium=logs-benchmark)
|
||||
|
||||
<p>  </p>
|
||||
|
||||
### SigNoz vs Loki
|
||||
|
||||
- SigNoz unterstützt Aggregationen von Daten mit hoher Kardinalität über ein großes Volumen, Loki hingegen nicht.
|
||||
- SigNoz unterstützt Indizes über Daten mit hoher Kardinalität und hat keine Beschränkungen hinsichtlich der Anzahl der Indizes, während Loki maximale Streams erreicht, wenn ein paar Indizes hinzugefügt werden.
|
||||
- Das Durchsuchen großer Datenmengen ist in Loki im Vergleich zu SigNoz schwierig und langsam.
|
||||
|
||||
Wir haben Benchmarks veröffentlicht, die Loki mit SigNoz vergleichen. Schauen Sie es sich [hier](https://signoz.io/blog/logs-performance-benchmark/?utm_source=github-readme&utm_medium=logs-benchmark)
|
||||
- Jaeger UI zeigt keine Metriken für Einzelschritt-Fehlersuchen oder für gefilterte Einzelschritt-Fehlersuchen an
|
||||
- Jaeger erstellt keine Aggregate für gefilterte Einzelschritt-Fehlersuchen, z. B. die P99 Latenz von Abfragen mit dem Tag - customer_type='premium', was hingegen mit SigNoz leicht umsetzbar ist.
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributors.svg" width="50px" />
|
||||
|
||||
## Zum Projekt beitragen
|
||||
|
||||
Wir ❤️ Beiträge zum Projekt, egal ob große oder kleine. Bitte lies dir zuerst die [CONTRIBUTING.md](CONTRIBUTING.md), durch, bevor du anfängst, Beiträge zu SigNoz zu machen.
|
||||
Du bist dir nicht sicher, wie du anfangen sollst? Schreib uns einfach auf dem #contributing Kanal in unserer [slack community](https://signoz.io/slack)
|
||||
|
||||
### Unsere Projektbetreuer
|
||||
Wir ❤️ Beiträge zum Projekt, egal ob große oder kleine. Bitte lies dir zuerst die [CONTRIBUTING.md](CONTRIBUTING.md) durch, bevor du anfängst, Beiträge zu SigNoz zu machen.
|
||||
|
||||
#### Backend
|
||||
|
||||
- [Ankit Nayan](https://github.com/ankitnayan)
|
||||
- [Nityananda Gohain](https://github.com/nityanandagohain)
|
||||
- [Srikanth Chekuri](https://github.com/srikanthccv)
|
||||
- [Vishal Sharma](https://github.com/makeavish)
|
||||
|
||||
#### Frontend
|
||||
|
||||
- [Palash Gupta](https://github.com/palashgdev)
|
||||
|
||||
#### DevOps
|
||||
|
||||
- [Prashant Shahi](https://github.com/prashant-shahi)
|
||||
Du bist dir nicht sicher, wie du anfangen sollst? Schreib uns einfach auf dem `#contributing` Kanal in unserer [Slack Community](https://signoz.io/slack).
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/DevelopingLocally.svg" width="50px" />
|
||||
|
||||
## Dokumentation
|
||||
|
||||
Du findest unsere Dokumentation unter https://signoz.io/docs/. Falls etwas unverständlich ist oder fehlt, öffne gerne ein Github Issue mit dem Label `documentation` oder schreib uns über den Community Slack Channel.
|
||||
|
||||
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## Gemeinschaft
|
||||
## Community
|
||||
|
||||
Werde Teil der [slack community](https://signoz.io/slack) um mehr über verteilte Einzelschritt-Fehlersuche, Messung von Systemzuständen oder SigNoz zu erfahren und sich mit anderen Nutzern und Mitwirkenden in Verbindung zu setzen.
|
||||
Werde Teil der [Slack Community](https://signoz.io/slack) um mehr über verteilte Einzelschritt-Fehlersuche, Messung von Systemzuständen oder SigNoz zu erfahren und sich mit anderen Nutzern und Mitwirkenden in Verbindung zu setzen.
|
||||
|
||||
Falls du irgendwelche Ideen, Fragen oder Feedback hast, kannst du sie gerne über unsere [Github Discussions](https://github.com/SigNoz/signoz/discussions) mit uns teilen.
|
||||
|
||||
Wie immer, Dank an unsere großartigen Mitwirkenden!
|
||||
Wie immer, danke an unsere großartigen Unterstützer!
|
||||
|
||||
<a href="https://github.com/signoz/signoz/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=signoz/signoz" />
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
59
README.md
59
README.md
@@ -23,7 +23,7 @@
|
||||
|
||||
##
|
||||
|
||||
SigNoz helps developers monitor applications and troubleshoot problems in their deployed applications. With SigNoz, you can:
|
||||
SigNoz helps developers monitor applications and troubleshoot problems in their deployed applications. SigNoz uses distributed tracing to gain visibility into your software stack.
|
||||
|
||||
👉 Visualise Metrics, Traces and Logs in a single pane of glass
|
||||
|
||||
@@ -35,41 +35,19 @@ SigNoz helps developers monitor applications and troubleshoot problems in their
|
||||
|
||||
👉 Filter and query logs, build dashboards and alerts based on attributes in logs
|
||||
|
||||
👉 Record exceptions automatically in Python, Java, Ruby, and Javascript
|
||||

|
||||
<br />
|
||||

|
||||
<br />
|
||||

|
||||
<br />
|
||||

|
||||
|
||||
👉 Easy to set alerts with DIY query builder
|
||||
|
||||
|
||||
### Application Metrics
|
||||
|
||||

|
||||
|
||||
|
||||
### Distributed Tracing
|
||||
<img width="2068" alt="distributed_tracing_2 2" src="https://user-images.githubusercontent.com/83692067/226536447-bae58321-6a22-4ed3-af80-e3e964cb3489.png">
|
||||
|
||||
<img width="2068" alt="distributed_tracing_1" src="https://user-images.githubusercontent.com/83692067/226536462-939745b6-4f9d-45a6-8016-814837e7f7b4.png">
|
||||
|
||||
### Logs Management
|
||||
|
||||
<img width="2068" alt="logs_management" src="https://user-images.githubusercontent.com/83692067/226536482-b8a5c4af-b69c-43d5-969c-338bd5eaf1a5.png">
|
||||
|
||||
### Infrastructure Monitoring
|
||||
|
||||
<img width="2068" alt="infrastructure_monitoring" src="https://user-images.githubusercontent.com/83692067/226536496-f38c4dbf-e03c-4158-8be0-32d4a61158c7.png">
|
||||
|
||||
### Exceptions Monitoring
|
||||
|
||||

|
||||
|
||||
|
||||
### Alerts
|
||||
|
||||
<img width="2068" alt="alerts_management" src="https://user-images.githubusercontent.com/83692067/226536548-2c81e2e8-c12d-47e8-bad7-c6be79055def.png">
|
||||
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## Join our Slack community
|
||||
|
||||
@@ -77,6 +55,7 @@ Come say Hi to us on [Slack](https://signoz.io/slack) 👋
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Features.svg" width="50px" />
|
||||
|
||||
## Features:
|
||||
|
||||
@@ -86,13 +65,10 @@ Come say Hi to us on [Slack](https://signoz.io/slack) 👋
|
||||
- See exact request trace to figure out issues in downstream services, slow DB queries, call to 3rd party services like payment gateways, etc
|
||||
- Filter traces by service name, operation, latency, error, tags/annotations.
|
||||
- Run aggregates on trace data (events/spans) to get business relevant metrics. e.g. You can get error rate and 99th percentile latency of `customer_type: gold` or `deployment_version: v2` or `external_call: paypal`
|
||||
- Native support for OpenTelemetry Logs, advanced log query builder, and automatic log collection from k8s cluster
|
||||
- Lightning quick log analytics ([Logs Perf. Benchmark](https://signoz.io/blog/logs-performance-benchmark/))
|
||||
- End-to-End visibility into infrastructure performance, ingest metrics from all kinds of host environments
|
||||
- Easy to set alerts with DIY query builder
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/WhatsCool.svg" width="50px" />
|
||||
|
||||
## Why SigNoz?
|
||||
|
||||
@@ -121,14 +97,15 @@ You can find the complete list of languages here - https://opentelemetry.io/docs
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Philosophy.svg" width="50px" />
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Deploy using Docker
|
||||
|
||||
Please follow the steps listed [here](https://signoz.io/docs/install/docker/) to install using docker
|
||||
Please follow the steps listed [here](https://signoz.io/docs/deployment/docker/) to install using docker
|
||||
|
||||
The [troubleshooting instructions](https://signoz.io/docs/install/troubleshooting/) may be helpful if you face any issues.
|
||||
The [troubleshooting instructions](https://signoz.io/docs/deployment/troubleshooting) may be helpful if you face any issues.
|
||||
|
||||
<p>  </p>
|
||||
|
||||
@@ -139,6 +116,7 @@ Please follow the steps listed [here](https://signoz.io/docs/deployment/helm_cha
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/UseSigNoz.svg" width="50px" />
|
||||
|
||||
## Comparisons to Familiar Tools
|
||||
|
||||
@@ -166,8 +144,6 @@ Moreover, SigNoz has few more advanced features wrt Jaeger:
|
||||
- SigNoz Logs management are based on ClickHouse, a columnar OLAP datastore which makes aggregate log analytics queries much more efficient
|
||||
- 50% lower resource requirement compared to Elastic during ingestion
|
||||
|
||||
We have published benchmarks comparing Elastic with SigNoz. Check it out [here](https://signoz.io/blog/logs-performance-benchmark/?utm_source=github-readme&utm_medium=logs-benchmark)
|
||||
|
||||
<p>  </p>
|
||||
|
||||
### SigNoz vs Loki
|
||||
@@ -176,10 +152,9 @@ We have published benchmarks comparing Elastic with SigNoz. Check it out [here](
|
||||
- SigNoz supports indexes over high cardinality data and has no limitations on the number of indexes, while Loki reaches max streams with a few indexes added to it.
|
||||
- Searching over a huge volume of data is difficult and slow in Loki compared to SigNoz
|
||||
|
||||
We have published benchmarks comparing Loki with SigNoz. Check it out [here](https://signoz.io/blog/logs-performance-benchmark/?utm_source=github-readme&utm_medium=logs-benchmark)
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributors.svg" width="50px" />
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -206,6 +181,7 @@ Not sure how to get started? Just ping us on `#contributing` in our [slack commu
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/DevelopingLocally.svg" width="50px" />
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -213,6 +189,7 @@ You can find docs at https://signoz.io/docs/. If you need any clarification or f
|
||||
|
||||
<br /><br />
|
||||
|
||||
<img align="left" src="https://signoz-public.s3.us-east-2.amazonaws.com/Contributing.svg" width="50px" />
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
@@ -84,9 +84,9 @@ Você pode encontrar a lista completa de linguagens aqui - https://opentelemetry
|
||||
|
||||
### Implantar usando Docker
|
||||
|
||||
Siga as etapas listadas [aqui](https://signoz.io/docs/install/docker/) para instalar usando o Docker.
|
||||
Siga as etapas listadas [aqui](https://signoz.io/docs/deployment/docker/) para instalar usando o Docker.
|
||||
|
||||
Esse [guia para solução de problemas](https://signoz.io/docs/install/troubleshooting/) pode ser útil se você enfrentar quaisquer problemas.
|
||||
Esse [guia para solução de problemas](https://signoz.io/docs/deployment/troubleshooting) pode ser útil se você enfrentar quaisquer problemas.
|
||||
|
||||
<p>  </p>
|
||||
|
||||
|
||||
@@ -80,9 +80,9 @@ SigNoz帮助开发人员监控应用并排查已部署应用中的问题。SigNo
|
||||
|
||||
### 使用Docker部署
|
||||
|
||||
请按照[这里](https://signoz.io/docs/install/docker/)列出的步骤使用Docker来安装
|
||||
请按照[这里](https://signoz.io/docs/deployment/docker/)列出的步骤使用Docker来安装
|
||||
|
||||
如果你遇到任何问题,这个[排查指南](https://signoz.io/docs/install/troubleshooting/)会对你有帮助。
|
||||
如果你遇到任何问题,这个[排查指南](https://signoz.io/docs/deployment/troubleshooting)会对你有帮助。
|
||||
|
||||
<p>  </p>
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ For x86 chip (amd):
|
||||
docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d
|
||||
```
|
||||
|
||||
For Mac with Apple chip (arm):
|
||||
|
||||
```sh
|
||||
docker-compose -f docker/clickhouse-setup/docker-compose.arm.yaml up -d
|
||||
```
|
||||
|
||||
Open http://localhost:3301 in your favourite browser. In couple of minutes, you should see
|
||||
the data generated from hotrod in SigNoz UI.
|
||||
|
||||
@@ -58,7 +64,7 @@ from the HotROD application, you should see the data generated from hotrod in Si
|
||||
```sh
|
||||
kubectl create ns sample-application
|
||||
|
||||
kubectl -n sample-application apply -f https://raw.githubusercontent.com/SigNoz/signoz/develop/sample-apps/hotrod/hotrod.yaml
|
||||
kubectl -n sample-application apply -f https://raw.githubusercontent.com/SigNoz/signoz/main/sample-apps/hotrod/hotrod.yaml
|
||||
```
|
||||
|
||||
To generate load:
|
||||
@@ -66,7 +72,7 @@ To generate load:
|
||||
```sh
|
||||
kubectl -n sample-application run strzal --image=djbingham/curl \
|
||||
--restart='OnFailure' -i --tty --rm --command -- curl -X POST -F \
|
||||
'user_count=6' -F 'spawn_rate=2' http://locust-master:8089/swarm
|
||||
'locust_count=6' -F 'hatch_rate=2' http://locust-master:8089/swarm
|
||||
```
|
||||
|
||||
To stop load:
|
||||
|
||||
@@ -7,21 +7,9 @@
|
||||
</default>
|
||||
<s3>
|
||||
<type>s3</type>
|
||||
<!-- For S3 cold storage,
|
||||
if region is us-east-1, endpoint can be https://<bucket-name>.s3.amazonaws.com
|
||||
if region is not us-east-1, endpoint should be https://<bucket-name>.s3-<region>.amazonaws.com
|
||||
For GCS cold storage,
|
||||
endpoint should be https://storage.googleapis.com/<bucket-name>/data/
|
||||
-->
|
||||
<endpoint>https://BUCKET-NAME.s3-REGION-NAME.amazonaws.com/data/</endpoint>
|
||||
<endpoint>https://BUCKET-NAME.s3.amazonaws.com/data/</endpoint>
|
||||
<access_key_id>ACCESS-KEY-ID</access_key_id>
|
||||
<secret_access_key>SECRET-ACCESS-KEY</secret_access_key>
|
||||
<!-- In case of S3, uncomment the below configuration in case you want to read
|
||||
AWS credentials from the Environment variables if they exist. -->
|
||||
<!-- <use_environment_credentials>true</use_environment_credentials> -->
|
||||
<!-- In case of GCS, uncomment the below configuration, since GCS does
|
||||
not support batch deletion and result in error messages in logs. -->
|
||||
<!-- <support_batch_delete>false</support_batch_delete> -->
|
||||
</s3>
|
||||
</disks>
|
||||
<policies>
|
||||
|
||||
@@ -34,7 +34,7 @@ x-clickhouse-depend: &clickhouse-depend
|
||||
|
||||
services:
|
||||
zookeeper-1:
|
||||
image: bitnami/zookeeper:3.7.1
|
||||
image: bitnami/zookeeper:3.7.0
|
||||
hostname: zookeeper-1
|
||||
user: root
|
||||
ports:
|
||||
@@ -124,7 +124,7 @@ services:
|
||||
# - ./data/clickhouse-3/:/var/lib/clickhouse/
|
||||
|
||||
alertmanager:
|
||||
image: signoz/alertmanager:0.23.1
|
||||
image: signoz/alertmanager:0.23.0-0.2
|
||||
volumes:
|
||||
- ./data/alertmanager:/data
|
||||
command:
|
||||
@@ -137,7 +137,7 @@ services:
|
||||
condition: on-failure
|
||||
|
||||
query-service:
|
||||
image: signoz/query-service:0.25.1
|
||||
image: signoz/query-service:0.14.0
|
||||
command: ["-config=/root/config/prometheus.yml"]
|
||||
# ports:
|
||||
# - "6060:6060" # pprof port
|
||||
@@ -156,7 +156,7 @@ services:
|
||||
- TELEMETRY_ENABLED=true
|
||||
- DEPLOYMENT_TYPE=docker-swarm
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8080/api/v1/health"]
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8080/api/v1/version"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
@@ -166,7 +166,7 @@ services:
|
||||
<<: *clickhouse-depend
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:0.25.1
|
||||
image: signoz/frontend:0.14.0
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
@@ -179,8 +179,8 @@ services:
|
||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
otel-collector:
|
||||
image: signoz/signoz-otel-collector:0.79.4
|
||||
command: ["--config=/etc/otel-collector-config.yaml", "--feature-gates=-pkg.translator.prometheus.NormalizeName"]
|
||||
image: signoz/signoz-otel-collector:0.66.2
|
||||
command: ["--config=/etc/otel-collector-config.yaml"]
|
||||
user: root # required for reading docker container logs
|
||||
volumes:
|
||||
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
|
||||
@@ -188,7 +188,6 @@ services:
|
||||
environment:
|
||||
- OTEL_RESOURCE_ATTRIBUTES=host.name={{.Node.Hostname}},os.type={{.Node.Platform.OS}},dockerswarm.service.name={{.Service.Name}},dockerswarm.task.name={{.Task.Name}}
|
||||
- DOCKER_MULTI_NODE_CLUSTER=false
|
||||
- LOW_CARDINAL_EXCEPTION_GROUPING=false
|
||||
ports:
|
||||
# - "1777:1777" # pprof extension
|
||||
- "4317:4317" # OTLP gRPC receiver
|
||||
@@ -208,8 +207,8 @@ services:
|
||||
<<: *clickhouse-depend
|
||||
|
||||
otel-collector-metrics:
|
||||
image: signoz/signoz-otel-collector:0.79.4
|
||||
command: ["--config=/etc/otel-collector-metrics-config.yaml", "--feature-gates=-pkg.translator.prometheus.NormalizeName"]
|
||||
image: signoz/signoz-otel-collector:0.66.2
|
||||
command: ["--config=/etc/otel-collector-metrics-config.yaml"]
|
||||
volumes:
|
||||
- ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml
|
||||
# ports:
|
||||
@@ -233,7 +232,7 @@ services:
|
||||
max-file: "3"
|
||||
|
||||
load-hotrod:
|
||||
image: "signoz/locust:1.2.3"
|
||||
image: "grubykarol/locust:1.2.3-python3.9-alpine3.12"
|
||||
hostname: load-hotrod
|
||||
environment:
|
||||
ATTACKED_HOST: http://hotrod:8080
|
||||
|
||||
@@ -75,7 +75,7 @@ processors:
|
||||
timeout: 10s
|
||||
resourcedetection:
|
||||
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||
detectors: [env, system] # include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||
detectors: [env, system] # include ec2 for AWS, gce for GCP and azure for Azure.
|
||||
timeout: 2s
|
||||
signozspanmetrics/prometheus:
|
||||
metrics_exporter: prometheus
|
||||
@@ -110,7 +110,6 @@ exporters:
|
||||
clickhousetraces:
|
||||
datasource: tcp://clickhouse:9000/?database=signoz_traces
|
||||
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
|
||||
low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING}
|
||||
clickhousemetricswrite:
|
||||
endpoint: tcp://clickhouse:9000/?database=signoz_metrics
|
||||
resource_to_telemetry_conversion:
|
||||
|
||||
@@ -7,21 +7,9 @@
|
||||
</default>
|
||||
<s3>
|
||||
<type>s3</type>
|
||||
<!-- For S3 cold storage,
|
||||
if region is us-east-1, endpoint can be https://<bucket-name>.s3.amazonaws.com
|
||||
if region is not us-east-1, endpoint should be https://<bucket-name>.s3-<region>.amazonaws.com
|
||||
For GCS cold storage,
|
||||
endpoint should be https://storage.googleapis.com/<bucket-name>/data/
|
||||
-->
|
||||
<endpoint>https://BUCKET-NAME.s3-REGION-NAME.amazonaws.com/data/</endpoint>
|
||||
<endpoint>https://BUCKET-NAME.s3.amazonaws.com/data/</endpoint>
|
||||
<access_key_id>ACCESS-KEY-ID</access_key_id>
|
||||
<secret_access_key>SECRET-ACCESS-KEY</secret_access_key>
|
||||
<!-- In case of S3, uncomment the below configuration in case you want to read
|
||||
AWS credentials from the Environment variables if they exist. -->
|
||||
<!-- <use_environment_credentials>true</use_environment_credentials> -->
|
||||
<!-- In case of GCS, uncomment the below configuration, since GCS does
|
||||
not support batch deletion and result in error messages in logs. -->
|
||||
<!-- <support_batch_delete>false</support_batch_delete> -->
|
||||
</s3>
|
||||
</disks>
|
||||
<policies>
|
||||
|
||||
@@ -27,7 +27,7 @@ services:
|
||||
|
||||
alertmanager:
|
||||
container_name: alertmanager
|
||||
image: signoz/alertmanager:0.23.1
|
||||
image: signoz/alertmanager:0.23.0-0.2
|
||||
volumes:
|
||||
- ./data/alertmanager:/data
|
||||
depends_on:
|
||||
@@ -41,8 +41,8 @@ services:
|
||||
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
||||
otel-collector:
|
||||
container_name: otel-collector
|
||||
image: signoz/signoz-otel-collector:0.79.4
|
||||
command: ["--config=/etc/otel-collector-config.yaml", "--feature-gates=-pkg.translator.prometheus.NormalizeName"]
|
||||
image: signoz/signoz-otel-collector:0.66.2
|
||||
command: ["--config=/etc/otel-collector-config.yaml"]
|
||||
# user: root # required for reading docker container logs
|
||||
volumes:
|
||||
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
|
||||
@@ -67,8 +67,8 @@ services:
|
||||
|
||||
otel-collector-metrics:
|
||||
container_name: otel-collector-metrics
|
||||
image: signoz/signoz-otel-collector:0.79.4
|
||||
command: ["--config=/etc/otel-collector-metrics-config.yaml", "--feature-gates=-pkg.translator.prometheus.NormalizeName"]
|
||||
image: signoz/signoz-otel-collector:0.66.2
|
||||
command: ["--config=/etc/otel-collector-metrics-config.yaml"]
|
||||
volumes:
|
||||
- ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml
|
||||
# ports:
|
||||
@@ -93,7 +93,7 @@ services:
|
||||
- JAEGER_ENDPOINT=http://otel-collector:14268/api/traces
|
||||
|
||||
load-hotrod:
|
||||
image: "signoz/locust:1.2.3"
|
||||
image: "grubykarol/locust:1.2.3-python3.9-alpine3.12"
|
||||
container_name: load-hotrod
|
||||
hostname: load-hotrod
|
||||
environment:
|
||||
|
||||
@@ -28,7 +28,7 @@ services:
|
||||
- "8080:8080"
|
||||
restart: on-failure
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8080/api/v1/health"]
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8080/api/v1/version"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
@@ -34,9 +34,9 @@ x-clickhouse-depend: &clickhouse-depend
|
||||
# condition: service_healthy
|
||||
|
||||
services:
|
||||
|
||||
|
||||
zookeeper-1:
|
||||
image: bitnami/zookeeper:3.7.1
|
||||
image: bitnami/zookeeper:3.7.0
|
||||
container_name: zookeeper-1
|
||||
hostname: zookeeper-1
|
||||
user: root
|
||||
@@ -114,13 +114,13 @@ services:
|
||||
# volumes:
|
||||
# - ./clickhouse-config.xml:/etc/clickhouse-server/config.xml
|
||||
# - ./clickhouse-users.xml:/etc/clickhouse-server/users.xml
|
||||
# - ./custom-function.xml:/etc/clickhouse-server/custom-function.xml
|
||||
# - ./custom-function.xml:/etc/clickhouse-server/custom-function.xml
|
||||
# - ./clickhouse-cluster.xml:/etc/clickhouse-server/config.d/cluster.xml
|
||||
# # - ./clickhouse-storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
# - ./data/clickhouse-2/:/var/lib/clickhouse/
|
||||
# - ./user_scripts:/var/lib/clickhouse/user_scripts/
|
||||
|
||||
|
||||
|
||||
# clickhouse-3:
|
||||
# <<: *clickhouse-defaults
|
||||
# container_name: clickhouse-3
|
||||
@@ -132,14 +132,14 @@ services:
|
||||
# volumes:
|
||||
# - ./clickhouse-config.xml:/etc/clickhouse-server/config.xml
|
||||
# - ./clickhouse-users.xml:/etc/clickhouse-server/users.xml
|
||||
# - ./custom-function.xml:/etc/clickhouse-server/custom-function.xml
|
||||
# - ./custom-function.xml:/etc/clickhouse-server/custom-function.xml
|
||||
# - ./clickhouse-cluster.xml:/etc/clickhouse-server/config.d/cluster.xml
|
||||
# # - ./clickhouse-storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
# - ./data/clickhouse-3/:/var/lib/clickhouse/
|
||||
# - ./user_scripts:/var/lib/clickhouse/user_scripts/
|
||||
|
||||
alertmanager:
|
||||
image: signoz/alertmanager:${ALERTMANAGER_TAG:-0.23.1}
|
||||
image: signoz/alertmanager:${ALERTMANAGER_TAG:-0.23.0-0.2}
|
||||
volumes:
|
||||
- ./data/alertmanager:/data
|
||||
depends_on:
|
||||
@@ -150,10 +150,10 @@ services:
|
||||
- --queryService.url=http://query-service:8085
|
||||
- --storage.path=/data
|
||||
|
||||
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
||||
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
||||
|
||||
query-service:
|
||||
image: signoz/query-service:${DOCKER_TAG:-0.25.1}
|
||||
image: signoz/query-service:${DOCKER_TAG:-0.14.0}
|
||||
container_name: query-service
|
||||
command: ["-config=/root/config/prometheus.yml"]
|
||||
# ports:
|
||||
@@ -174,14 +174,14 @@ services:
|
||||
- DEPLOYMENT_TYPE=docker-standalone-amd
|
||||
restart: on-failure
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8080/api/v1/health"]
|
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8080/api/v1/version"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
<<: *clickhouse-depend
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:${DOCKER_TAG:-0.25.1}
|
||||
image: signoz/frontend:${DOCKER_TAG:-0.14.0}
|
||||
container_name: frontend
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
@@ -193,8 +193,8 @@ services:
|
||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
otel-collector:
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.79.4}
|
||||
command: ["--config=/etc/otel-collector-config.yaml", "--feature-gates=-pkg.translator.prometheus.NormalizeName"]
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.2}
|
||||
command: ["--config=/etc/otel-collector-config.yaml"]
|
||||
user: root # required for reading docker container logs
|
||||
volumes:
|
||||
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
|
||||
@@ -202,7 +202,6 @@ services:
|
||||
environment:
|
||||
- OTEL_RESOURCE_ATTRIBUTES=host.name=signoz-host,os.type=linux
|
||||
- DOCKER_MULTI_NODE_CLUSTER=false
|
||||
- LOW_CARDINAL_EXCEPTION_GROUPING=false
|
||||
ports:
|
||||
# - "1777:1777" # pprof extension
|
||||
- "4317:4317" # OTLP gRPC receiver
|
||||
@@ -219,8 +218,8 @@ services:
|
||||
<<: *clickhouse-depend
|
||||
|
||||
otel-collector-metrics:
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.79.4}
|
||||
command: ["--config=/etc/otel-collector-metrics-config.yaml", "--feature-gates=-pkg.translator.prometheus.NormalizeName"]
|
||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.2}
|
||||
command: ["--config=/etc/otel-collector-metrics-config.yaml"]
|
||||
volumes:
|
||||
- ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml
|
||||
# ports:
|
||||
@@ -232,18 +231,18 @@ services:
|
||||
<<: *clickhouse-depend
|
||||
|
||||
hotrod:
|
||||
image: jaegertracing/example-hotrod:1.30
|
||||
container_name: hotrod
|
||||
logging:
|
||||
options:
|
||||
max-size: 50m
|
||||
max-file: "3"
|
||||
command: ["all"]
|
||||
environment:
|
||||
- JAEGER_ENDPOINT=http://otel-collector:14268/api/traces
|
||||
image: jaegertracing/example-hotrod:1.30
|
||||
container_name: hotrod
|
||||
logging:
|
||||
options:
|
||||
max-size: 50m
|
||||
max-file: "3"
|
||||
command: ["all"]
|
||||
environment:
|
||||
- JAEGER_ENDPOINT=http://otel-collector:14268/api/traces
|
||||
|
||||
load-hotrod:
|
||||
image: "signoz/locust:1.2.3"
|
||||
image: "grubykarol/locust:1.2.3-python3.9-alpine3.12"
|
||||
container_name: load-hotrod
|
||||
hostname: load-hotrod
|
||||
environment:
|
||||
|
||||
@@ -70,40 +70,6 @@ receivers:
|
||||
|
||||
|
||||
processors:
|
||||
logstransform/internal:
|
||||
operators:
|
||||
- type: trace_parser
|
||||
if: '"trace_id" in attributes or "span_id" in attributes'
|
||||
trace_id:
|
||||
parse_from: attributes.trace_id
|
||||
span_id:
|
||||
parse_from: attributes.span_id
|
||||
output: remove_trace_id
|
||||
- type: trace_parser
|
||||
if: '"traceId" in attributes or "spanId" in attributes'
|
||||
trace_id:
|
||||
parse_from: attributes.traceId
|
||||
span_id:
|
||||
parse_from: attributes.spanId
|
||||
output: remove_traceId
|
||||
- id: remove_traceId
|
||||
type: remove
|
||||
if: '"traceId" in attributes'
|
||||
field: attributes.traceId
|
||||
output: remove_spanId
|
||||
- id: remove_spanId
|
||||
type: remove
|
||||
if: '"spanId" in attributes'
|
||||
field: attributes.spanId
|
||||
- id: remove_trace_id
|
||||
type: remove
|
||||
if: '"trace_id" in attributes'
|
||||
field: attributes.trace_id
|
||||
output: remove_span_id
|
||||
- id: remove_span_id
|
||||
type: remove
|
||||
if: '"span_id" in attributes'
|
||||
field: attributes.span_id
|
||||
batch:
|
||||
send_batch_size: 10000
|
||||
send_batch_max_size: 11000
|
||||
@@ -138,7 +104,7 @@ processors:
|
||||
# retry_on_failure: true
|
||||
resourcedetection:
|
||||
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||
detectors: [env, system] # include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||
detectors: [env, system] # include ec2 for AWS, gce for GCP and azure for Azure.
|
||||
timeout: 2s
|
||||
|
||||
extensions:
|
||||
@@ -153,7 +119,6 @@ exporters:
|
||||
clickhousetraces:
|
||||
datasource: tcp://clickhouse:9000/?database=signoz_traces
|
||||
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
|
||||
low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING}
|
||||
clickhousemetricswrite:
|
||||
endpoint: tcp://clickhouse:9000/?database=signoz_metrics
|
||||
resource_to_telemetry_conversion:
|
||||
@@ -206,5 +171,5 @@ service:
|
||||
exporters: [prometheus]
|
||||
logs:
|
||||
receivers: [otlp, filelog/dockercontainers]
|
||||
processors: [logstransform/internal, batch]
|
||||
processors: [batch]
|
||||
exporters: [clickhouselogsexporter]
|
||||
@@ -51,7 +51,7 @@ check_os() {
|
||||
os_name="$(cat /etc/*-release | awk -F= '$1 == "NAME" { gsub(/"/, ""); print $2; exit }')"
|
||||
|
||||
case "$os_name" in
|
||||
Ubuntu*|Pop!_OS)
|
||||
Ubuntu*)
|
||||
desired_os=1
|
||||
os="ubuntu"
|
||||
package_manager="apt-get"
|
||||
@@ -81,11 +81,6 @@ check_os() {
|
||||
os="centos"
|
||||
package_manager="yum"
|
||||
;;
|
||||
Rocky*)
|
||||
desired_os=1
|
||||
os="centos"
|
||||
package_manager="yum"
|
||||
;;
|
||||
SLES*)
|
||||
desired_os=1
|
||||
os="sles"
|
||||
@@ -125,7 +120,7 @@ check_ports_occupied() {
|
||||
|
||||
echo "+++++++++++ ERROR ++++++++++++++++++++++"
|
||||
echo "SigNoz requires ports 3301 & 4317 to be open. Please shut down any other service(s) that may be running on these ports."
|
||||
echo "You can run SigNoz on another port following this guide https://signoz.io/docs/install/troubleshooting/"
|
||||
echo "You can run SigNoz on another port following this guide https://signoz.io/docs/deployment/docker#troubleshooting"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
exit 1
|
||||
@@ -228,7 +223,7 @@ wait_for_containers_start() {
|
||||
|
||||
# The while loop is important because for-loops don't work for dynamic values
|
||||
while [[ $timeout -gt 0 ]]; do
|
||||
status_code="$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:3301/api/v1/health?live=1" || true)"
|
||||
status_code="$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3301/api/v1/services/list || true)"
|
||||
if [[ status_code -eq 200 ]]; then
|
||||
break
|
||||
else
|
||||
@@ -249,7 +244,7 @@ bye() { # Prints a friendly good bye message and exits the script.
|
||||
echo ""
|
||||
echo -e "$sudo_cmd docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
|
||||
echo "Please read our troubleshooting guide https://signoz.io/docs/install/troubleshooting/"
|
||||
# echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker#troubleshooting"
|
||||
echo "or reach us for support in #help channel in our Slack Community https://signoz.io/slack"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
|
||||
@@ -277,7 +272,7 @@ request_sudo() {
|
||||
echo -e "\n\n🙇 We will need sudo access to complete the installation."
|
||||
if (( $EUID != 0 )); then
|
||||
sudo_cmd="sudo"
|
||||
echo -e "Please enter your sudo password, if prompted."
|
||||
echo -e "Please enter your sudo password, if prompt."
|
||||
# $sudo_cmd -l | grep -e "NOPASSWD: ALL" > /dev/null
|
||||
# if [[ $? -ne 0 ]] && ! $sudo_cmd -v; then
|
||||
# echo "Need sudo privileges to proceed with the installation."
|
||||
@@ -500,7 +495,7 @@ if [[ $status_code -ne 200 ]]; then
|
||||
|
||||
echo -e "$sudo_cmd docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
|
||||
echo "Please read our troubleshooting guide https://signoz.io/docs/install/troubleshooting/"
|
||||
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://signoz.io/slack"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++"
|
||||
|
||||
@@ -516,15 +511,13 @@ else
|
||||
echo ""
|
||||
echo -e "🟢 Your frontend is running on http://localhost:3301"
|
||||
echo ""
|
||||
echo "ℹ️ By default, retention period is set to 7 days for logs and traces, and 30 days for metrics."
|
||||
echo -e "To change this, navigate to the General tab on the Settings page of SigNoz UI. For more details, refer to https://signoz.io/docs/userguide/retention-period \n"
|
||||
|
||||
echo "ℹ️ To bring down SigNoz and clean volumes : $sudo_cmd docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml down -v"
|
||||
|
||||
echo ""
|
||||
echo "+++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo ""
|
||||
echo "👉 Need help in Getting Started?"
|
||||
echo "👉 Need help Getting Started?"
|
||||
echo -e "Join us on Slack https://signoz.io/slack"
|
||||
echo ""
|
||||
echo -e "\n📨 Please share your email to receive support & updates about SigNoz!"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.18-buster AS builder
|
||||
FROM golang:1.17-buster AS builder
|
||||
|
||||
# LD_FLAGS is passed as argument from Makefile. It will be empty, if no argument passed
|
||||
ARG LD_FLAGS
|
||||
|
||||
@@ -8,23 +8,17 @@ import (
|
||||
"go.signoz.io/signoz/ee/query-service/interfaces"
|
||||
"go.signoz.io/signoz/ee/query-service/license"
|
||||
baseapp "go.signoz.io/signoz/pkg/query-service/app"
|
||||
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
|
||||
baseint "go.signoz.io/signoz/pkg/query-service/interfaces"
|
||||
basemodel "go.signoz.io/signoz/pkg/query-service/model"
|
||||
rules "go.signoz.io/signoz/pkg/query-service/rules"
|
||||
"go.signoz.io/signoz/pkg/query-service/version"
|
||||
)
|
||||
|
||||
type APIHandlerOptions struct {
|
||||
DataConnector interfaces.DataConnector
|
||||
SkipConfig *basemodel.SkipConfig
|
||||
PreferDelta bool
|
||||
PreferSpanMetrics bool
|
||||
AppDao dao.ModelDao
|
||||
RulesManager *rules.Manager
|
||||
FeatureFlags baseint.FeatureLookup
|
||||
LicenseManager *license.Manager
|
||||
LogsParsingPipelineController *logparsingpipeline.LogParsingPipelineController
|
||||
DataConnector interfaces.DataConnector
|
||||
AppDao dao.ModelDao
|
||||
RulesManager *rules.Manager
|
||||
FeatureFlags baseint.FeatureLookup
|
||||
LicenseManager *license.Manager
|
||||
}
|
||||
|
||||
type APIHandler struct {
|
||||
@@ -36,15 +30,10 @@ type APIHandler struct {
|
||||
func NewAPIHandler(opts APIHandlerOptions) (*APIHandler, error) {
|
||||
|
||||
baseHandler, err := baseapp.NewAPIHandler(baseapp.APIHandlerOpts{
|
||||
Reader: opts.DataConnector,
|
||||
SkipConfig: opts.SkipConfig,
|
||||
PerferDelta: opts.PreferDelta,
|
||||
PreferSpanMetrics: opts.PreferSpanMetrics,
|
||||
AppDao: opts.AppDao,
|
||||
RuleManager: opts.RulesManager,
|
||||
FeatureFlags: opts.FeatureFlags,
|
||||
LogsParsingPipelineController: opts.LogsParsingPipelineController,
|
||||
})
|
||||
Reader: opts.DataConnector,
|
||||
AppDao: opts.AppDao,
|
||||
RuleManager: opts.RulesManager,
|
||||
FeatureFlags: opts.FeatureFlags})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -79,75 +68,64 @@ func (ah *APIHandler) CheckFeature(f string) bool {
|
||||
}
|
||||
|
||||
// RegisterRoutes registers routes for this handler on the given router
|
||||
func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *baseapp.AuthMiddleware) {
|
||||
func (ah *APIHandler) RegisterRoutes(router *mux.Router) {
|
||||
// note: add ee override methods first
|
||||
|
||||
// routes available only in ee version
|
||||
router.HandleFunc("/api/v1/licenses",
|
||||
am.AdminAccess(ah.listLicenses)).
|
||||
baseapp.AdminAccess(ah.listLicenses)).
|
||||
Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/api/v1/licenses",
|
||||
am.AdminAccess(ah.applyLicense)).
|
||||
baseapp.AdminAccess(ah.applyLicense)).
|
||||
Methods(http.MethodPost)
|
||||
|
||||
router.HandleFunc("/api/v1/featureFlags",
|
||||
am.OpenAccess(ah.getFeatureFlags)).
|
||||
baseapp.OpenAccess(ah.getFeatureFlags)).
|
||||
Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/api/v1/loginPrecheck",
|
||||
am.OpenAccess(ah.precheckLogin)).
|
||||
baseapp.OpenAccess(ah.precheckLogin)).
|
||||
Methods(http.MethodGet)
|
||||
|
||||
// paid plans specific routes
|
||||
router.HandleFunc("/api/v1/complete/saml",
|
||||
am.OpenAccess(ah.receiveSAML)).
|
||||
baseapp.OpenAccess(ah.receiveSAML)).
|
||||
Methods(http.MethodPost)
|
||||
|
||||
router.HandleFunc("/api/v1/complete/google",
|
||||
am.OpenAccess(ah.receiveGoogleAuth)).
|
||||
baseapp.OpenAccess(ah.receiveGoogleAuth)).
|
||||
Methods(http.MethodGet)
|
||||
|
||||
|
||||
router.HandleFunc("/api/v1/orgs/{orgId}/domains",
|
||||
am.AdminAccess(ah.listDomainsByOrg)).
|
||||
baseapp.AdminAccess(ah.listDomainsByOrg)).
|
||||
Methods(http.MethodGet)
|
||||
|
||||
router.HandleFunc("/api/v1/domains",
|
||||
am.AdminAccess(ah.postDomain)).
|
||||
baseapp.AdminAccess(ah.postDomain)).
|
||||
Methods(http.MethodPost)
|
||||
|
||||
router.HandleFunc("/api/v1/domains/{id}",
|
||||
am.AdminAccess(ah.putDomain)).
|
||||
baseapp.AdminAccess(ah.putDomain)).
|
||||
Methods(http.MethodPut)
|
||||
|
||||
router.HandleFunc("/api/v1/domains/{id}",
|
||||
am.AdminAccess(ah.deleteDomain)).
|
||||
baseapp.AdminAccess(ah.deleteDomain)).
|
||||
Methods(http.MethodDelete)
|
||||
|
||||
// base overrides
|
||||
router.HandleFunc("/api/v1/version", am.OpenAccess(ah.getVersion)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/invite/{token}", am.OpenAccess(ah.getInvite)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/register", am.OpenAccess(ah.registerUser)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/login", am.OpenAccess(ah.loginUser)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/traces/{traceId}", am.ViewAccess(ah.searchTraces)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v2/metrics/query_range", am.ViewAccess(ah.queryRangeMetricsV2)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/version", baseapp.OpenAccess(ah.getVersion)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/invite/{token}", baseapp.OpenAccess(ah.getInvite)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/register", baseapp.OpenAccess(ah.registerUser)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/login", baseapp.OpenAccess(ah.loginUser)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/traces/{traceId}", baseapp.ViewAccess(ah.searchTraces)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v2/metrics/query_range", baseapp.ViewAccess(ah.queryRangeMetricsV2)).Methods(http.MethodPost)
|
||||
|
||||
// PAT APIs
|
||||
router.HandleFunc("/api/v1/pat", am.OpenAccess(ah.createPAT)).Methods(http.MethodPost)
|
||||
router.HandleFunc("/api/v1/pat", am.OpenAccess(ah.getPATs)).Methods(http.MethodGet)
|
||||
router.HandleFunc("/api/v1/pat/{id}", am.OpenAccess(ah.deletePAT)).Methods(http.MethodDelete)
|
||||
|
||||
ah.APIHandler.RegisterRoutes(router, am)
|
||||
ah.APIHandler.RegisterRoutes(router)
|
||||
|
||||
}
|
||||
|
||||
func (ah *APIHandler) getVersion(w http.ResponseWriter, r *http.Request) {
|
||||
version := version.GetVersion()
|
||||
versionResponse := basemodel.GetVersionResponse{
|
||||
Version: version,
|
||||
EE: "Y",
|
||||
SetupCompleted: ah.SetupCompleted,
|
||||
}
|
||||
|
||||
ah.WriteJSON(w, r, versionResponse)
|
||||
ah.WriteJSON(w, r, map[string]string{"version": version, "ee": "Y"})
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"go.signoz.io/signoz/ee/query-service/constants"
|
||||
"go.signoz.io/signoz/ee/query-service/model"
|
||||
@@ -88,16 +87,9 @@ func (ah *APIHandler) registerUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// get invite object
|
||||
invite, err := baseauth.ValidateInvite(ctx, req)
|
||||
if err != nil {
|
||||
if err != nil || invite == nil {
|
||||
zap.S().Errorf("failed to validate invite token", err)
|
||||
RespondError(w, model.BadRequest(err), nil)
|
||||
return
|
||||
}
|
||||
|
||||
if invite == nil {
|
||||
zap.S().Errorf("failed to validate invite token: it is either empty or invalid", err)
|
||||
RespondError(w, model.BadRequest(basemodel.ErrSignupFailed{}), nil)
|
||||
return
|
||||
}
|
||||
|
||||
// get auth domain from email domain
|
||||
@@ -198,7 +190,7 @@ func handleSsoError(w http.ResponseWriter, r *http.Request, redirectURL string)
|
||||
}
|
||||
|
||||
// receiveGoogleAuth completes google OAuth response and forwards a request
|
||||
// to front-end to sign user in
|
||||
// to front-end to sign user in
|
||||
func (ah *APIHandler) receiveGoogleAuth(w http.ResponseWriter, r *http.Request) {
|
||||
redirectUri := constants.GetDefaultSiteURL()
|
||||
ctx := context.Background()
|
||||
@@ -229,15 +221,15 @@ func (ah *APIHandler) receiveGoogleAuth(w http.ResponseWriter, r *http.Request)
|
||||
// upgrade redirect url from the relay state for better accuracy
|
||||
redirectUri = fmt.Sprintf("%s://%s%s", parsedState.Scheme, parsedState.Host, "/login")
|
||||
|
||||
// fetch domain by parsing relay state.
|
||||
// fetch domain by parsing relay state.
|
||||
domain, err := ah.AppDao().GetDomainFromSsoResponse(ctx, parsedState)
|
||||
if err != nil {
|
||||
handleSsoError(w, r, redirectUri)
|
||||
return
|
||||
}
|
||||
|
||||
// now that we have domain, use domain to fetch sso settings.
|
||||
// prepare google callback handler using parsedState -
|
||||
// now that we have domain, use domain to fetch sso settings.
|
||||
// prepare google callback handler using parsedState -
|
||||
// which contains redirect URL (front-end endpoint)
|
||||
callbackHandler, err := domain.PrepareGoogleOAuthProvider(parsedState)
|
||||
|
||||
@@ -247,7 +239,7 @@ func (ah *APIHandler) receiveGoogleAuth(w http.ResponseWriter, r *http.Request)
|
||||
handleSsoError(w, r, redirectUri)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
nextPage, err := ah.AppDao().PrepareSsoRedirect(ctx, redirectUri, identity.Email)
|
||||
if err != nil {
|
||||
zap.S().Errorf("[receiveGoogleAuth] failed to generate redirect URI after successful login ", domain.String(), zap.Error(err))
|
||||
@@ -258,12 +250,15 @@ func (ah *APIHandler) receiveGoogleAuth(w http.ResponseWriter, r *http.Request)
|
||||
http.Redirect(w, r, nextPage, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// receiveSAML completes a SAML request and gets user logged in
|
||||
func (ah *APIHandler) receiveSAML(w http.ResponseWriter, r *http.Request) {
|
||||
// this is the source url that initiated the login request
|
||||
redirectUri := constants.GetDefaultSiteURL()
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
if !ah.CheckFeature(model.SSO) {
|
||||
zap.S().Errorf("[receiveSAML] sso requested but feature unavailable %s in org domain %s", model.SSO)
|
||||
http.Redirect(w, r, fmt.Sprintf("%s?ssoerror=%s", redirectUri, "feature unavailable, please upgrade your billing plan to access this feature"), http.StatusMovedPermanently)
|
||||
@@ -292,13 +287,13 @@ func (ah *APIHandler) receiveSAML(w http.ResponseWriter, r *http.Request) {
|
||||
// upgrade redirect url from the relay state for better accuracy
|
||||
redirectUri = fmt.Sprintf("%s://%s%s", parsedState.Scheme, parsedState.Host, "/login")
|
||||
|
||||
// fetch domain by parsing relay state.
|
||||
// fetch domain by parsing relay state.
|
||||
domain, err := ah.AppDao().GetDomainFromSsoResponse(ctx, parsedState)
|
||||
if err != nil {
|
||||
handleSsoError(w, r, redirectUri)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
sp, err := domain.PrepareSamlRequest(parsedState)
|
||||
if err != nil {
|
||||
zap.S().Errorf("[receiveSAML] failed to prepare saml request for domain (%s): %v", domain.String(), err)
|
||||
@@ -332,6 +327,6 @@ func (ah *APIHandler) receiveSAML(w http.ResponseWriter, r *http.Request) {
|
||||
handleSsoError(w, r, redirectUri)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
http.Redirect(w, r, nextPage, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
@@ -2,23 +2,9 @@ package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
basemodel "go.signoz.io/signoz/pkg/query-service/model"
|
||||
)
|
||||
|
||||
func (ah *APIHandler) getFeatureFlags(w http.ResponseWriter, r *http.Request) {
|
||||
featureSet, err := ah.FF().GetFeatureFlags()
|
||||
if err != nil {
|
||||
ah.HandleError(w, err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if ah.opts.PreferSpanMetrics {
|
||||
for idx := range featureSet {
|
||||
feature := &featureSet[idx]
|
||||
if feature.Name == basemodel.UseSpanMetrics {
|
||||
featureSet[idx].Active = true
|
||||
}
|
||||
}
|
||||
}
|
||||
featureSet := ah.FF().GetFeatureFlags()
|
||||
ah.Respond(w, featureSet)
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"go.signoz.io/signoz/ee/query-service/model"
|
||||
"go.signoz.io/signoz/pkg/query-service/auth"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func generatePATToken() string {
|
||||
// Generate a 32-byte random token.
|
||||
token := make([]byte, 32)
|
||||
rand.Read(token)
|
||||
// Encode the token in base64.
|
||||
encodedToken := base64.StdEncoding.EncodeToString(token)
|
||||
return encodedToken
|
||||
}
|
||||
|
||||
func (ah *APIHandler) createPAT(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.Background()
|
||||
|
||||
req := model.PAT{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
RespondError(w, model.BadRequest(err), nil)
|
||||
return
|
||||
}
|
||||
user, err := auth.GetUserFromRequest(r)
|
||||
if err != nil {
|
||||
RespondError(w, &model.ApiError{
|
||||
Typ: model.ErrorUnauthorized,
|
||||
Err: err,
|
||||
}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// All the PATs are associated with the user creating the PAT. Hence, the permissions
|
||||
// associated with the PAT is also equivalent to that of the user.
|
||||
req.UserID = user.Id
|
||||
req.CreatedAt = time.Now().Unix()
|
||||
req.Token = generatePATToken()
|
||||
|
||||
zap.S().Debugf("Got PAT request: %+v", req)
|
||||
if apierr := ah.AppDao().CreatePAT(ctx, &req); apierr != nil {
|
||||
RespondError(w, apierr, nil)
|
||||
return
|
||||
}
|
||||
|
||||
ah.Respond(w, &req)
|
||||
}
|
||||
|
||||
func (ah *APIHandler) getPATs(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.Background()
|
||||
user, err := auth.GetUserFromRequest(r)
|
||||
if err != nil {
|
||||
RespondError(w, &model.ApiError{
|
||||
Typ: model.ErrorUnauthorized,
|
||||
Err: err,
|
||||
}, nil)
|
||||
return
|
||||
}
|
||||
zap.S().Infof("Get PATs for user: %+v", user.Id)
|
||||
pats, apierr := ah.AppDao().ListPATs(ctx, user.Id)
|
||||
if apierr != nil {
|
||||
RespondError(w, apierr, nil)
|
||||
return
|
||||
}
|
||||
ah.Respond(w, pats)
|
||||
}
|
||||
|
||||
func (ah *APIHandler) deletePAT(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.Background()
|
||||
id := mux.Vars(r)["id"]
|
||||
user, err := auth.GetUserFromRequest(r)
|
||||
if err != nil {
|
||||
RespondError(w, &model.ApiError{
|
||||
Typ: model.ErrorUnauthorized,
|
||||
Err: err,
|
||||
}, nil)
|
||||
return
|
||||
}
|
||||
pat, apierr := ah.AppDao().GetPATByID(ctx, id)
|
||||
if apierr != nil {
|
||||
RespondError(w, apierr, nil)
|
||||
return
|
||||
}
|
||||
if pat.UserID != user.Id {
|
||||
RespondError(w, &model.ApiError{
|
||||
Typ: model.ErrorUnauthorized,
|
||||
Err: fmt.Errorf("unauthorized PAT delete request"),
|
||||
}, nil)
|
||||
return
|
||||
}
|
||||
zap.S().Debugf("Delete PAT with id: %+v", id)
|
||||
if apierr := ah.AppDao().DeletePAT(ctx, id); apierr != nil {
|
||||
RespondError(w, apierr, nil)
|
||||
return
|
||||
}
|
||||
ah.Respond(w, map[string]string{"data": "pat deleted successfully"})
|
||||
}
|
||||
@@ -22,24 +22,14 @@ import (
|
||||
"go.signoz.io/signoz/ee/query-service/app/db"
|
||||
"go.signoz.io/signoz/ee/query-service/dao"
|
||||
"go.signoz.io/signoz/ee/query-service/interfaces"
|
||||
baseInterface "go.signoz.io/signoz/pkg/query-service/interfaces"
|
||||
|
||||
licensepkg "go.signoz.io/signoz/ee/query-service/license"
|
||||
"go.signoz.io/signoz/ee/query-service/usage"
|
||||
|
||||
"go.signoz.io/signoz/pkg/query-service/agentConf"
|
||||
baseapp "go.signoz.io/signoz/pkg/query-service/app"
|
||||
"go.signoz.io/signoz/pkg/query-service/app/dashboards"
|
||||
baseexplorer "go.signoz.io/signoz/pkg/query-service/app/explorer"
|
||||
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
|
||||
"go.signoz.io/signoz/pkg/query-service/app/opamp"
|
||||
opAmpModel "go.signoz.io/signoz/pkg/query-service/app/opamp/model"
|
||||
baseauth "go.signoz.io/signoz/pkg/query-service/auth"
|
||||
baseconst "go.signoz.io/signoz/pkg/query-service/constants"
|
||||
"go.signoz.io/signoz/pkg/query-service/healthcheck"
|
||||
basealm "go.signoz.io/signoz/pkg/query-service/integrations/alertManager"
|
||||
baseint "go.signoz.io/signoz/pkg/query-service/interfaces"
|
||||
basemodel "go.signoz.io/signoz/pkg/query-service/model"
|
||||
pqle "go.signoz.io/signoz/pkg/query-service/pqlEngine"
|
||||
rules "go.signoz.io/signoz/pkg/query-service/rules"
|
||||
"go.signoz.io/signoz/pkg/query-service/telemetry"
|
||||
@@ -47,18 +37,13 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const AppDbEngine = "sqlite"
|
||||
|
||||
type ServerOptions struct {
|
||||
PromConfigPath string
|
||||
SkipTopLvlOpsPath string
|
||||
HTTPHostPort string
|
||||
PrivateHostPort string
|
||||
PromConfigPath string
|
||||
HTTPHostPort string
|
||||
PrivateHostPort string
|
||||
// alert specific params
|
||||
DisableRules bool
|
||||
RuleRepoURL string
|
||||
PreferDelta bool
|
||||
PreferSpanMetrics bool
|
||||
DisableRules bool
|
||||
RuleRepoURL string
|
||||
}
|
||||
|
||||
// Server runs HTTP api service
|
||||
@@ -79,9 +64,6 @@ type Server struct {
|
||||
// feature flags
|
||||
featureLookup baseint.FeatureLookup
|
||||
|
||||
// Usage manager
|
||||
usageManager *usage.Manager
|
||||
|
||||
unavailableChannel chan healthcheck.Status
|
||||
}
|
||||
|
||||
@@ -98,8 +80,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
baseexplorer.InitWithDSN(baseconst.RELATIONAL_DATASOURCE_PATH)
|
||||
|
||||
localDB, err := dashboards.InitDB(baseconst.RELATIONAL_DATASOURCE_PATH)
|
||||
|
||||
if err != nil {
|
||||
@@ -126,15 +106,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
||||
go qb.Start(readerReady)
|
||||
reader = qb
|
||||
} else {
|
||||
return nil, fmt.Errorf("storage type: %s is not supported in query service", storage)
|
||||
}
|
||||
skipConfig := &basemodel.SkipConfig{}
|
||||
if serverOptions.SkipTopLvlOpsPath != "" {
|
||||
// read skip config
|
||||
skipConfig, err = basemodel.ReadSkipConfig(serverOptions.SkipTopLvlOpsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("Storage type: %s is not supported in query service", storage)
|
||||
}
|
||||
|
||||
<-readerReady
|
||||
@@ -143,30 +115,12 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
||||
serverOptions.RuleRepoURL,
|
||||
localDB,
|
||||
reader,
|
||||
serverOptions.DisableRules,
|
||||
lm)
|
||||
serverOptions.DisableRules)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// initiate opamp
|
||||
_, err = opAmpModel.InitDB(baseconst.RELATIONAL_DATASOURCE_PATH)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// initiate agent config handler
|
||||
if err := agentConf.Initiate(localDB, AppDbEngine); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ingestion pipelines manager
|
||||
logParsingPipelineController, err := logparsingpipeline.NewLogParsingPipelinesController(localDB, "sqlite")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// start the usagemanager
|
||||
usageManager, err := usage.New("sqlite", localDB, lm.GetRepo(), reader.GetConn())
|
||||
if err != nil {
|
||||
@@ -180,15 +134,11 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
||||
telemetry.GetInstance().SetReader(reader)
|
||||
|
||||
apiOpts := api.APIHandlerOptions{
|
||||
DataConnector: reader,
|
||||
SkipConfig: skipConfig,
|
||||
PreferDelta: serverOptions.PreferDelta,
|
||||
PreferSpanMetrics: serverOptions.PreferSpanMetrics,
|
||||
AppDao: modelDao,
|
||||
RulesManager: rm,
|
||||
FeatureFlags: lm,
|
||||
LicenseManager: lm,
|
||||
LogsParsingPipelineController: logParsingPipelineController,
|
||||
DataConnector: reader,
|
||||
AppDao: modelDao,
|
||||
RulesManager: rm,
|
||||
FeatureFlags: lm,
|
||||
LicenseManager: lm,
|
||||
}
|
||||
|
||||
apiHandler, err := api.NewAPIHandler(apiOpts)
|
||||
@@ -202,7 +152,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
|
||||
ruleManager: rm,
|
||||
serverOptions: serverOptions,
|
||||
unavailableChannel: make(chan healthcheck.Status),
|
||||
usageManager: usageManager,
|
||||
}
|
||||
|
||||
httpServer, err := s.createPublicServer(apiHandler)
|
||||
@@ -238,7 +187,7 @@ func (s *Server) createPrivateServer(apiHandler *api.APIHandler) (*http.Server,
|
||||
// ip here for alert manager
|
||||
AllowedOrigins: []string{"*"},
|
||||
AllowedMethods: []string{"GET", "DELETE", "POST", "PUT", "PATCH"},
|
||||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "SIGNOZ-API-KEY"},
|
||||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type"},
|
||||
})
|
||||
|
||||
handler := c.Handler(r)
|
||||
@@ -253,33 +202,13 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler) (*http.Server, e
|
||||
|
||||
r := mux.NewRouter()
|
||||
|
||||
getUserFromRequest := func(r *http.Request) (*basemodel.UserPayload, error) {
|
||||
patToken := r.Header.Get("SIGNOZ-API-KEY")
|
||||
if len(patToken) > 0 {
|
||||
zap.S().Debugf("Received a non-zero length PAT token")
|
||||
ctx := context.Background()
|
||||
dao := apiHandler.AppDao()
|
||||
|
||||
user, err := dao.GetUserByPAT(ctx, patToken)
|
||||
if err == nil && user != nil {
|
||||
zap.S().Debugf("Found valid PAT user: %+v", user)
|
||||
return user, nil
|
||||
}
|
||||
if err != nil {
|
||||
zap.S().Debugf("Error while getting user for PAT: %+v", err)
|
||||
}
|
||||
}
|
||||
return baseauth.GetUserFromRequest(r)
|
||||
}
|
||||
am := baseapp.NewAuthMiddleware(getUserFromRequest)
|
||||
r.Use(setTimeoutMiddleware)
|
||||
r.Use(s.analyticsMiddleware)
|
||||
r.Use(loggingMiddleware)
|
||||
|
||||
apiHandler.RegisterRoutes(r, am)
|
||||
apiHandler.RegisterMetricsRoutes(r, am)
|
||||
apiHandler.RegisterLogsRoutes(r, am)
|
||||
apiHandler.RegisterQueryRangeV3Routes(r, am)
|
||||
apiHandler.RegisterRoutes(r)
|
||||
apiHandler.RegisterMetricsRoutes(r)
|
||||
apiHandler.RegisterLogsRoutes(r)
|
||||
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
@@ -303,7 +232,7 @@ func loggingMiddleware(next http.Handler) http.Handler {
|
||||
path, _ := route.GetPathTemplate()
|
||||
startTime := time.Now()
|
||||
next.ServeHTTP(w, r)
|
||||
zap.L().Info(path+"\ttimeTaken:"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path))
|
||||
zap.S().Info(path, "\ttimeTaken: ", time.Now().Sub(startTime))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -315,7 +244,7 @@ func loggingMiddlewarePrivate(next http.Handler) http.Handler {
|
||||
path, _ := route.GetPathTemplate()
|
||||
startTime := time.Now()
|
||||
next.ServeHTTP(w, r)
|
||||
zap.L().Info(path+"\tprivatePort: true \ttimeTaken"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path), zap.Bool("tprivatePort", true))
|
||||
zap.S().Info(path, "\tprivatePort: true", "\ttimeTaken: ", time.Now().Sub(startTime))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -342,9 +271,8 @@ func (lrw *loggingResponseWriter) Flush() {
|
||||
|
||||
func extractDashboardMetaData(path string, r *http.Request) (map[string]interface{}, bool) {
|
||||
pathToExtractBodyFrom := "/api/v2/metrics/query_range"
|
||||
|
||||
var requestBody map[string]interface{}
|
||||
data := map[string]interface{}{}
|
||||
var postData *basemodel.QueryRangeParamsV2
|
||||
|
||||
if path == pathToExtractBodyFrom && (r.Method == "POST") {
|
||||
if r.Body != nil {
|
||||
@@ -354,8 +282,7 @@ func extractDashboardMetaData(path string, r *http.Request) (map[string]interfac
|
||||
}
|
||||
r.Body.Close() // must close
|
||||
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
json.Unmarshal(bodyBytes, &postData)
|
||||
|
||||
json.Unmarshal(bodyBytes, &requestBody)
|
||||
} else {
|
||||
return nil, false
|
||||
}
|
||||
@@ -364,20 +291,31 @@ func extractDashboardMetaData(path string, r *http.Request) (map[string]interfac
|
||||
return nil, false
|
||||
}
|
||||
|
||||
signozMetricNotFound := false
|
||||
compositeMetricQuery, compositeMetricQueryExists := requestBody["compositeMetricQuery"]
|
||||
|
||||
if postData != nil {
|
||||
signozMetricNotFound = telemetry.GetInstance().CheckSigNozMetricsV2(postData.CompositeMetricQuery)
|
||||
signozMetricFound := false
|
||||
|
||||
if postData.CompositeMetricQuery != nil {
|
||||
data["queryType"] = postData.CompositeMetricQuery.QueryType
|
||||
data["panelType"] = postData.CompositeMetricQuery.PanelType
|
||||
if compositeMetricQueryExists {
|
||||
compositeMetricQueryMap := compositeMetricQuery.(map[string]interface{})
|
||||
|
||||
signozMetricFound = telemetry.GetInstance().CheckSigNozMetrics(compositeMetricQueryMap)
|
||||
|
||||
queryType, queryTypeExists := compositeMetricQueryMap["queryType"]
|
||||
if queryTypeExists {
|
||||
data["queryType"] = queryType
|
||||
}
|
||||
panelType, panelTypeExists := compositeMetricQueryMap["panelType"]
|
||||
if panelTypeExists {
|
||||
data["panelType"] = panelType
|
||||
}
|
||||
|
||||
data["datasource"] = postData.DataSource
|
||||
}
|
||||
|
||||
if signozMetricNotFound {
|
||||
datasource, datasourceExists := requestBody["dataSource"]
|
||||
if datasourceExists {
|
||||
data["datasource"] = datasource
|
||||
}
|
||||
|
||||
if !signozMetricFound {
|
||||
telemetry.GetInstance().AddActiveMetricsUser()
|
||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_DASHBOARDS_METADATA, data, true)
|
||||
}
|
||||
@@ -431,7 +369,7 @@ func setTimeoutMiddleware(next http.Handler) http.Handler {
|
||||
// check if route is not excluded
|
||||
url := r.URL.Path
|
||||
if _, ok := baseconst.TimeoutExcludedRoutes[url]; !ok {
|
||||
ctx, cancel = context.WithTimeout(r.Context(), baseconst.ContextTimeout)
|
||||
ctx, cancel = context.WithTimeout(r.Context(), baseconst.ContextTimeout*time.Second)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
@@ -517,7 +455,7 @@ func (s *Server) Start() error {
|
||||
if port, err := utils.GetPort(s.privateConn.Addr()); err == nil {
|
||||
privatePort = port
|
||||
}
|
||||
|
||||
fmt.Println("starting private http")
|
||||
go func() {
|
||||
zap.S().Info("Starting Private HTTP server", zap.Int("port", privatePort), zap.String("addr", s.serverOptions.PrivateHostPort))
|
||||
|
||||
@@ -533,40 +471,6 @@ func (s *Server) Start() error {
|
||||
|
||||
}()
|
||||
|
||||
go func() {
|
||||
zap.S().Info("Starting OpAmp Websocket server", zap.String("addr", baseconst.OpAmpWsEndpoint))
|
||||
err := opamp.InitalizeServer(baseconst.OpAmpWsEndpoint, &opAmpModel.AllAgents)
|
||||
if err != nil {
|
||||
zap.S().Info("opamp ws server failed to start", err)
|
||||
s.unavailableChannel <- healthcheck.Unavailable
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Stop() error {
|
||||
if s.httpServer != nil {
|
||||
if err := s.httpServer.Shutdown(context.Background()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if s.privateHTTP != nil {
|
||||
if err := s.privateHTTP.Shutdown(context.Background()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
opamp.StopServer()
|
||||
|
||||
if s.ruleManager != nil {
|
||||
s.ruleManager.Stop()
|
||||
}
|
||||
|
||||
// stop usage manager
|
||||
s.usageManager.Stop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -576,8 +480,7 @@ func makeRulesManager(
|
||||
ruleRepoURL string,
|
||||
db *sqlx.DB,
|
||||
ch baseint.Reader,
|
||||
disableRules bool,
|
||||
fm baseInterface.FeatureLookup) (*rules.Manager, error) {
|
||||
disableRules bool) (*rules.Manager, error) {
|
||||
|
||||
// create engine
|
||||
pqle, err := pqle.FromConfigPath(promConfigPath)
|
||||
@@ -604,7 +507,6 @@ func makeRulesManager(
|
||||
Context: context.Background(),
|
||||
Logger: nil,
|
||||
DisableRules: disableRules,
|
||||
FeatureFlags: fm,
|
||||
}
|
||||
|
||||
// create Manager
|
||||
|
||||
@@ -3,7 +3,6 @@ package dao
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.signoz.io/signoz/ee/query-service/model"
|
||||
@@ -25,7 +24,7 @@ type ModelDao interface {
|
||||
CanUsePassword(ctx context.Context, email string) (bool, basemodel.BaseApiError)
|
||||
PrepareSsoRedirect(ctx context.Context, redirectUri, email string) (redirectURL string, apierr basemodel.BaseApiError)
|
||||
GetDomainFromSsoResponse(ctx context.Context, relayState *url.URL) (*model.OrgDomain, error)
|
||||
|
||||
|
||||
// org domain (auth domains) CRUD ops
|
||||
ListDomains(ctx context.Context, orgId string) ([]model.OrgDomain, basemodel.BaseApiError)
|
||||
GetDomain(ctx context.Context, id uuid.UUID) (*model.OrgDomain, basemodel.BaseApiError)
|
||||
@@ -33,11 +32,4 @@ type ModelDao interface {
|
||||
UpdateDomain(ctx context.Context, domain *model.OrgDomain) basemodel.BaseApiError
|
||||
DeleteDomain(ctx context.Context, id uuid.UUID) basemodel.BaseApiError
|
||||
GetDomainByEmail(ctx context.Context, email string) (*model.OrgDomain, basemodel.BaseApiError)
|
||||
|
||||
CreatePAT(ctx context.Context, p *model.PAT) basemodel.BaseApiError
|
||||
GetPAT(ctx context.Context, pat string) (*model.PAT, basemodel.BaseApiError)
|
||||
GetPATByID(ctx context.Context, id string) (*model.PAT, basemodel.BaseApiError)
|
||||
GetUserByPAT(ctx context.Context, token string) (*basemodel.UserPayload, basemodel.BaseApiError)
|
||||
ListPATs(ctx context.Context, userID string) ([]model.PAT, basemodel.BaseApiError)
|
||||
DeletePAT(ctx context.Context, id string) basemodel.BaseApiError
|
||||
}
|
||||
|
||||
@@ -48,17 +48,7 @@ func InitDB(dataSourceName string) (*modelDao, error) {
|
||||
updated_at INTEGER,
|
||||
data TEXT NOT NULL,
|
||||
FOREIGN KEY(org_id) REFERENCES organizations(id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS personal_access_tokens (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id TEXT NOT NULL,
|
||||
token TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
expires_at INTEGER NOT NULL,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||
);
|
||||
`
|
||||
);`
|
||||
|
||||
_, err = m.DB().Exec(table_schema)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"go.signoz.io/signoz/ee/query-service/model"
|
||||
basemodel "go.signoz.io/signoz/pkg/query-service/model"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (m *modelDao) CreatePAT(ctx context.Context, p *model.PAT) basemodel.BaseApiError {
|
||||
_, err := m.DB().ExecContext(ctx,
|
||||
"INSERT INTO personal_access_tokens (user_id, token, name, created_at, expires_at) VALUES ($1, $2, $3, $4, $5)",
|
||||
p.UserID,
|
||||
p.Token,
|
||||
p.Name,
|
||||
p.CreatedAt,
|
||||
p.ExpiresAt)
|
||||
if err != nil {
|
||||
zap.S().Errorf("Failed to insert PAT in db, err: %v", zap.Error(err))
|
||||
return model.InternalError(fmt.Errorf("PAT insertion failed"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *modelDao) ListPATs(ctx context.Context, userID string) ([]model.PAT, basemodel.BaseApiError) {
|
||||
pats := []model.PAT{}
|
||||
|
||||
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE user_id=?;`, userID); err != nil {
|
||||
zap.S().Errorf("Failed to fetch PATs for user: %s, err: %v", userID, zap.Error(err))
|
||||
return nil, model.InternalError(fmt.Errorf("failed to fetch PATs"))
|
||||
}
|
||||
return pats, nil
|
||||
}
|
||||
|
||||
func (m *modelDao) DeletePAT(ctx context.Context, id string) basemodel.BaseApiError {
|
||||
_, err := m.DB().ExecContext(ctx, `DELETE from personal_access_tokens where id=?;`, id)
|
||||
if err != nil {
|
||||
zap.S().Errorf("Failed to delete PAT, err: %v", zap.Error(err))
|
||||
return model.InternalError(fmt.Errorf("failed to delete PAT"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *modelDao) GetPAT(ctx context.Context, token string) (*model.PAT, basemodel.BaseApiError) {
|
||||
pats := []model.PAT{}
|
||||
|
||||
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE token=?;`, token); err != nil {
|
||||
return nil, model.InternalError(fmt.Errorf("failed to fetch PAT"))
|
||||
}
|
||||
|
||||
if len(pats) != 1 {
|
||||
return nil, &model.ApiError{
|
||||
Typ: model.ErrorInternal,
|
||||
Err: fmt.Errorf("found zero or multiple PATs with same token, %s", token),
|
||||
}
|
||||
}
|
||||
|
||||
return &pats[0], nil
|
||||
}
|
||||
|
||||
func (m *modelDao) GetPATByID(ctx context.Context, id string) (*model.PAT, basemodel.BaseApiError) {
|
||||
pats := []model.PAT{}
|
||||
|
||||
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE id=?;`, id); err != nil {
|
||||
return nil, model.InternalError(fmt.Errorf("failed to fetch PAT"))
|
||||
}
|
||||
|
||||
if len(pats) != 1 {
|
||||
return nil, &model.ApiError{
|
||||
Typ: model.ErrorInternal,
|
||||
Err: fmt.Errorf("found zero or multiple PATs with same token"),
|
||||
}
|
||||
}
|
||||
|
||||
return &pats[0], nil
|
||||
}
|
||||
|
||||
func (m *modelDao) GetUserByPAT(ctx context.Context, token string) (*basemodel.UserPayload, basemodel.BaseApiError) {
|
||||
users := []basemodel.UserPayload{}
|
||||
|
||||
query := `SELECT
|
||||
u.id,
|
||||
u.name,
|
||||
u.email,
|
||||
u.password,
|
||||
u.created_at,
|
||||
u.profile_picture_url,
|
||||
u.org_id,
|
||||
u.group_id
|
||||
FROM users u, personal_access_tokens p
|
||||
WHERE u.id = p.user_id and p.token=?;`
|
||||
|
||||
if err := m.DB().Select(&users, query, token); err != nil {
|
||||
return nil, model.InternalError(fmt.Errorf("failed to fetch user from PAT, err: %v", err))
|
||||
}
|
||||
|
||||
if len(users) != 1 {
|
||||
return nil, &model.ApiError{
|
||||
Typ: model.ErrorInternal,
|
||||
Err: fmt.Errorf("found zero or multiple users with same PAT token"),
|
||||
}
|
||||
}
|
||||
return &users[0], nil
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package license
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -10,7 +9,6 @@ import (
|
||||
|
||||
"go.signoz.io/signoz/ee/query-service/license/sqlite"
|
||||
"go.signoz.io/signoz/ee/query-service/model"
|
||||
basemodel "go.signoz.io/signoz/pkg/query-service/model"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -127,79 +125,3 @@ func (r *Repo) UpdatePlanDetails(ctx context.Context,
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repo) CreateFeature(req *basemodel.Feature) *basemodel.ApiError {
|
||||
|
||||
_, err := r.db.Exec(
|
||||
`INSERT INTO feature_status (name, active, usage, usage_limit, route)
|
||||
VALUES (?, ?, ?, ?, ?);`,
|
||||
req.Name, req.Active, req.Usage, req.UsageLimit, req.Route)
|
||||
if err != nil {
|
||||
return &basemodel.ApiError{Typ: basemodel.ErrorInternal, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repo) GetFeature(featureName string) (basemodel.Feature, error) {
|
||||
|
||||
var feature basemodel.Feature
|
||||
|
||||
err := r.db.Get(&feature,
|
||||
`SELECT * FROM feature_status WHERE name = ?;`, featureName)
|
||||
if err != nil {
|
||||
return feature, err
|
||||
}
|
||||
if feature.Name == "" {
|
||||
return feature, basemodel.ErrFeatureUnavailable{Key: featureName}
|
||||
}
|
||||
return feature, nil
|
||||
}
|
||||
|
||||
func (r *Repo) GetAllFeatures() ([]basemodel.Feature, error) {
|
||||
|
||||
var feature []basemodel.Feature
|
||||
|
||||
err := r.db.Select(&feature,
|
||||
`SELECT * FROM feature_status;`)
|
||||
if err != nil {
|
||||
return feature, err
|
||||
}
|
||||
|
||||
return feature, nil
|
||||
}
|
||||
|
||||
func (r *Repo) UpdateFeature(req basemodel.Feature) error {
|
||||
|
||||
_, err := r.db.Exec(
|
||||
`UPDATE feature_status SET active = ?, usage = ?, usage_limit = ?, route = ? WHERE name = ?;`,
|
||||
req.Active, req.Usage, req.UsageLimit, req.Route, req.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repo) InitFeatures(req basemodel.FeatureSet) error {
|
||||
// get a feature by name, if it doesn't exist, create it. If it does exist, update it.
|
||||
for _, feature := range req {
|
||||
currentFeature, err := r.GetFeature(feature.Name)
|
||||
if err != nil && err == sql.ErrNoRows {
|
||||
err := r.CreateFeature(&feature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
feature.Usage = currentFeature.Usage
|
||||
if feature.Usage >= feature.UsageLimit && feature.UsageLimit != -1 {
|
||||
feature.Active = false
|
||||
}
|
||||
err = r.UpdateFeature(feature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -96,11 +96,6 @@ func (lm *Manager) SetActive(l *model.License) {
|
||||
lm.activeFeatures = l.FeatureSet
|
||||
// set default features
|
||||
setDefaultFeatures(lm)
|
||||
|
||||
err := lm.InitFeatures(lm.activeFeatures)
|
||||
if err != nil {
|
||||
zap.S().Panicf("Couldn't activate features: %v", err)
|
||||
}
|
||||
if !lm.validatorRunning {
|
||||
// we want to make sure only one validator runs,
|
||||
// we already have lock() so good to go
|
||||
@@ -111,7 +106,9 @@ func (lm *Manager) SetActive(l *model.License) {
|
||||
}
|
||||
|
||||
func setDefaultFeatures(lm *Manager) {
|
||||
lm.activeFeatures = append(lm.activeFeatures, baseconstants.DEFAULT_FEATURE_SET...)
|
||||
for k, v := range baseconstants.DEFAULT_FEATURE_SET {
|
||||
lm.activeFeatures[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// LoadActiveLicense loads the most recent active license
|
||||
@@ -126,13 +123,8 @@ func (lm *Manager) LoadActiveLicense() error {
|
||||
} else {
|
||||
zap.S().Info("No active license found, defaulting to basic plan")
|
||||
// if no active license is found, we default to basic(free) plan with all default features
|
||||
lm.activeFeatures = model.BasicPlan
|
||||
lm.activeFeatures = basemodel.BasicPlan
|
||||
setDefaultFeatures(lm)
|
||||
err := lm.InitFeatures(lm.activeFeatures)
|
||||
if err != nil {
|
||||
zap.S().Error("Couldn't initialize features: ", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -299,31 +291,18 @@ func (lm *Manager) Activate(ctx context.Context, key string) (licenseResponse *m
|
||||
// CheckFeature will be internally used by backend routines
|
||||
// for feature gating
|
||||
func (lm *Manager) CheckFeature(featureKey string) error {
|
||||
feature, err := lm.repo.GetFeature(featureKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if feature.Active {
|
||||
return nil
|
||||
if value, ok := lm.activeFeatures[featureKey]; ok {
|
||||
if value {
|
||||
return nil
|
||||
}
|
||||
return basemodel.ErrFeatureUnavailable{Key: featureKey}
|
||||
}
|
||||
return basemodel.ErrFeatureUnavailable{Key: featureKey}
|
||||
}
|
||||
|
||||
// GetFeatureFlags returns current active features
|
||||
func (lm *Manager) GetFeatureFlags() (basemodel.FeatureSet, error) {
|
||||
return lm.repo.GetAllFeatures()
|
||||
}
|
||||
|
||||
func (lm *Manager) InitFeatures(features basemodel.FeatureSet) error {
|
||||
return lm.repo.InitFeatures(features)
|
||||
}
|
||||
|
||||
func (lm *Manager) UpdateFeatureFlag(feature basemodel.Feature) error {
|
||||
return lm.repo.UpdateFeature(feature)
|
||||
}
|
||||
|
||||
func (lm *Manager) GetFeatureFlag(key string) (basemodel.Feature, error) {
|
||||
return lm.repo.GetFeature(key)
|
||||
func (lm *Manager) GetFeatureFlags() basemodel.FeatureSet {
|
||||
return lm.activeFeatures
|
||||
}
|
||||
|
||||
// GetRepo return the license repo
|
||||
|
||||
@@ -2,7 +2,6 @@ package sqlite
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
@@ -34,19 +33,5 @@ func InitDB(db *sqlx.DB) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error in creating licenses table: %s", err.Error())
|
||||
}
|
||||
|
||||
table_schema = `CREATE TABLE IF NOT EXISTS feature_status (
|
||||
name TEXT PRIMARY KEY,
|
||||
active bool,
|
||||
usage INTEGER DEFAULT 0,
|
||||
usage_limit INTEGER DEFAULT 0,
|
||||
route TEXT
|
||||
);`
|
||||
|
||||
_, err = db.Exec(table_schema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error in creating feature_status table: %s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,78 +3,30 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||
"go.signoz.io/signoz/ee/query-service/app"
|
||||
"go.signoz.io/signoz/pkg/query-service/auth"
|
||||
"go.signoz.io/signoz/pkg/query-service/constants"
|
||||
baseconst "go.signoz.io/signoz/pkg/query-service/constants"
|
||||
"go.signoz.io/signoz/pkg/query-service/version"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
zapotlpencoder "github.com/SigNoz/zap_otlp/zap_otlp_encoder"
|
||||
zapotlpsync "github.com/SigNoz/zap_otlp/zap_otlp_sync"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
func initZapLog(enableQueryServiceLogOTLPExport bool) *zap.Logger {
|
||||
func initZapLog() *zap.Logger {
|
||||
config := zap.NewDevelopmentConfig()
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer stop()
|
||||
|
||||
config.EncoderConfig.EncodeDuration = zapcore.StringDurationEncoder
|
||||
otlpEncoder := zapotlpencoder.NewOTLPEncoder(config.EncoderConfig)
|
||||
consoleEncoder := zapcore.NewConsoleEncoder(config.EncoderConfig)
|
||||
defaultLogLevel := zapcore.DebugLevel
|
||||
config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
||||
config.EncoderConfig.TimeKey = "timestamp"
|
||||
config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
|
||||
res := resource.NewWithAttributes(
|
||||
semconv.SchemaURL,
|
||||
semconv.ServiceNameKey.String("query-service"),
|
||||
)
|
||||
|
||||
core := zapcore.NewTee(
|
||||
zapcore.NewCore(consoleEncoder, os.Stdout, defaultLogLevel),
|
||||
)
|
||||
|
||||
if enableQueryServiceLogOTLPExport == true {
|
||||
conn, err := grpc.DialContext(ctx, constants.OTLPTarget, grpc.WithBlock(), grpc.WithInsecure(), grpc.WithTimeout(time.Second*30))
|
||||
if err != nil {
|
||||
log.Println("failed to connect to otlp collector to export query service logs with error:", err)
|
||||
} else {
|
||||
logExportBatchSizeInt, err := strconv.Atoi(baseconst.LogExportBatchSize)
|
||||
if err != nil {
|
||||
logExportBatchSizeInt = 1000
|
||||
}
|
||||
ws := zapcore.AddSync(zapotlpsync.NewOtlpSyncer(conn, zapotlpsync.Options{
|
||||
BatchSize: logExportBatchSizeInt,
|
||||
ResourceSchema: semconv.SchemaURL,
|
||||
Resource: res,
|
||||
}))
|
||||
core = zapcore.NewTee(
|
||||
zapcore.NewCore(consoleEncoder, os.Stdout, defaultLogLevel),
|
||||
zapcore.NewCore(otlpEncoder, zapcore.NewMultiWriteSyncer(ws), defaultLogLevel),
|
||||
)
|
||||
}
|
||||
}
|
||||
logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
|
||||
|
||||
logger, _ := config.Build()
|
||||
return logger
|
||||
}
|
||||
|
||||
func main() {
|
||||
var promConfigPath, skipTopLvlOpsPath string
|
||||
var promConfigPath string
|
||||
|
||||
// disables rule execution but allows change to the rule definition
|
||||
var disableRules bool
|
||||
@@ -82,20 +34,12 @@ func main() {
|
||||
// the url used to build link in the alert messages in slack and other systems
|
||||
var ruleRepoURL string
|
||||
|
||||
var enableQueryServiceLogOTLPExport bool
|
||||
var preferDelta bool
|
||||
var preferSpanMetrics bool
|
||||
|
||||
flag.StringVar(&promConfigPath, "config", "./config/prometheus.yml", "(prometheus config to read metrics)")
|
||||
flag.StringVar(&skipTopLvlOpsPath, "skip-top-level-ops", "", "(config file to skip top level operations)")
|
||||
flag.BoolVar(&disableRules, "rules.disable", false, "(disable rule evaluation)")
|
||||
flag.BoolVar(&preferDelta, "prefer-delta", false, "(prefer delta over cumulative metrics)")
|
||||
flag.BoolVar(&preferSpanMetrics, "prefer-span-metrics", false, "(prefer span metrics for service level metrics)")
|
||||
flag.StringVar(&ruleRepoURL, "rules.repo-url", baseconst.AlertHelpPage, "(host address used to build rule link in alert messages)")
|
||||
flag.BoolVar(&enableQueryServiceLogOTLPExport, "enable.query.service.log.otlp.export", false, "(enable query service log otlp export)")
|
||||
flag.Parse()
|
||||
|
||||
loggerMgr := initZapLog(enableQueryServiceLogOTLPExport)
|
||||
loggerMgr := initZapLog()
|
||||
zap.ReplaceGlobals(loggerMgr)
|
||||
defer loggerMgr.Sync() // flushes buffer, if any
|
||||
|
||||
@@ -103,14 +47,11 @@ func main() {
|
||||
version.PrintVersion()
|
||||
|
||||
serverOptions := &app.ServerOptions{
|
||||
HTTPHostPort: baseconst.HTTPHostPort,
|
||||
PromConfigPath: promConfigPath,
|
||||
SkipTopLvlOpsPath: skipTopLvlOpsPath,
|
||||
PreferDelta: preferDelta,
|
||||
PreferSpanMetrics: preferSpanMetrics,
|
||||
PrivateHostPort: baseconst.PrivateHostPort,
|
||||
DisableRules: disableRules,
|
||||
RuleRepoURL: ruleRepoURL,
|
||||
HTTPHostPort: baseconst.HTTPHostPort,
|
||||
PromConfigPath: promConfigPath,
|
||||
PrivateHostPort: baseconst.PrivateHostPort,
|
||||
DisableRules: disableRules,
|
||||
RuleRepoURL: ruleRepoURL,
|
||||
}
|
||||
|
||||
// Read the jwt secret key
|
||||
@@ -144,7 +85,6 @@ func main() {
|
||||
logger.Info("Received HealthCheck status: ", zap.Int("status", int(status)))
|
||||
case <-signalsChannel:
|
||||
logger.Fatal("Received OS Interrupt Signal ... ")
|
||||
server.Stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package model
|
||||
|
||||
type PAT struct {
|
||||
Id string `json:"id" db:"id"`
|
||||
UserID string `json:"userId" db:"user_id"`
|
||||
Token string `json:"token" db:"token"`
|
||||
Name string `json:"name" db:"name"`
|
||||
CreatedAt int64 `json:"createdAt" db:"created_at"`
|
||||
ExpiresAt int64 `json:"expiresAt" db:"expires_at"` // unused as of now
|
||||
}
|
||||
@@ -11,164 +11,21 @@ const Enterprise = "ENTERPRISE_PLAN"
|
||||
const DisableUpsell = "DISABLE_UPSELL"
|
||||
|
||||
var BasicPlan = basemodel.FeatureSet{
|
||||
basemodel.Feature{
|
||||
Name: SSO,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.OSS,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: DisableUpsell,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.SmartTraceDetail,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.CustomMetricsFunction,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.QueryBuilderPanels,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: 5,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.QueryBuilderAlerts,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: 5,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.UseSpanMetrics,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
Basic: true,
|
||||
SSO: false,
|
||||
DisableUpsell: false,
|
||||
}
|
||||
|
||||
var ProPlan = basemodel.FeatureSet{
|
||||
basemodel.Feature{
|
||||
Name: SSO,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.OSS,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.SmartTraceDetail,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.CustomMetricsFunction,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.QueryBuilderPanels,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.QueryBuilderAlerts,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.UseSpanMetrics,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
Pro: true,
|
||||
SSO: true,
|
||||
basemodel.SmartTraceDetail: true,
|
||||
basemodel.CustomMetricsFunction: true,
|
||||
}
|
||||
|
||||
var EnterprisePlan = basemodel.FeatureSet{
|
||||
basemodel.Feature{
|
||||
Name: SSO,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.OSS,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.SmartTraceDetail,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.CustomMetricsFunction,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.QueryBuilderPanels,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.QueryBuilderAlerts,
|
||||
Active: true,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.UseSpanMetrics,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
Enterprise: true,
|
||||
SSO: true,
|
||||
basemodel.SmartTraceDetail: true,
|
||||
basemodel.CustomMetricsFunction: true,
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/go-co-op/gocron"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
@@ -29,6 +28,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// send usage every 24 hour
|
||||
uploadFrequency = 24 * time.Hour
|
||||
|
||||
locker = stateUnlocked
|
||||
)
|
||||
|
||||
@@ -37,7 +39,12 @@ type Manager struct {
|
||||
|
||||
licenseRepo *license.Repo
|
||||
|
||||
scheduler *gocron.Scheduler
|
||||
// end the usage routine, this is important to gracefully
|
||||
// stopping usage reporting and protect in-consistent updates
|
||||
done chan struct{}
|
||||
|
||||
// terminated waits for the UsageExporter go routine to end
|
||||
terminated chan struct{}
|
||||
}
|
||||
|
||||
func New(dbType string, db *sqlx.DB, licenseRepo *license.Repo, clickhouseConn clickhouse.Conn) (*Manager, error) {
|
||||
@@ -46,7 +53,6 @@ func New(dbType string, db *sqlx.DB, licenseRepo *license.Repo, clickhouseConn c
|
||||
// repository: repo,
|
||||
clickhouseConn: clickhouseConn,
|
||||
licenseRepo: licenseRepo,
|
||||
scheduler: gocron.NewScheduler(time.UTC).Every(1).Day().At("00:00"), // send usage every at 00:00 UTC
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
@@ -58,30 +64,37 @@ func (lm *Manager) Start() error {
|
||||
return fmt.Errorf("usage exporter is locked")
|
||||
}
|
||||
|
||||
_, err := lm.scheduler.Do(func() { lm.UploadUsage() })
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// upload usage once when starting the service
|
||||
lm.UploadUsage()
|
||||
|
||||
lm.scheduler.StartAsync()
|
||||
go lm.UsageExporter(context.Background())
|
||||
|
||||
return nil
|
||||
}
|
||||
func (lm *Manager) UploadUsage() {
|
||||
ctx := context.Background()
|
||||
|
||||
func (lm *Manager) UsageExporter(ctx context.Context) {
|
||||
defer close(lm.terminated)
|
||||
|
||||
uploadTicker := time.NewTicker(uploadFrequency)
|
||||
defer uploadTicker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-lm.done:
|
||||
return
|
||||
case <-uploadTicker.C:
|
||||
lm.UploadUsage(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (lm *Manager) UploadUsage(ctx context.Context) error {
|
||||
// check if license is present or not
|
||||
license, err := lm.licenseRepo.GetActiveLicense(ctx)
|
||||
license, err := lm.licenseRepo.GetActiveLicense(context.Background())
|
||||
if err != nil {
|
||||
zap.S().Errorf("failed to get active license: %v", zap.Error(err))
|
||||
return
|
||||
return fmt.Errorf("failed to get active license")
|
||||
}
|
||||
if license == nil {
|
||||
// we will not start the usage reporting if license is not present.
|
||||
zap.S().Info("no license present, skipping usage reporting")
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
usages := []model.UsageDB{}
|
||||
@@ -107,8 +120,7 @@ func (lm *Manager) UploadUsage() {
|
||||
dbusages := []model.UsageDB{}
|
||||
err := lm.clickhouseConn.Select(ctx, &dbusages, fmt.Sprintf(query, db, db), time.Now().Add(-(24 * time.Hour)))
|
||||
if err != nil && !strings.Contains(err.Error(), "doesn't exist") {
|
||||
zap.S().Errorf("failed to get usage from clickhouse: %v", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
for _, u := range dbusages {
|
||||
u.Type = db
|
||||
@@ -118,7 +130,7 @@ func (lm *Manager) UploadUsage() {
|
||||
|
||||
if len(usages) <= 0 {
|
||||
zap.S().Info("no snapshots to upload, skipping.")
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
zap.S().Info("uploading usage data")
|
||||
@@ -127,15 +139,13 @@ func (lm *Manager) UploadUsage() {
|
||||
for _, usage := range usages {
|
||||
usageDataBytes, err := encryption.Decrypt([]byte(usage.ExporterID[:32]), []byte(usage.Data))
|
||||
if err != nil {
|
||||
zap.S().Errorf("error while decrypting usage data: %v", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
usageData := model.Usage{}
|
||||
err = json.Unmarshal(usageDataBytes, &usageData)
|
||||
if err != nil {
|
||||
zap.S().Errorf("error while unmarshalling usage data: %v", zap.Error(err))
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
usageData.CollectorID = usage.CollectorID
|
||||
@@ -150,16 +160,20 @@ func (lm *Manager) UploadUsage() {
|
||||
LicenseKey: key,
|
||||
Usage: usagesPayload,
|
||||
}
|
||||
lm.UploadUsageWithExponentalBackOff(ctx, payload)
|
||||
err = lm.UploadUsageWithExponentalBackOff(ctx, payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lm *Manager) UploadUsageWithExponentalBackOff(ctx context.Context, payload model.UsagePayload) {
|
||||
func (lm *Manager) UploadUsageWithExponentalBackOff(ctx context.Context, payload model.UsagePayload) error {
|
||||
for i := 1; i <= MaxRetries; i++ {
|
||||
apiErr := licenseserver.SendUsage(ctx, payload)
|
||||
if apiErr != nil && i == MaxRetries {
|
||||
zap.S().Errorf("retries stopped : %v", zap.Error(apiErr))
|
||||
// not returning error here since it is captured in the failed count
|
||||
return
|
||||
return nil
|
||||
} else if apiErr != nil {
|
||||
// sleeping for exponential backoff
|
||||
sleepDuration := RetryInterval * time.Duration(i)
|
||||
@@ -169,14 +183,11 @@ func (lm *Manager) UploadUsageWithExponentalBackOff(ctx context.Context, payload
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lm *Manager) Stop() {
|
||||
lm.scheduler.Stop()
|
||||
|
||||
zap.S().Debug("sending usage data before shutting down")
|
||||
// send usage before shutting down
|
||||
lm.UploadUsage()
|
||||
|
||||
close(lm.done)
|
||||
atomic.StoreUint32(&locker, stateUnlocked)
|
||||
<-lm.terminated
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
["@babel/preset-react", { "runtime": "automatic" }],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
|
||||
@@ -16,7 +16,6 @@ module.exports = {
|
||||
'plugin:sonarjs/recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
'plugin:react/jsx-runtime',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
@@ -59,7 +58,7 @@ module.exports = {
|
||||
'react/no-array-index-key': 'error',
|
||||
'linebreak-style': [
|
||||
'error',
|
||||
process.env.platform === 'win32' ? 'windows' : 'unix',
|
||||
process.platform === 'win32' ? 'windows' : 'unix',
|
||||
],
|
||||
'@typescript-eslint/default-param-last': 'off',
|
||||
|
||||
@@ -103,10 +102,9 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
|
||||
'arrow-body-style': ['error', 'as-needed'],
|
||||
|
||||
// eslint rules need to remove
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'import/no-cycle': 'off',
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
cd frontend && yarn run commitlint --edit $1
|
||||
cd frontend && npm run commitlint
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
network-timeout 600000
|
||||
save-prefix ""
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
# **Frontend Guidelines**
|
||||
|
||||
Embrace the spirit of collaboration and contribute to the success of our open-source project by adhering to these frontend development guidelines with precision and passion.
|
||||
|
||||
### React and Components
|
||||
|
||||
- Strive to create small and modular components, ensuring they are divided into individual pieces for improved maintainability and reusability.
|
||||
- Avoid passing inline objects or functions as props to React components, as they are recreated with each render cycle.
|
||||
Utilize careful memoization of functions and variables, balancing optimization efforts to prevent potential performance issues. [When to useMemo and useCallback](https://kentcdodds.com/blog/usememo-and-usecallback) by Kent C. Dodds is quite helpful for this scenario.
|
||||
- Minimize the use of inline functions whenever possible to enhance code readability and improve overall comprehension.
|
||||
- Employ the appropriate usage of useMemo and useCallback hooks for effective memoization of values and functions.
|
||||
- Determine the appropriate placement of components:
|
||||
- Pages should contain an aggregation of all components and containers.
|
||||
- Commonly used components should reside in the 'components' directory.
|
||||
- Parent components responsible for data manipulation should be placed in the 'container' directory.
|
||||
- Strategically decide where to store data, either in global state or local components:
|
||||
- Begin by storing data in local components and gradually transition to global state as necessary.
|
||||
- Avoid importing default namespace `React` as the project is using `v18` and `import React from 'react'` is not needed anymore.
|
||||
- When a function requires more than three arguments (except when memoized), encapsulate them within an object to enhance readability and reduce potential parameter complexity.
|
||||
|
||||
### API and Services
|
||||
|
||||
- Avoid incorporating business logic within API/Service files to maintain flexibility for consumers to handle it according to their specific needs.
|
||||
- Employ the use of the useQuery hook for fetching data and the useMutation hook for updating data, ensuring a consistent and efficient approach.
|
||||
- Utilize the useQueryClient hook when updating the cache, facilitating smooth and effective management of data within the application.
|
||||
|
||||
**Note -** In our project, we are utilizing React Query v3. To gain a comprehensive understanding of its features and implementation, we recommend referring to the [official documentation](https://tanstack.com/query/v3/docs/react/overview) as a valuable resource.
|
||||
|
||||
### Styling
|
||||
|
||||
- Refrain from using inline styling within React components to maintain separation of concerns and promote a more maintainable codebase.
|
||||
- Opt for using the rem unit instead of px values to ensure better scalability and responsiveness across different devices and screen sizes.
|
||||
|
||||
### Linting and Setup
|
||||
|
||||
- It is crucial to refrain from disabling ESLint and TypeScript errors within the project. If there is a specific rule that needs to be disabled, provide a clear and justified explanation for doing so. Maintaining the integrity of the linting and type-checking processes ensures code quality and consistency throughout the codebase.
|
||||
- In our project, we rely on several essential ESLint plugins, namely:
|
||||
- [plugin:@typescript-eslint](https://typescript-eslint.io/rules/)
|
||||
- [airbnb styleguide](https://github.com/airbnb/javascript)
|
||||
- [plugin:sonarjs](https://github.com/SonarSource/eslint-plugin-sonarjs)
|
||||
|
||||
To ensure compliance with our coding standards and best practices, we encourage you to refer to the documentation of these plugins. Familiarizing yourself with the ESLint rules they provide will help maintain code quality and consistency throughout the project.
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- Ensure that component names are written in Capital Case, while the folder names should be in lowercase.
|
||||
- Keep all other elements, such as variables, functions, and file names, in lowercase.
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- Ensure that functions are modularized and follow the Single Responsibility Principle (SRP). The function's name should accurately convey its purpose and functionality.
|
||||
- Semantic division of functions into smaller units should be prioritized for improved readability and maintainability.
|
||||
Aim to keep functions concise and avoid exceeding a maximum length of 40 lines to enhance code understandability and ease of maintenance.
|
||||
- Eliminate the use of hard-coded strings or enums, favoring a more flexible and maintainable approach.
|
||||
- Strive to internationalize all strings within the codebase to support localization and improve accessibility for users across different languages.
|
||||
- Minimize the usage of multiple if statements or switch cases within a function. Consider creating a mapper and separating logic into multiple functions for better code organization.
|
||||
@@ -1,5 +1,5 @@
|
||||
# Builder stage
|
||||
FROM node:16.15.0 as builder
|
||||
FROM node:16.15.0-slim as builder
|
||||
|
||||
# Add Maintainer Info
|
||||
LABEL maintainer="signoz"
|
||||
@@ -11,8 +11,6 @@ WORKDIR /frontend
|
||||
|
||||
# Copy the package.json and .yarnrc files prior to install dependencies
|
||||
COPY package.json ./
|
||||
# Copy lock file
|
||||
COPY yarn.lock ./
|
||||
COPY .yarnrc ./
|
||||
|
||||
# Install the dependencies and make the folder
|
||||
|
||||
@@ -15,19 +15,16 @@ const config: Config.InitialOptions = {
|
||||
useESM: true,
|
||||
},
|
||||
},
|
||||
testMatch: ['<rootDir>/src/**/*?(*.)(test).(ts|js)?(x)'],
|
||||
testMatch: ['<rootDir>/src/**/?(*.)(test).(ts|js)?(x)'],
|
||||
preset: 'ts-jest/presets/js-with-ts-esm',
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx)?$': 'ts-jest',
|
||||
'^.+\\.(js|jsx)$': 'babel-jest',
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!(lodash-es|react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend)/)',
|
||||
],
|
||||
transformIgnorePatterns: ['node_modules/(?!(lodash-es)/)'],
|
||||
setupFilesAfterEnv: ['<rootDir>jest.setup.ts'],
|
||||
testPathIgnorePatterns: ['/node_modules/', '/public/'],
|
||||
moduleDirectories: ['node_modules', 'src'],
|
||||
testEnvironment: 'jest-environment-jsdom',
|
||||
testEnvironmentOptions: {
|
||||
'jest-playwright': {
|
||||
browsers: ['chromium', 'firefox', 'webkit'],
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
/* eslint-disable object-shorthand */
|
||||
/* eslint-disable func-names */
|
||||
|
||||
/**
|
||||
* Adds custom matchers from the react testing library to all tests
|
||||
*/
|
||||
import '@testing-library/jest-dom';
|
||||
import 'jest-styled-components';
|
||||
|
||||
// Mock window.matchMedia
|
||||
window.matchMedia =
|
||||
window.matchMedia ||
|
||||
function (): any {
|
||||
return {
|
||||
matches: false,
|
||||
addListener: function () {},
|
||||
removeListener: function () {},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -31,10 +31,12 @@
|
||||
"@ant-design/icons": "4.8.0",
|
||||
"@grafana/data": "^8.4.3",
|
||||
"@monaco-editor/react": "^4.3.1",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@welldone-software/why-did-you-render": "^6.2.1",
|
||||
"@xstate/react": "^3.0.0",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"antd": "5.0.5",
|
||||
"antd-table-saveas-excel": "2.2.1",
|
||||
"axios": "^0.21.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.0",
|
||||
@@ -42,21 +44,21 @@
|
||||
"babel-plugin-named-asset-import": "^0.3.7",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"babel-preset-react-app": "^10.0.0",
|
||||
"chart.js": "3.9.1",
|
||||
"chart.js": "^3.4.0",
|
||||
"chartjs-adapter-date-fns": "^2.0.0",
|
||||
"chartjs-plugin-annotation": "^1.4.0",
|
||||
"color": "^4.2.1",
|
||||
"color-alpha": "1.1.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "4.3.0",
|
||||
"css-minimizer-webpack-plugin": "^3.2.0",
|
||||
"d3": "^6.2.0",
|
||||
"d3-flame-graph": "^3.1.1",
|
||||
"d3-tip": "^0.9.1",
|
||||
"dayjs": "^1.10.7",
|
||||
"dompurify": "3.0.0",
|
||||
"dotenv": "8.2.0",
|
||||
"event-source-polyfill": "1.0.31",
|
||||
"eventemitter3": "5.0.1",
|
||||
"file-loader": "6.1.1",
|
||||
"fontfaceobserver": "2.3.0",
|
||||
"flat": "^5.0.2",
|
||||
"history": "4.10.1",
|
||||
"html-webpack-plugin": "5.1.0",
|
||||
"i18next": "^21.6.12",
|
||||
@@ -68,23 +70,17 @@
|
||||
"less-loader": "^10.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mini-css-extract-plugin": "2.4.5",
|
||||
"papaparse": "5.4.1",
|
||||
"react": "18.2.0",
|
||||
"react-addons-update": "15.6.3",
|
||||
"react-dnd": "16.0.1",
|
||||
"react-dnd-html5-backend": "16.0.1",
|
||||
"react-dom": "18.2.0",
|
||||
"react-drag-listview": "2.0.0",
|
||||
"react": "17.0.0",
|
||||
"react-dom": "17.0.0",
|
||||
"react-force-graph": "^1.41.0",
|
||||
"react-graph-vis": "^1.0.5",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-helmet-async": "1.3.0",
|
||||
"react-i18next": "^11.16.1",
|
||||
"react-intersection-observer": "9.4.1",
|
||||
"react-query": "^3.34.19",
|
||||
"react-redux": "^7.2.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-use": "^17.3.2",
|
||||
"react-virtuoso": "4.0.3",
|
||||
"react-vis": "^1.11.7",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"stream": "^0.0.2",
|
||||
@@ -124,35 +120,31 @@
|
||||
"@commitlint/config-conventional": "^16.2.4",
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@playwright/test": "^1.22.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/user-event": "14.4.3",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/compression-webpack-plugin": "^9.0.0",
|
||||
"@types/copy-webpack-plugin": "^8.0.1",
|
||||
"@types/dompurify": "^2.4.0",
|
||||
"@types/d3": "^6.2.0",
|
||||
"@types/d3-tip": "^3.5.5",
|
||||
"@types/event-source-polyfill": "^1.0.0",
|
||||
"@types/fontfaceobserver": "2.1.0",
|
||||
"@types/flat": "^5.0.2",
|
||||
"@types/jest": "^27.5.1",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/mini-css-extract-plugin": "^2.5.1",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/papaparse": "5.3.7",
|
||||
"@types/react": "18.0.26",
|
||||
"@types/react-addons-update": "0.14.21",
|
||||
"@types/react-dom": "18.0.10",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^16.9.9",
|
||||
"@types/react-grid-layout": "^1.1.2",
|
||||
"@types/react-helmet-async": "1.0.3",
|
||||
"@types/react-redux": "^7.1.11",
|
||||
"@types/react-resizable": "3.0.3",
|
||||
"@types/react-router-dom": "^5.1.6",
|
||||
"@types/redux": "^3.6.0",
|
||||
"@types/styled-components": "^5.1.4",
|
||||
"@types/uuid": "^8.3.1",
|
||||
"@types/vis": "^4.21.21",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@types/webpack-dev-server": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
||||
"@typescript-eslint/parser": "^4.28.2",
|
||||
"@welldone-software/why-did-you-render": "6.2.1",
|
||||
"autoprefixer": "^9.0.0",
|
||||
"babel-plugin-styled-components": "^1.12.0",
|
||||
"compression-webpack-plugin": "9.0.0",
|
||||
@@ -177,12 +169,11 @@
|
||||
"is-ci": "^3.0.1",
|
||||
"jest-playwright-preset": "^1.7.0",
|
||||
"jest-styled-components": "^7.0.8",
|
||||
"less-plugin-npm-import": "^2.1.0",
|
||||
"lint-staged": "^12.3.7",
|
||||
"portfinder-sync": "^0.0.2",
|
||||
"prettier": "2.2.1",
|
||||
"react-hooks-testing-library": "0.6.0",
|
||||
"react-hot-loader": "^4.13.0",
|
||||
"react-resizable": "3.0.4",
|
||||
"ts-jest": "^27.1.4",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript-plugin-css-modules": "^3.4.0",
|
||||
@@ -195,7 +186,7 @@
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "18.0.26",
|
||||
"@types/react-dom": "18.0.10"
|
||||
"@types/react": "17.0.0",
|
||||
"@types/react-dom": "17.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,5 @@
|
||||
"my_settings": "My Settings",
|
||||
"overview_metrics": "Overview Metrics",
|
||||
"dbcall_metrics": "Database Calls",
|
||||
"external_metrics": "External Calls",
|
||||
"pipelines": "Pipelines",
|
||||
"archives": "Archives",
|
||||
"logs_to_metrics": "Logs To Metrics"
|
||||
"external_metrics": "External Calls"
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"SIGN_UP": "SigNoz | Sign Up",
|
||||
"LOGIN": "SigNoz | Login",
|
||||
"SERVICE_METRICS": "SigNoz | Service Metrics",
|
||||
"SERVICE_MAP": "SigNoz | Service Map",
|
||||
"TRACE": "SigNoz | Trace",
|
||||
"TRACE_DETAIL": "SigNoz | Trace Detail",
|
||||
"TRACES_EXPLORER": "SigNoz | Traces Explorer",
|
||||
"SETTINGS": "SigNoz | Settings",
|
||||
"INSTRUMENTATION": "SigNoz | Get Started",
|
||||
"USAGE_EXPLORER": "SigNoz | Usage Explorer",
|
||||
"APPLICATION": "SigNoz | Home",
|
||||
"ALL_DASHBOARD": "SigNoz | All Dashboards",
|
||||
"DASHBOARD": "SigNoz | Dashboard",
|
||||
"DASHBOARD_WIDGET": "SigNoz | Dashboard Widget",
|
||||
"EDIT_ALERTS": "SigNoz | Edit Alerts",
|
||||
"LIST_ALL_ALERT": "SigNoz | All Alerts",
|
||||
"ALERTS_NEW": "SigNoz | New Alert",
|
||||
"ALL_CHANNELS": "SigNoz | All Channels",
|
||||
"CHANNELS_NEW": "SigNoz | New Channel",
|
||||
"CHANNELS_EDIT": "SigNoz | Edit Channel",
|
||||
"ALL_ERROR": "SigNoz | All Errors",
|
||||
"ERROR_DETAIL": "SigNoz | Error Detail",
|
||||
"VERSION": "SigNoz | Version",
|
||||
"MY_SETTINGS": "SigNoz | My Settings",
|
||||
"ORG_SETTINGS": "SigNoz | Organization Settings",
|
||||
"SOMETHING_WENT_WRONG": "SigNoz | Something Went Wrong",
|
||||
"UN_AUTHORIZED": "SigNoz | Unauthorized",
|
||||
"NOT_FOUND": "SigNoz | Page Not Found",
|
||||
"LOGS": "SigNoz | Logs",
|
||||
"LOGS_EXPLORER": "SigNoz | Logs Explorer",
|
||||
"HOME_PAGE": "Open source Observability Platform | SigNoz",
|
||||
"PASSWORD_RESET": "SigNoz | Password Reset",
|
||||
"LIST_LICENSES": "SigNoz | List of Licenses",
|
||||
"DEFAULT": "Open source Observability Platform | SigNoz"
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"options_menu": {
|
||||
"options": "Options",
|
||||
"format": "Format",
|
||||
"raw": "Raw",
|
||||
"default": "Default",
|
||||
"column": "Column",
|
||||
"maxLines": "Max lines per Row",
|
||||
"addColumn": "Add a column"
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
"routes": {
|
||||
"general": "General",
|
||||
"alert_channels": "Alert Channels",
|
||||
"all_errors": "All Exceptions",
|
||||
"pipelines": "Pipelines"
|
||||
"all_errors": "All Exceptions"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"delete": "Delete",
|
||||
"filter": "Filter",
|
||||
"update": "Update",
|
||||
"create": "Create",
|
||||
"reorder": "Reorder",
|
||||
"cancel": "Cancel",
|
||||
"reorder_pipeline": "Do you want to reorder pipeline?",
|
||||
"reorder_pipeline_description": "Logs are processed sequentially in processors and pipelines. Reordering it may change how data is processed by them.",
|
||||
"delete_pipeline": "Do you want to delete pipeline",
|
||||
"delete_pipeline_description": "Logs are processed sequentially in processors and pipelines. Deleting a pipeline may change content of data processed by other pipelines & processors",
|
||||
"add_new_pipeline": "Add a New Pipeline",
|
||||
"new_pipeline": "New Pipeline",
|
||||
"enter_edit_mode": "Enter Edit Mode",
|
||||
"save_configuration": "Save Configuration",
|
||||
"edit_pipeline": "Edit Pipeline",
|
||||
"create_pipeline": "Create New Pipeline",
|
||||
"add_new_processor": "Add Processor",
|
||||
"edit_processor": "Edit Processor",
|
||||
"create_processor": "Create New Processor",
|
||||
"processor_type": "Select Processor Type",
|
||||
"reorder_processor": "Do you want to reorder processor?",
|
||||
"reorder_processor_description": "Logs are processed sequentially in processors. Reordering it may change how data is processed by them.",
|
||||
"delete_processor": "Do you want to delete processor",
|
||||
"delete_processor_description": "Logs are processed sequentially in processors. Deleting a processor may change content of data processed by other processors",
|
||||
"search_pipeline_placeholder": "Filter Pipelines",
|
||||
"pipeline_name_placeholder": "Name",
|
||||
"pipeline_tags_placeholder": "Tags",
|
||||
"pipeline_description_placeholder": "Enter description for your pipeline",
|
||||
"processor_name_placeholder": "Name",
|
||||
"processor_regex_placeholder": "Regex",
|
||||
"processor_parsefrom_placeholder": "Parse From",
|
||||
"processor_parseto_placeholder": "Parse From",
|
||||
"processor_onerror_placeholder": "on Error",
|
||||
"processor_pattern_placeholder": "Pattern",
|
||||
"processor_field_placeholder": "Field",
|
||||
"processor_value_placeholder": "Value",
|
||||
"processor_description_placeholder": "example rule: %{word:first}",
|
||||
"processor_trace_id_placeholder": "Trace Id Parce From",
|
||||
"processor_span_id_placeholder": "Span id Parse From",
|
||||
"processor_trace_flags_placeholder": "Trace flags parse from",
|
||||
"processor_from_placeholder": "From",
|
||||
"processor_to_placeholder": "To"
|
||||
}
|
||||
@@ -5,8 +5,5 @@
|
||||
"my_settings": "My Settings",
|
||||
"overview_metrics": "Overview Metrics",
|
||||
"dbcall_metrics": "Database Calls",
|
||||
"external_metrics": "External Calls",
|
||||
"pipelines": "Pipelines",
|
||||
"archives": "Archives",
|
||||
"logs_to_metrics": "Logs To Metrics"
|
||||
"external_metrics": "External Calls"
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"SIGN_UP": "SigNoz | Sign Up",
|
||||
"LOGIN": "SigNoz | Login",
|
||||
"SERVICE_METRICS": "SigNoz | Service Metrics",
|
||||
"SERVICE_MAP": "SigNoz | Service Map",
|
||||
"TRACE": "SigNoz | Trace",
|
||||
"TRACE_DETAIL": "SigNoz | Trace Detail",
|
||||
"TRACES_EXPLORER": "SigNoz | Traces Explorer",
|
||||
"SETTINGS": "SigNoz | Settings",
|
||||
"INSTRUMENTATION": "SigNoz | Get Started",
|
||||
"USAGE_EXPLORER": "SigNoz | Usage Explorer",
|
||||
"APPLICATION": "SigNoz | Home",
|
||||
"ALL_DASHBOARD": "SigNoz | All Dashboards",
|
||||
"DASHBOARD": "SigNoz | Dashboard",
|
||||
"DASHBOARD_WIDGET": "SigNoz | Dashboard Widget",
|
||||
"EDIT_ALERTS": "SigNoz | Edit Alerts",
|
||||
"LIST_ALL_ALERT": "SigNoz | All Alerts",
|
||||
"ALERTS_NEW": "SigNoz | New Alert",
|
||||
"ALL_CHANNELS": "SigNoz | All Channels",
|
||||
"CHANNELS_NEW": "SigNoz | New Channel",
|
||||
"CHANNELS_EDIT": "SigNoz | Edit Channel",
|
||||
"ALL_ERROR": "SigNoz | All Errors",
|
||||
"ERROR_DETAIL": "SigNoz | Error Detail",
|
||||
"VERSION": "SigNoz | Version",
|
||||
"MY_SETTINGS": "SigNoz | My Settings",
|
||||
"ORG_SETTINGS": "SigNoz | Organization Settings",
|
||||
"SOMETHING_WENT_WRONG": "SigNoz | Something Went Wrong",
|
||||
"UN_AUTHORIZED": "SigNoz | Unauthorized",
|
||||
"NOT_FOUND": "SigNoz | Page Not Found",
|
||||
"LOGS": "SigNoz | Logs",
|
||||
"LOGS_EXPLORER": "SigNoz | Logs Explorer",
|
||||
"HOME_PAGE": "Open source Observability Platform | SigNoz",
|
||||
"PASSWORD_RESET": "SigNoz | Password Reset",
|
||||
"LIST_LICENSES": "SigNoz | List of Licenses",
|
||||
"DEFAULT": "Open source Observability Platform | SigNoz"
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"options_menu": {
|
||||
"options": "Options",
|
||||
"format": "Format",
|
||||
"raw": "Raw",
|
||||
"default": "Default",
|
||||
"column": "Column",
|
||||
"maxLines": "Max lines per Row",
|
||||
"addColumn": "Add a column"
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
"routes": {
|
||||
"general": "General",
|
||||
"alert_channels": "Alert Channels",
|
||||
"all_errors": "All Exceptions",
|
||||
"pipelines": "Pipelines"
|
||||
"all_errors": "All Exceptions"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { notification } from 'antd';
|
||||
import getLocalStorageApi from 'api/browser/localstorage/get';
|
||||
import loginApi from 'api/user/login';
|
||||
import { Logout } from 'api/utils';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import history from 'lib/history';
|
||||
import { ReactChild, useEffect, useMemo } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { matchPath, Redirect, useLocation } from 'react-router-dom';
|
||||
@@ -47,8 +47,6 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
|
||||
|
||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
const currentRoute = mapRoutes.get('current');
|
||||
|
||||
const navigateToLoginIfNotLoggedIn = (isLoggedIn = isLoggedInState): void => {
|
||||
@@ -108,7 +106,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
|
||||
} else {
|
||||
Logout();
|
||||
|
||||
notifications.error({
|
||||
notification.error({
|
||||
message: response.error || t('something_went_wrong'),
|
||||
});
|
||||
}
|
||||
@@ -161,7 +159,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
|
||||
}
|
||||
|
||||
interface PrivateRouteProps {
|
||||
children: ReactChild;
|
||||
children: React.ReactChild;
|
||||
}
|
||||
|
||||
export default PrivateRoute;
|
||||
|
||||
@@ -3,11 +3,8 @@ import NotFound from 'components/NotFound';
|
||||
import Spinner from 'components/Spinner';
|
||||
import AppLayout from 'container/AppLayout';
|
||||
import { useThemeConfig } from 'hooks/useDarkMode';
|
||||
import { NotificationProvider } from 'hooks/useNotifications';
|
||||
import { ResourceProvider } from 'hooks/useResourceAttribute';
|
||||
import history from 'lib/history';
|
||||
import { QueryBuilderProvider } from 'providers/QueryBuilder';
|
||||
import { Suspense } from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import { Route, Router, Switch } from 'react-router-dom';
|
||||
|
||||
import PrivateRoute from './Private';
|
||||
@@ -19,30 +16,24 @@ function App(): JSX.Element {
|
||||
return (
|
||||
<ConfigProvider theme={themeConfig}>
|
||||
<Router history={history}>
|
||||
<NotificationProvider>
|
||||
<PrivateRoute>
|
||||
<ResourceProvider>
|
||||
<QueryBuilderProvider>
|
||||
<AppLayout>
|
||||
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
|
||||
<Switch>
|
||||
{routes.map(({ path, component, exact }) => (
|
||||
<Route
|
||||
key={`${path}`}
|
||||
exact={exact}
|
||||
path={path}
|
||||
component={component}
|
||||
/>
|
||||
))}
|
||||
<PrivateRoute>
|
||||
<AppLayout>
|
||||
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
|
||||
<Switch>
|
||||
{routes.map(({ path, component, exact }) => (
|
||||
<Route
|
||||
key={`${path}`}
|
||||
exact={exact}
|
||||
path={path}
|
||||
component={component}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Route path="*" component={NotFound} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</AppLayout>
|
||||
</QueryBuilderProvider>
|
||||
</ResourceProvider>
|
||||
</PrivateRoute>
|
||||
</NotificationProvider>
|
||||
<Route path="*" component={NotFound} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</AppLayout>
|
||||
</PrivateRoute>
|
||||
</Router>
|
||||
</ConfigProvider>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import Loadable from 'components/Loadable';
|
||||
|
||||
export const ServicesTablePage = Loadable(
|
||||
() => import(/* webpackChunkName: "ServicesTablePage" */ 'pages/Services'),
|
||||
() => import(/* webpackChunkName: "ServicesTablePage" */ 'pages/Metrics'),
|
||||
);
|
||||
|
||||
export const ServiceMetricsPage = Loadable(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "ServiceMetricsPage" */ 'pages/MetricsApplication'
|
||||
/* webpackChunkName: "ServiceMetricsPage" */ 'pages/MetricApplication'
|
||||
),
|
||||
);
|
||||
|
||||
@@ -15,11 +15,6 @@ export const ServiceMapPage = Loadable(
|
||||
() => import(/* webpackChunkName: "ServiceMapPage" */ 'modules/Servicemap'),
|
||||
);
|
||||
|
||||
export const TracesExplorer = Loadable(
|
||||
() =>
|
||||
import(/* webpackChunkName: "Traces Explorer Page" */ 'pages/TracesExplorer'),
|
||||
);
|
||||
|
||||
export const TraceFilter = Loadable(
|
||||
() => import(/* webpackChunkName: "Trace Filter Page" */ 'pages/Trace'),
|
||||
);
|
||||
@@ -106,10 +101,6 @@ export const Logs = Loadable(
|
||||
() => import(/* webpackChunkName: "Logs" */ 'pages/Logs'),
|
||||
);
|
||||
|
||||
export const LogsExplorer = Loadable(
|
||||
() => import(/* webpackChunkName: "Logs Explorer" */ 'pages/LogsExplorer'),
|
||||
);
|
||||
|
||||
export const Login = Loadable(
|
||||
() => import(/* webpackChunkName: "Login" */ 'pages/Login'),
|
||||
);
|
||||
@@ -132,7 +123,3 @@ export const SomethingWentWrong = Loadable(
|
||||
export const LicensePage = Loadable(
|
||||
() => import(/* webpackChunkName: "All Channels" */ 'pages/License'),
|
||||
);
|
||||
|
||||
export const PipelinePage = Loadable(
|
||||
() => import(/* webpackChunkName: "Pipelines" */ 'pages/Pipelines'),
|
||||
);
|
||||
|
||||
@@ -16,12 +16,10 @@ import {
|
||||
ListAllALertsPage,
|
||||
Login,
|
||||
Logs,
|
||||
LogsExplorer,
|
||||
MySettings,
|
||||
NewDashboardPage,
|
||||
OrganizationSettings,
|
||||
PasswordReset,
|
||||
PipelinePage,
|
||||
ServiceMapPage,
|
||||
ServiceMetricsPage,
|
||||
ServicesTablePage,
|
||||
@@ -31,7 +29,6 @@ import {
|
||||
StatusPage,
|
||||
TraceDetail,
|
||||
TraceFilter,
|
||||
TracesExplorer,
|
||||
UnAuthorized,
|
||||
UsageExplorerPage,
|
||||
} from './pageComponents';
|
||||
@@ -142,13 +139,6 @@ const routes: AppRoutes[] = [
|
||||
isPrivate: true,
|
||||
key: 'TRACE',
|
||||
},
|
||||
{
|
||||
path: ROUTES.TRACES_EXPLORER,
|
||||
exact: true,
|
||||
component: TracesExplorer,
|
||||
isPrivate: true,
|
||||
key: 'TRACES_EXPLORER',
|
||||
},
|
||||
{
|
||||
path: ROUTES.CHANNELS_NEW,
|
||||
exact: true,
|
||||
@@ -219,13 +209,6 @@ const routes: AppRoutes[] = [
|
||||
key: 'LOGS',
|
||||
isPrivate: true,
|
||||
},
|
||||
{
|
||||
path: ROUTES.LOGS_EXPLORER,
|
||||
exact: true,
|
||||
component: LogsExplorer,
|
||||
key: 'LOGS_EXPLORER',
|
||||
isPrivate: true,
|
||||
},
|
||||
{
|
||||
path: ROUTES.LOGIN,
|
||||
exact: true,
|
||||
@@ -254,13 +237,6 @@ const routes: AppRoutes[] = [
|
||||
key: 'SOMETHING_WENT_WRONG',
|
||||
isPrivate: false,
|
||||
},
|
||||
{
|
||||
path: ROUTES.PIPELINES,
|
||||
exact: true,
|
||||
component: PipelinePage,
|
||||
key: 'PIPELINES',
|
||||
isPrivate: true,
|
||||
},
|
||||
];
|
||||
|
||||
export interface AppRoutes {
|
||||
|
||||
@@ -16,7 +16,7 @@ export function ErrorResponseHandler(error: AxiosError): ErrorResponse {
|
||||
return {
|
||||
statusCode,
|
||||
payload: null,
|
||||
error: data.errorType,
|
||||
error: 'Not Found',
|
||||
message: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const apiV1 = '/api/v1/';
|
||||
|
||||
export const apiV2 = '/api/v2/';
|
||||
export const apiV3 = '/api/v3/';
|
||||
export const apiAlertManager = '/api/alertmanager';
|
||||
|
||||
export default apiV1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ApiV2Instance as axios } from 'api';
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
@@ -8,7 +8,9 @@ const query = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/variables/query`, props);
|
||||
const response = await axios.get(
|
||||
`/variables/query?query=${encodeURIComponent(props.query)}`,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import createQueryParams from 'lib/createQueryParams';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/errors/getAll';
|
||||
|
||||
@@ -8,17 +9,11 @@ const getAll = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/listErrors`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
order: props.order,
|
||||
orderParam: props.orderParam,
|
||||
limit: props.limit,
|
||||
offset: props.offset,
|
||||
exceptionType: props.exceptionType,
|
||||
serviceName: props.serviceName,
|
||||
tags: props.tags,
|
||||
});
|
||||
const response = await axios.get(
|
||||
`/listErrors?${createQueryParams({
|
||||
...props,
|
||||
})}`,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import createQueryParams from 'lib/createQueryParams';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/errors/getErrorCounts';
|
||||
|
||||
@@ -8,13 +9,11 @@ const getErrorCounts = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/countErrors`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
exceptionType: props.exceptionType,
|
||||
serviceName: props.serviceName,
|
||||
tags: props.tags,
|
||||
});
|
||||
const response = await axios.get(
|
||||
`/countErrors?${createQueryParams({
|
||||
...props,
|
||||
})}`,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
@@ -2,15 +2,13 @@ import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { Pipeline } from 'types/api/pipeline/def';
|
||||
import { Props } from 'types/api/pipeline/post';
|
||||
import { PayloadProps } from 'types/api/features/getFeatures';
|
||||
|
||||
const post = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<Pipeline> | ErrorResponse> => {
|
||||
const getFeaturesFlags = async (): Promise<
|
||||
SuccessResponse<PayloadProps> | ErrorResponse
|
||||
> => {
|
||||
try {
|
||||
const response = await axios.post('/logs/pipelines', props.data);
|
||||
|
||||
const response = await axios.get(`/featureFlags`);
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
@@ -22,4 +20,4 @@ const post = async (
|
||||
}
|
||||
};
|
||||
|
||||
export default post;
|
||||
export default getFeaturesFlags;
|
||||
@@ -9,7 +9,7 @@ import { ENVIRONMENT } from 'constants/env';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import store from 'store';
|
||||
|
||||
import apiV1, { apiAlertManager, apiV2, apiV3 } from './apiV1';
|
||||
import apiV1, { apiAlertManager, apiV2 } from './apiV1';
|
||||
import { Logout } from './utils';
|
||||
|
||||
const interceptorsResponse = (
|
||||
@@ -109,17 +109,6 @@ ApiV2Instance.interceptors.response.use(
|
||||
);
|
||||
ApiV2Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
|
||||
// axios V3
|
||||
export const ApiV3Instance = axios.create({
|
||||
baseURL: `${ENVIRONMENT.baseURL}${apiV3}`,
|
||||
});
|
||||
ApiV3Instance.interceptors.response.use(
|
||||
interceptorsResponse,
|
||||
interceptorRejected,
|
||||
);
|
||||
ApiV3Instance.interceptors.request.use(interceptorsRequestResponse);
|
||||
//
|
||||
|
||||
AxiosAlertManagerInstance.interceptors.response.use(
|
||||
interceptorsResponse,
|
||||
interceptorRejected,
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
import { ApiV3Instance as axios } from 'api';
|
||||
import { ApiV2Instance as axios } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
MetricRangePayloadV3,
|
||||
MetricRangePayloadProps,
|
||||
MetricsRangeProps,
|
||||
} from 'types/api/metrics/getQueryRange';
|
||||
|
||||
export const getMetricsQueryRange = async (
|
||||
props: MetricsRangeProps,
|
||||
): Promise<SuccessResponse<MetricRangePayloadV3> | ErrorResponse> => {
|
||||
): Promise<SuccessResponse<MetricRangePayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post('/query_range', props);
|
||||
const response = await axios.post(`/metrics/query_range`, props);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data,
|
||||
params: props,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/metrics/getService';
|
||||
|
||||
const getService = async (props: Props): Promise<PayloadProps> => {
|
||||
const response = await axios.post(`/services`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
tags: props.selectedTags,
|
||||
});
|
||||
return response.data;
|
||||
const getService = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/services`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
tags: props.selectedTags,
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default getService;
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/metrics/getServiceOverview';
|
||||
|
||||
const getServiceOverview = async (props: Props): Promise<PayloadProps> => {
|
||||
const response = await axios.post(`/service/overview`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
service: props.service,
|
||||
step: props.step,
|
||||
tags: props.selectedTags,
|
||||
});
|
||||
const getServiceOverview = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/service/overview`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
service: props.service,
|
||||
step: props.step,
|
||||
tags: props.selectedTags,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default getServiceOverview;
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/metrics/getTopLevelOperations';
|
||||
|
||||
const getTopLevelOperations = async (): Promise<ServiceDataProps> => {
|
||||
const response = await axios.post(`/service/top_level_operations`);
|
||||
return response.data;
|
||||
};
|
||||
const getTopLevelOperations = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/service/top_level_operations`);
|
||||
|
||||
export type ServiceDataProps = {
|
||||
[serviceName: string]: string[];
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data[props.service],
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default getTopLevelOperations;
|
||||
|
||||
@@ -1,15 +1,29 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/metrics/getTopOperations';
|
||||
|
||||
const getTopOperations = async (props: Props): Promise<PayloadProps> => {
|
||||
const response = await axios.post(`/service/top_operations`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
service: props.service,
|
||||
tags: props.selectedTags,
|
||||
});
|
||||
const getTopOperations = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/service/top_operations`, {
|
||||
start: `${props.start}`,
|
||||
end: `${props.end}`,
|
||||
service: props.service,
|
||||
tags: props.selectedTags,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default getTopOperations;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { Pipeline } from 'types/api/pipeline/def';
|
||||
import { Props } from 'types/api/pipeline/get';
|
||||
|
||||
const get = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<Pipeline> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.get(`/logs/pipelines/${props.version}`);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response?.data?.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
|
||||
export default get;
|
||||
@@ -1,49 +0,0 @@
|
||||
import { ApiV3Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { baseAutoCompleteIdKeysOrder } from 'constants/queryBuilder';
|
||||
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
|
||||
import createQueryParams from 'lib/createQueryParams';
|
||||
// ** Helpers
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
// ** Types
|
||||
import { IGetAggregateAttributePayload } from 'types/api/queryBuilder/getAggregatorAttribute';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
IQueryAutocompleteResponse,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
export const getAggregateAttribute = async ({
|
||||
aggregateOperator,
|
||||
searchText,
|
||||
dataSource,
|
||||
}: IGetAggregateAttributePayload): Promise<
|
||||
SuccessResponse<IQueryAutocompleteResponse> | ErrorResponse
|
||||
> => {
|
||||
try {
|
||||
const response: AxiosResponse<{
|
||||
data: IQueryAutocompleteResponse;
|
||||
}> = await ApiV3Instance.get(
|
||||
`autocomplete/aggregate_attributes?${createQueryParams({
|
||||
aggregateOperator,
|
||||
searchText,
|
||||
dataSource,
|
||||
})}`,
|
||||
);
|
||||
|
||||
const payload: BaseAutocompleteData[] =
|
||||
response.data.data.attributeKeys?.map(({ id: _, ...item }) => ({
|
||||
...item,
|
||||
id: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder),
|
||||
})) || [];
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.statusText,
|
||||
payload: { attributeKeys: payload },
|
||||
};
|
||||
} catch (e) {
|
||||
return ErrorResponseHandler(e as AxiosError);
|
||||
}
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
import { ApiV3Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { baseAutoCompleteIdKeysOrder } from 'constants/queryBuilder';
|
||||
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
|
||||
import createQueryParams from 'lib/createQueryParams';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
// ** Types
|
||||
import { IGetAttributeKeysPayload } from 'types/api/queryBuilder/getAttributeKeys';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
IQueryAutocompleteResponse,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
export const getAggregateKeys = async ({
|
||||
aggregateOperator,
|
||||
searchText,
|
||||
dataSource,
|
||||
aggregateAttribute,
|
||||
tagType,
|
||||
}: IGetAttributeKeysPayload): Promise<
|
||||
SuccessResponse<IQueryAutocompleteResponse> | ErrorResponse
|
||||
> => {
|
||||
try {
|
||||
const response: AxiosResponse<{
|
||||
data: IQueryAutocompleteResponse;
|
||||
}> = await ApiV3Instance.get(
|
||||
`autocomplete/attribute_keys?${createQueryParams({
|
||||
aggregateOperator,
|
||||
searchText,
|
||||
dataSource,
|
||||
aggregateAttribute,
|
||||
})}&tagType=${tagType}`,
|
||||
);
|
||||
|
||||
const payload: BaseAutocompleteData[] =
|
||||
response.data.data.attributeKeys?.map(({ id: _, ...item }) => ({
|
||||
...item,
|
||||
id: createIdFromObjectFields(item, baseAutoCompleteIdKeysOrder),
|
||||
})) || [];
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.statusText,
|
||||
payload: { attributeKeys: payload },
|
||||
};
|
||||
} catch (e) {
|
||||
return ErrorResponseHandler(e as AxiosError);
|
||||
}
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
import { ApiV3Instance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import createQueryParams from 'lib/createQueryParams';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
IAttributeValuesResponse,
|
||||
IGetAttributeValuesPayload,
|
||||
} from 'types/api/queryBuilder/getAttributesValues';
|
||||
|
||||
export const getAttributesValues = async ({
|
||||
aggregateOperator,
|
||||
dataSource,
|
||||
aggregateAttribute,
|
||||
attributeKey,
|
||||
filterAttributeKeyDataType,
|
||||
tagType,
|
||||
searchText,
|
||||
}: IGetAttributeValuesPayload): Promise<
|
||||
SuccessResponse<IAttributeValuesResponse> | ErrorResponse
|
||||
> => {
|
||||
try {
|
||||
const response = await ApiV3Instance.get(
|
||||
`/autocomplete/attribute_values?${createQueryParams({
|
||||
aggregateOperator,
|
||||
dataSource,
|
||||
aggregateAttribute,
|
||||
attributeKey,
|
||||
searchText,
|
||||
})}&filterAttributeKeyDataType=${filterAttributeKeyDataType}&tagType=${tagType}`,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
@@ -32,7 +32,6 @@ const getFilters = async (
|
||||
maxDuration: String((duration.duration || [])[0] || ''),
|
||||
minDuration: String((duration.duration || [])[1] || ''),
|
||||
exclude,
|
||||
spanKind: props.spanKind,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -10,11 +10,9 @@ const getSpans = async (
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const updatedSelectedTags = props.selectedTags.map((e) => ({
|
||||
Key: `${e.Key}.(string)`,
|
||||
Key: e.Key[0],
|
||||
Operator: e.Operator,
|
||||
StringValues: e.StringValues,
|
||||
NumberValues: e.NumberValues,
|
||||
BoolValues: e.BoolValues,
|
||||
Values: e.Values,
|
||||
}));
|
||||
|
||||
const exclude: string[] = [];
|
||||
@@ -37,14 +35,13 @@ const getSpans = async (
|
||||
start: String(props.start),
|
||||
end: String(props.end),
|
||||
function: props.function,
|
||||
groupBy: props.groupBy === 'none' ? '' : props.groupBy,
|
||||
groupBy: props.groupBy,
|
||||
step: props.step,
|
||||
tags: updatedSelectedTags,
|
||||
...nonDuration,
|
||||
maxDuration: String((duration.duration || [])[0] || ''),
|
||||
minDuration: String((duration.duration || [])[1] || ''),
|
||||
exclude,
|
||||
spanKind: props.spanKind,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -28,11 +28,9 @@ const getSpanAggregate = async (
|
||||
});
|
||||
|
||||
const updatedSelectedTags = props.selectedTags.map((e) => ({
|
||||
Key: `${e.Key}.(string)`,
|
||||
Key: e.Key[0],
|
||||
Operator: e.Operator,
|
||||
StringValues: e.StringValues,
|
||||
NumberValues: e.NumberValues,
|
||||
BoolValues: e.BoolValues,
|
||||
Values: e.Values,
|
||||
}));
|
||||
|
||||
const other = Object.fromEntries(props.selectedFilter);
|
||||
@@ -48,7 +46,6 @@ const getSpanAggregate = async (
|
||||
maxDuration: String((duration.duration || [])[0] || ''),
|
||||
minDuration: String((duration.duration || [])[1] || ''),
|
||||
exclude,
|
||||
spanKind: props.spanKind,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -32,7 +32,6 @@ const getTagFilters = async (
|
||||
maxDuration: String((duration.duration || [])[0] || ''),
|
||||
minDuration: String((duration.duration || [])[1] || ''),
|
||||
exclude,
|
||||
spanKind: props.spanKind,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -11,12 +11,9 @@ const getTagValue = async (
|
||||
const response = await axios.post<PayloadProps>(`/getTagValues`, {
|
||||
start: props.start.toString(),
|
||||
end: props.end.toString(),
|
||||
tagKey: {
|
||||
Key: props.tagKey.Key,
|
||||
Type: props.tagKey.Type,
|
||||
},
|
||||
spanKind: props.spanKind,
|
||||
tagKey: props.tagKey,
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
|
||||
@@ -9,9 +9,9 @@ const loginPrecheck = async (
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`/loginPrecheck?email=${encodeURIComponent(
|
||||
props.email,
|
||||
)}&ref=${encodeURIComponent(window.location.href)}`,
|
||||
`/loginPrecheck?email=${props.email}&ref=${encodeURIComponent(
|
||||
window.location.href,
|
||||
)}`,
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,6 +14,7 @@ const signup = async (
|
||||
const response = await axios.post(`/register`, {
|
||||
...props,
|
||||
});
|
||||
console.log(' response.data.data', response.data.data);
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
function Table(): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M41.0667 0H6.39993C2.87982 0 0 2.87982 0 6.39993V41.6001C0 45.1202 2.87982 48 6.39993 48H41.0667C44.5868 48 47.4667 45.1202 47.4667 41.6001V6.39993C47.4667 2.87982 44.5868 0 41.0667 0ZM44.2669 6.39993V9.60013H32.0002V3.2002H41.0668C42.8268 3.2002 44.267 4.63992 44.267 6.40003L44.2669 6.39993ZM17.6002 9.60013V3.2002H29.8669V9.60013H17.6002ZM29.8669 11.7333V44.8001H17.6002L17.6005 11.7333H29.8669ZM6.40012 3.20011H15.4667V9.60004H3.20001V6.39984C3.20001 4.63983 4.64011 3.20001 6.40022 3.20001L6.40012 3.20011ZM3.19992 41.6003V11.7335H15.4666V44.8003H6.40003C4.64002 44.8003 3.19982 43.3606 3.19982 41.6005L3.19992 41.6003ZM41.0667 44.8001H32.0001V11.7333H44.2668V41.6001C44.2668 43.3601 42.8267 44.7999 41.0666 44.7999L41.0667 44.8001ZM5.33326 18.6666C5.33326 18.08 5.81317 17.6001 6.39983 17.6001H12.2667C12.8534 17.6001 13.3333 18.08 13.3333 18.6666C13.3333 19.2533 12.8534 19.7332 12.2667 19.7332H6.39983C5.81315 19.7332 5.33326 19.2533 5.33326 18.6666ZM13.3333 25.0666C13.3333 25.6533 12.8534 26.1332 12.2667 26.1332H6.39983C5.81315 26.1332 5.33326 25.6532 5.33326 25.0666C5.33326 24.4799 5.81317 24 6.39983 24H12.2667C12.8534 24 13.3333 24.4799 13.3333 25.0666ZM13.3333 31.4665C13.3333 32.0532 12.8534 32.5331 12.2667 32.5331H6.39983C5.81315 32.5331 5.33326 32.0532 5.33326 31.4665C5.33326 30.8798 5.81317 30.3999 6.39983 30.3999H12.2667C12.8534 30.3999 13.3333 30.8798 13.3333 31.4665ZM13.3333 37.8668C13.3333 38.4535 12.8534 38.9334 12.2667 38.9334H6.39983C5.81315 38.9334 5.33326 38.4535 5.33326 37.8668C5.33326 37.2801 5.81317 36.8002 6.39983 36.8002H12.2667C12.8534 36.7999 13.3333 37.2802 13.3333 37.8668ZM19.7332 18.6667C19.7332 18.0801 20.2131 17.6002 20.7998 17.6002H26.6667C27.2534 17.6002 27.7333 18.0801 27.7333 18.6667C27.7333 19.2534 27.2533 19.7333 26.6667 19.7333H20.7998C20.2131 19.7333 19.7332 19.2534 19.7332 18.6667ZM19.7332 25.0667C19.7332 24.48 20.2131 24.0001 20.7998 24.0001H26.6667C27.2534 24.0001 27.7333 24.48 27.7333 25.0667C27.7333 25.6534 27.2533 26.1332 26.6667 26.1332H20.7998C20.2131 26.1332 19.7332 25.6533 19.7332 25.0667ZM19.7332 31.4666C19.7332 30.8799 20.2131 30.4 20.7998 30.4H26.6667C27.2534 30.4 27.7333 30.8799 27.7333 31.4666C27.7333 32.0533 27.2533 32.5332 26.6667 32.5332H20.7998C20.2131 32.5336 19.7332 32.0533 19.7332 31.4666ZM27.7333 37.8669C27.7333 38.4536 27.2533 38.9335 26.6667 38.9335H20.7998C20.2131 38.9335 19.7332 38.4536 19.7332 37.8669C19.7332 37.2802 20.2131 36.8003 20.7998 36.8003H26.6667C27.2534 36.8 27.7333 37.2803 27.7333 37.8669ZM42.1333 18.6668C42.1333 19.2535 41.6534 19.7334 41.0667 19.7334H35.1999C34.6132 19.7334 34.1333 19.2535 34.1333 18.6668C34.1333 18.0802 34.6132 17.6003 35.1999 17.6003H41.0667C41.6534 17.6003 42.1333 18.0802 42.1333 18.6668ZM42.1333 25.0668C42.1333 25.6535 41.6534 26.1333 41.0667 26.1333H35.1999C34.6132 26.1333 34.1333 25.6534 34.1333 25.0668C34.1333 24.4801 34.6132 24.0002 35.1999 24.0002H41.0667C41.6534 24.0002 42.1333 24.4801 42.1333 25.0668ZM42.1333 31.4667C42.1333 32.0534 41.6534 32.5333 41.0667 32.5333H35.1999C34.6132 32.5333 34.1333 32.0534 34.1333 31.4667C34.1333 30.88 34.6132 30.4001 35.1999 30.4001H41.0667C41.6534 30.4001 42.1333 30.88 42.1333 31.4667ZM42.1333 37.867C42.1333 38.4537 41.6534 38.9336 41.0667 38.9336H35.1999C34.6132 38.9336 34.1333 38.4537 34.1333 37.867C34.1333 37.2803 34.6132 36.8004 35.1999 36.8004H41.0667C41.6534 36.8001 42.1333 37.2803 42.1333 37.867Z"
|
||||
fill="#1668DC"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default Table;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,22 +1,26 @@
|
||||
function Value(): JSX.Element {
|
||||
import React from 'react';
|
||||
|
||||
function Value(props: ValueProps): JSX.Element {
|
||||
const { fillColor } = props;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width="68"
|
||||
height="48"
|
||||
viewBox="0 0 68 48"
|
||||
width="78"
|
||||
height="32"
|
||||
viewBox="0 0 78 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 5.914V42.086C0 43.6542 0.62289 45.1585 1.73183 46.2675C2.84078 47.3771 4.34511 48 5.91329 48H61.5019C63.0701 48 64.5744 47.3771 65.6834 46.2675C66.7923 45.1585 67.4152 43.6542 67.4152 42.086V5.914C67.4152 4.34578 66.7923 2.84152 65.6834 1.73253C64.5744 0.623576 63.0701 0 61.5019 0H5.91329C4.34508 0 2.84082 0.623576 1.73183 1.73253C0.622872 2.84149 0 4.34581 0 5.914ZM63.4735 5.914V42.086C63.4735 42.6092 63.2659 43.1104 62.896 43.4803C62.5261 43.8495 62.0249 44.0571 61.5024 44.0571H5.91382C4.82549 44.0571 3.94277 43.175 3.94277 42.086V5.91403C3.94277 4.8257 4.82553 3.94298 5.91382 3.94298H61.5024C62.0249 3.94298 62.5261 4.15061 62.896 4.52048C63.2659 4.88968 63.4735 5.39148 63.4735 5.914Z"
|
||||
fill="#1554AD"
|
||||
/>
|
||||
<path
|
||||
d="M13.7695 17.668C10.1016 17.668 7.48828 20.1758 7.48828 23.6094V23.6328C7.48828 26.8438 9.76172 29.2109 13.0078 29.2109C15.3281 29.2109 16.8047 28.0273 17.4258 26.6914H17.6602C17.6602 26.8203 17.6484 26.9492 17.6484 27.0781C17.5195 30.3125 16.3828 32.9375 13.6992 32.9375C12.2109 32.9375 11.168 32.1641 10.7227 30.9805L10.6875 30.8633H7.71094L7.73438 30.9922C8.27344 33.582 10.5938 35.4219 13.6992 35.4219C17.9531 35.4219 20.5195 32.0469 20.5195 26.3516V26.3281C20.5195 20.2344 17.3789 17.668 13.7695 17.668ZM13.7578 26.8906C11.8359 26.8906 10.4414 25.4844 10.4414 23.5273V23.5039C10.4414 21.6172 11.9297 20.1289 13.793 20.1289C15.668 20.1289 17.1328 21.6406 17.1328 23.5742V23.5977C17.1328 25.5078 15.668 26.8906 13.7578 26.8906ZM24.832 35.2344C25.9102 35.2344 26.6953 34.4258 26.6953 33.3828C26.6953 32.3398 25.9102 31.5312 24.832 31.5312C23.7656 31.5312 22.9688 32.3398 22.9688 33.3828C22.9688 34.4258 23.7656 35.2344 24.832 35.2344ZM37.8633 35H40.7578V31.7539H43.0312V29.2578H40.7578V18.0898H36.4805C34.1836 21.582 31.7812 25.4727 29.5898 29.2812V31.7539H37.8633V35ZM32.4023 29.3281V29.1523C34.043 26.2812 36 23.1523 37.7344 20.5039H37.9102V29.3281H32.4023ZM52.6406 35.4219C56.3086 35.4219 58.9219 32.9141 58.9219 29.4805V29.457C58.9219 26.2461 56.6484 23.8789 53.4023 23.8789C51.082 23.8789 49.6055 25.0625 48.9844 26.3984H48.75C48.75 26.2695 48.7617 26.1406 48.7617 26.0117C48.8906 22.7773 50.0273 20.1523 52.7109 20.1523C54.1992 20.1523 55.2422 20.9258 55.6875 22.1094L55.7344 22.2266H58.6992L58.6758 22.0977C58.1367 19.5078 55.8164 17.668 52.7109 17.668C48.457 17.668 45.8906 21.043 45.8906 26.7383V26.7617C45.8906 32.8555 49.0312 35.4219 52.6406 35.4219ZM49.2773 29.5156V29.4922C49.2773 27.582 50.7422 26.1992 52.6523 26.1992C54.5742 26.1992 55.9688 27.6055 55.9688 29.5625V29.5859C55.9688 31.4727 54.4922 32.9609 52.6172 32.9609C50.7422 32.9609 49.2773 31.4492 49.2773 29.5156Z"
|
||||
fill="#1668DC"
|
||||
d="M15.0215 17.875C14.2285 18.8184 13.2783 19.5771 12.1709 20.1514C11.0771 20.7256 9.87402 21.0127 8.56152 21.0127C6.83887 21.0127 5.33496 20.5889 4.0498 19.7412C2.77832 18.8936 1.79395 17.7041 1.09668 16.1729C0.399414 14.6279 0.0507812 12.9258 0.0507812 11.0664C0.0507812 9.07031 0.426758 7.27246 1.17871 5.67285C1.94434 4.07324 3.02441 2.84961 4.41895 2.00195C5.81348 1.1543 7.44043 0.730469 9.2998 0.730469C12.2529 0.730469 14.5771 1.83789 16.2725 4.05273C17.9814 6.25391 18.8359 9.26172 18.8359 13.0762V14.1836C18.8359 19.9941 17.6875 24.2393 15.3906 26.9189C13.0938 29.585 9.62793 30.9521 4.99316 31.0205H4.25488V27.8213H5.05469C8.18555 27.7666 10.5918 26.9531 12.2734 25.3809C13.9551 23.7949 14.8711 21.293 15.0215 17.875ZM9.17676 17.875C10.4482 17.875 11.6172 17.4854 12.6836 16.7061C13.7637 15.9268 14.5498 14.9629 15.042 13.8145V12.2969C15.042 9.80859 14.502 7.78516 13.4219 6.22656C12.3418 4.66797 10.9746 3.88867 9.32031 3.88867C7.65234 3.88867 6.3125 4.53125 5.30078 5.81641C4.28906 7.08789 3.7832 8.76953 3.7832 10.8613C3.7832 12.8984 4.26855 14.5801 5.23926 15.9062C6.22363 17.2188 7.53613 17.875 9.17676 17.875ZM24.5371 29.0107C24.5371 28.3545 24.7285 27.8076 25.1113 27.3701C25.5078 26.9326 26.0957 26.7139 26.875 26.7139C27.6543 26.7139 28.2422 26.9326 28.6387 27.3701C29.0488 27.8076 29.2539 28.3545 29.2539 29.0107C29.2539 29.6396 29.0488 30.166 28.6387 30.5898C28.2422 31.0137 27.6543 31.2256 26.875 31.2256C26.0957 31.2256 25.5078 31.0137 25.1113 30.5898C24.7285 30.166 24.5371 29.6396 24.5371 29.0107ZM51.1562 20.9717H55.2988V24.0684H51.1562V31H47.3418V24.0684H33.7451V21.833L47.1162 1.14062H51.1562V20.9717ZM38.0518 20.9717H47.3418V6.3291L46.8906 7.14941L38.0518 20.9717ZM73.6123 1.12012V4.33984H72.915C69.9619 4.39453 67.6104 5.26953 65.8604 6.96484C64.1104 8.66016 63.0986 11.0459 62.8252 14.1221C64.3975 12.3174 66.5439 11.415 69.2646 11.415C71.8623 11.415 73.9336 12.3311 75.4785 14.1631C77.0371 15.9951 77.8164 18.3604 77.8164 21.2588C77.8164 24.335 76.9756 26.7959 75.2939 28.6416C73.626 30.4873 71.3838 31.4102 68.5674 31.4102C65.71 31.4102 63.3926 30.3164 61.6152 28.1289C59.8379 25.9277 58.9492 23.0977 58.9492 19.6387V18.1826C58.9492 12.6865 60.1182 8.48926 62.4561 5.59082C64.8076 2.67871 68.3008 1.18848 72.9355 1.12012H73.6123ZM68.6289 14.5732C67.3301 14.5732 66.1338 14.9629 65.04 15.7422C63.9463 16.5215 63.1875 17.499 62.7637 18.6748V20.0693C62.7637 22.5303 63.3174 24.5127 64.4248 26.0166C65.5322 27.5205 66.9131 28.2725 68.5674 28.2725C70.2764 28.2725 71.6162 27.6436 72.5869 26.3857C73.5713 25.1279 74.0635 23.4805 74.0635 21.4434C74.0635 19.3926 73.5645 17.7383 72.5664 16.4805C71.582 15.209 70.2695 14.5732 68.6289 14.5732Z"
|
||||
fill={fillColor}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
interface ValueProps {
|
||||
fillColor: React.CSSProperties['color'];
|
||||
}
|
||||
|
||||
export default Value;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
function NotFound(): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
function SomethingWentWrong(): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
function UnAuthorized(): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user