Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14ea7bd86a | ||
|
|
8bf0123370 | ||
|
|
dc9ffcdd45 | ||
|
|
c79223742f | ||
|
|
d9a99827c0 | ||
|
|
1bf6faff8b | ||
|
|
95fb068bb0 | ||
|
|
0907ed280b | ||
|
|
fc7a0a8354 | ||
|
|
b27e30db58 | ||
|
|
1ab291f3e8 | ||
|
|
552d193cef | ||
|
|
ba0f06f381 | ||
|
|
bbbb1c1d60 | ||
|
|
32a09d4ca2 | ||
|
|
7ae43cf511 | ||
|
|
d1887fdbfe | ||
|
|
5414a73b40 | ||
|
|
7f116d1597 | ||
|
|
2c1b530aa0 | ||
|
|
231b8467fd | ||
|
|
24910f6a39 | ||
|
|
03bf9afe03 | ||
|
|
fbf047a477 | ||
|
|
afc0559456 | ||
|
|
34e9247562 | ||
|
|
bbd90bff0c | ||
|
|
3e0f5a866d | ||
|
|
fb634303e8 | ||
|
|
5e828bf174 | ||
|
|
8f2ed0e46f | ||
|
|
19b25219f4 | ||
|
|
447700326a | ||
|
|
3ed4fb2b75 | ||
|
|
32750fa2af | ||
|
|
47b0671b27 | ||
|
|
9bc62d83d3 | ||
|
|
5e4cff7ae2 | ||
|
|
271ffbd1a1 | ||
|
|
5b691d26e4 | ||
|
|
6b6070fd45 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,6 +14,8 @@ frontend/coverage
|
||||
frontend/build
|
||||
frontend/.vscode
|
||||
frontend/.yarnclean
|
||||
frontend/.temp_cache
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
@@ -33,7 +35,6 @@ frontend/cypress.env.json
|
||||
.idea
|
||||
|
||||
**/.vscode
|
||||
*.tgz
|
||||
**/build
|
||||
**/storage
|
||||
**/locust-scripts/__pycache__/
|
||||
|
||||
@@ -16,7 +16,10 @@ Need to update [https://github.com/SigNoz/signoz/tree/main/frontend](https://git
|
||||
|
||||
- `git clone https://github.com/SigNoz/signoz.git && cd signoz`
|
||||
- comment out frontend service section at `deploy/docker/clickhouse-setup/docker-compose.yaml#L38`
|
||||
- run `cd deploy && docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d` (this will install signoz locally without the frontend service)
|
||||
- run `cd deploy` to move to deploy directory
|
||||
- Install signoz locally without the frontend
|
||||
- If you are using x86_64 processors (All Intel/AMD processors) run `sudo docker-compose --env-file ./docker/clickhouse-setup/env/x86_64.env -f docker/clickhouse-setup/docker-compose.yaml up -d`
|
||||
- If you are on arm64 processors (Apple M1 Macbooks) run `sudo docker-compose --env-file ./docker/clickhouse-setup/env/arm64.env -f docker/clickhouse-setup/docker-compose.yaml up -d`
|
||||
- `cd ../frontend` and change baseURL to `http://localhost:8080` in file `src/constants/env.ts`
|
||||
- `yarn install`
|
||||
- `yarn dev`
|
||||
@@ -41,7 +44,9 @@ Need to update [https://github.com/SigNoz/signoz/tree/main/pkg/query-service](ht
|
||||
- `git clone https://github.com/SigNoz/signoz.git && cd signoz/deploy`
|
||||
- comment out frontend service section at `docker/clickhouse-setup/docker-compose.yaml#L38`
|
||||
- comment out query-service section at `docker/clickhouse-setup/docker-compose.yaml#L22`
|
||||
- Run `docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d` (this will install signoz locally without the frontend and query-service)
|
||||
- Install signoz locally without the frontend and query-service
|
||||
- If you are using x86_64 processors (All Intel/AMD processors) run `sudo docker-compose --env-file ./docker/clickhouse-setup/env/x86_64.env -f docker/clickhouse-setup/docker-compose.yaml up -d`
|
||||
- If you are on arm64 processors (Apple M1 Macbooks) run `sudo docker-compose --env-file ./docker/clickhouse-setup/env/arm64.env -f docker/clickhouse-setup/docker-compose.yaml up -d`
|
||||
- `STORAGE=clickhouse ClickHouseUrl=tcp://localhost:9001 go run main.go`
|
||||
|
||||
**_Query Service should now be available at `http://localhost:8080`_**
|
||||
|
||||
@@ -2,7 +2,7 @@ version: "2.4"
|
||||
|
||||
services:
|
||||
clickhouse:
|
||||
image: yandex/clickhouse-server
|
||||
image: ${clickhouse_image}
|
||||
expose:
|
||||
- 8123
|
||||
- 9000
|
||||
@@ -33,7 +33,7 @@ services:
|
||||
- 9093:9093
|
||||
|
||||
query-service:
|
||||
image: signoz/query-service:0.5.0
|
||||
image: signoz/query-service:0.5.3
|
||||
container_name: query-service
|
||||
command: ["-config=/root/config/prometheus.yml"]
|
||||
ports:
|
||||
@@ -54,7 +54,7 @@ services:
|
||||
condition: service_healthy
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:0.5.0
|
||||
image: signoz/frontend:0.5.3
|
||||
container_name: frontend
|
||||
|
||||
depends_on:
|
||||
|
||||
1
deploy/docker/clickhouse-setup/env/arm64.env
vendored
Normal file
1
deploy/docker/clickhouse-setup/env/arm64.env
vendored
Normal file
@@ -0,0 +1 @@
|
||||
clickhouse_image=altinity/clickhouse-server:21.8.12.1.testingarm
|
||||
1
deploy/docker/clickhouse-setup/env/x86_64.env
vendored
Normal file
1
deploy/docker/clickhouse-setup/env/x86_64.env
vendored
Normal file
@@ -0,0 +1 @@
|
||||
clickhouse_image=yandex/clickhouse-server
|
||||
@@ -9,7 +9,7 @@ receivers:
|
||||
config:
|
||||
scrape_configs:
|
||||
- job_name: "otel-collector"
|
||||
scrape_interval: 60s
|
||||
scrape_interval: 30s
|
||||
static_configs:
|
||||
- targets: ["otel-collector:8889"]
|
||||
processors:
|
||||
|
||||
@@ -36,6 +36,10 @@ is_mac() {
|
||||
[[ $OSTYPE == darwin* ]]
|
||||
}
|
||||
|
||||
is_arm64(){
|
||||
[[ `uname -m` == 'arm64' ]]
|
||||
}
|
||||
|
||||
check_os() {
|
||||
if is_mac; then
|
||||
package_manager="brew"
|
||||
@@ -267,7 +271,11 @@ bye() { # Prints a friendly good bye message and exits the script.
|
||||
echo "🔴 The containers didn't seem to start correctly. Please run the following command to check containers that may have errored out:"
|
||||
echo ""
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
echo -e "sudo docker-compose -f docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
if is_arm64; then
|
||||
echo -e "sudo docker-compose --env-file ./docker/clickhouse-setup/env/arm64.env -f docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
else
|
||||
echo -e "sudo docker-compose --env-file ./docker/clickhouse-setup/env/x86_64.env -f docker/clickhouse-setup/docker-compose.yaml ps -a"
|
||||
fi
|
||||
else
|
||||
echo -e "sudo docker-compose -f docker/druid-kafka-setup/docker-compose-tiny.yaml ps -a"
|
||||
fi
|
||||
@@ -408,7 +416,11 @@ start_docker
|
||||
echo ""
|
||||
echo -e "\n🟡 Pulling the latest container images for SigNoz. To run as sudo it may ask for system password\n"
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
sudo docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml pull
|
||||
if is_arm64; then
|
||||
sudo docker-compose --env-file ./docker/clickhouse-setup/env/arm64.env -f ./docker/clickhouse-setup/docker-compose.yaml pull
|
||||
else
|
||||
sudo docker-compose --env-file ./docker/clickhouse-setup/env/x86_64.env -f ./docker/clickhouse-setup/docker-compose.yaml pull
|
||||
fi
|
||||
else
|
||||
sudo docker-compose -f ./docker/druid-kafka-setup/docker-compose-tiny.yaml pull
|
||||
fi
|
||||
@@ -420,7 +432,11 @@ echo
|
||||
# The docker-compose command does some nasty stuff for the `--detach` functionality. So we add a `|| true` so that the
|
||||
# script doesn't exit because this command looks like it failed to do it's thing.
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
sudo docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml up --detach --remove-orphans || true
|
||||
if is_arm64; then
|
||||
sudo docker-compose --env-file ./docker/clickhouse-setup/env/arm64.env -f ./docker/clickhouse-setup/docker-compose.yaml up --detach --remove-orphans || true
|
||||
else
|
||||
sudo docker-compose --env-file ./docker/clickhouse-setup/env/x86_64.env -f ./docker/clickhouse-setup/docker-compose.yaml up --detach --remove-orphans || true
|
||||
fi
|
||||
else
|
||||
sudo docker-compose -f ./docker/druid-kafka-setup/docker-compose-tiny.yaml up --detach --remove-orphans || true
|
||||
fi
|
||||
@@ -480,7 +496,7 @@ else
|
||||
echo ""
|
||||
|
||||
if [ $setup_type == 'clickhouse' ]; then
|
||||
echo "ℹ️ To bring down SigNoz and clean volumes : sudo docker-compose -f docker/clickhouse-setup/docker-compose.yaml down -v"
|
||||
echo "ℹ️ To bring down SigNoz and clean volumes : sudo docker-compose --env-file ./docker/clickhouse-setup/env/arm64.env -f docker/clickhouse-setup/docker-compose.yaml down -v"
|
||||
else
|
||||
echo "ℹ️ To bring down SigNoz and clean volumes : sudo docker-compose -f docker/druid-kafka-setup/docker-compose-tiny.yaml down -v"
|
||||
fi
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: retention-config
|
||||
data:
|
||||
retention-spec.json: |
|
||||
[{"period":"P3D","includeFuture":true,"tieredReplicants":{"_default_tier":1},"type":"loadByPeriod"},{"type":"dropForever"}]
|
||||
@@ -1,29 +0,0 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: set-retention
|
||||
annotations:
|
||||
"helm.sh/hook": post-install,post-upgrade
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 100
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: set-retention
|
||||
image: theithollow/hollowapp-blog:curl
|
||||
volumeMounts:
|
||||
- name: retention-config-volume
|
||||
mountPath: /app/retention-spec.json
|
||||
subPath: retention-spec.json
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- "curl -X POST -H 'Content-Type: application/json' -d @/app/retention-spec.json http://signoz-druid-router:8888/druid/coordinator/v1/rules/flattened_spans"
|
||||
|
||||
volumes:
|
||||
- name: retention-config-volume
|
||||
configMap:
|
||||
name: retention-config
|
||||
|
||||
restartPolicy: Never
|
||||
backoffLimit: 8
|
||||
@@ -1,76 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: supervisor-config
|
||||
data:
|
||||
supervisor-spec.json: |
|
||||
{
|
||||
"type": "kafka",
|
||||
"dataSchema": {
|
||||
"dataSource": "flattened_spans",
|
||||
"parser": {
|
||||
"type": "string",
|
||||
"parseSpec": {
|
||||
"format": "json",
|
||||
"timestampSpec": {
|
||||
"column": "StartTimeUnixNano",
|
||||
"format": "nano"
|
||||
},
|
||||
"dimensionsSpec": {
|
||||
"dimensions": [
|
||||
"TraceId",
|
||||
"SpanId",
|
||||
"ParentSpanId",
|
||||
"Name",
|
||||
"ServiceName",
|
||||
"References",
|
||||
"Tags",
|
||||
"ExternalHttpMethod",
|
||||
"ExternalHttpUrl",
|
||||
"Component",
|
||||
"DBSystem",
|
||||
"DBName",
|
||||
"DBOperation",
|
||||
"PeerService",
|
||||
{
|
||||
"type": "string",
|
||||
"name": "TagsKeys",
|
||||
"multiValueHandling": "ARRAY"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "TagsValues",
|
||||
"multiValueHandling": "ARRAY"
|
||||
},
|
||||
{ "name": "DurationNano", "type": "Long" },
|
||||
{ "name": "Kind", "type": "int" },
|
||||
{ "name": "StatusCode", "type": "int" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"metricsSpec" : [
|
||||
{ "type": "quantilesDoublesSketch", "name": "QuantileDuration", "fieldName": "DurationNano" }
|
||||
],
|
||||
"granularitySpec": {
|
||||
"type": "uniform",
|
||||
"segmentGranularity": "DAY",
|
||||
"queryGranularity": "NONE",
|
||||
"rollup": false
|
||||
}
|
||||
},
|
||||
"tuningConfig": {
|
||||
"type": "kafka",
|
||||
"reportParseExceptions": true
|
||||
},
|
||||
"ioConfig": {
|
||||
"topic": "flattened_spans",
|
||||
"replicas": 1,
|
||||
"taskDuration": "PT20M",
|
||||
"completionTimeout": "PT30M",
|
||||
"consumerProperties": {
|
||||
"bootstrap.servers": "signoz-kafka:9092"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: create-supervisor
|
||||
annotations:
|
||||
"helm.sh/hook": post-install,post-upgrade
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 100
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: create-supervisor
|
||||
image: theithollow/hollowapp-blog:curl
|
||||
volumeMounts:
|
||||
- name: supervisor-config-volume
|
||||
mountPath: /app/supervisor-spec.json
|
||||
subPath: supervisor-spec.json
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- "curl -X POST -H 'Content-Type: application/json' -d @/app/supervisor-spec.json http://signoz-druid-router:8888/druid/indexer/v1/supervisor"
|
||||
volumes:
|
||||
- name: supervisor-config-volume
|
||||
configMap:
|
||||
name: supervisor-config
|
||||
restartPolicy: Never
|
||||
backoffLimit: 8
|
||||
@@ -1,60 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: otel-collector-conf
|
||||
labels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-conf
|
||||
data:
|
||||
otel-collector-config: |
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
jaeger:
|
||||
protocols:
|
||||
grpc:
|
||||
thrift_http:
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
memory_limiter:
|
||||
# Same as --mem-ballast-size-mib CLI argument
|
||||
ballast_size_mib: 683
|
||||
# 80% of maximum memory up to 2G
|
||||
limit_mib: 1500
|
||||
# 25% of limit up to 2G
|
||||
spike_limit_mib: 512
|
||||
check_interval: 5s
|
||||
queued_retry:
|
||||
num_workers: 4
|
||||
queue_size: 100
|
||||
retry_on_failure: true
|
||||
extensions:
|
||||
health_check: {}
|
||||
zpages: {}
|
||||
exporters:
|
||||
kafka/traces:
|
||||
brokers:
|
||||
- signoz-kafka:9092
|
||||
topic: 'otlp_spans'
|
||||
protocol_version: 2.0.0
|
||||
|
||||
kafka/metrics:
|
||||
brokers:
|
||||
- signoz-kafka:9092
|
||||
topic: 'otlp_metrics'
|
||||
protocol_version: 2.0.0
|
||||
service:
|
||||
extensions: [health_check, zpages]
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [jaeger, otlp]
|
||||
processors: [memory_limiter, batch, queued_retry]
|
||||
exporters: [kafka/traces]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [kafka/metrics]
|
||||
@@ -2,20 +2,14 @@ dependencies:
|
||||
- name: zookeeper
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 6.0.0
|
||||
- name: kafka
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 12.0.0
|
||||
- name: druid
|
||||
repository: https://charts.helm.sh/incubator
|
||||
version: 0.2.18
|
||||
- name: flattener-processor
|
||||
repository: file://./signoz-charts/flattener-processor
|
||||
version: 0.3.6
|
||||
- name: query-service
|
||||
repository: file://./signoz-charts/query-service
|
||||
version: 0.3.6
|
||||
version: 0.5.3
|
||||
- name: frontend
|
||||
repository: file://./signoz-charts/frontend
|
||||
version: 0.3.6
|
||||
digest: sha256:b160e903c630a90644683c512eb8ba018e18d2c08051e255edd3749cb9cc7228
|
||||
generated: "2021-08-23T12:06:37.231066+05:30"
|
||||
version: 0.5.3
|
||||
- name: alertmanager
|
||||
repository: file://./signoz-charts/alertmanager
|
||||
version: 0.5.0
|
||||
digest: sha256:891df4e1a3d9fc7bf2b4b67beb4e505f1ec4da20952c2e294ad8b16fcc4eccb7
|
||||
generated: "2021-12-11T11:40:26.756851+05:30"
|
||||
|
||||
@@ -15,29 +15,23 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.3.2
|
||||
version: 0.5.3
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 0.3.2
|
||||
appVersion: 0.5.3
|
||||
|
||||
dependencies:
|
||||
- name: zookeeper
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
version: 6.0.0
|
||||
- name: kafka
|
||||
repository: "https://charts.bitnami.com/bitnami"
|
||||
version: 12.0.0
|
||||
- name: druid
|
||||
repository: "https://charts.helm.sh/incubator"
|
||||
version: 0.2.18
|
||||
- name: flattener-processor
|
||||
repository: "file://./signoz-charts/flattener-processor"
|
||||
version: 0.3.6
|
||||
- name: query-service
|
||||
repository: "file://./signoz-charts/query-service"
|
||||
version: 0.3.6
|
||||
version: 0.5.3
|
||||
- name: frontend
|
||||
repository: "file://./signoz-charts/frontend"
|
||||
version: 0.3.6
|
||||
version: 0.5.3
|
||||
- name: alertmanager
|
||||
repository: "file://./signoz-charts/alertmanager"
|
||||
version: 0.5.0
|
||||
BIN
deploy/kubernetes/platform/charts/alertmanager-0.5.0.tgz
Normal file
BIN
deploy/kubernetes/platform/charts/alertmanager-0.5.0.tgz
Normal file
Binary file not shown.
BIN
deploy/kubernetes/platform/charts/frontend-0.5.3.tgz
Normal file
BIN
deploy/kubernetes/platform/charts/frontend-0.5.3.tgz
Normal file
Binary file not shown.
BIN
deploy/kubernetes/platform/charts/query-service-0.5.3.tgz
Normal file
BIN
deploy/kubernetes/platform/charts/query-service-0.5.3.tgz
Normal file
Binary file not shown.
BIN
deploy/kubernetes/platform/charts/zookeeper-6.0.0.tgz
Normal file
BIN
deploy/kubernetes/platform/charts/zookeeper-6.0.0.tgz
Normal file
Binary file not shown.
1223
deploy/kubernetes/platform/crds/clickhouse-operator-install.yaml
Normal file
1223
deploy/kubernetes/platform/crds/clickhouse-operator-install.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,3 +21,5 @@
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
|
||||
unittests/
|
||||
@@ -0,0 +1,7 @@
|
||||
apiVersion: v2
|
||||
name: alertmanager
|
||||
description: The Alertmanager handles alerts sent by client applications such as the Prometheus server.
|
||||
type: application
|
||||
version: 0.5.0
|
||||
appVersion: 0.5.0
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
configmapReload:
|
||||
enabled: true
|
||||
@@ -2,20 +2,20 @@
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "flattener-processor.fullname" . }})
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "alertmanager.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "flattener-processor.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "flattener-processor.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "alertmanager.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "alertmanager.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "flattener-processor.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "alertmanager.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
echo "Visit http://127.0.0.1:{{ .Values.service.port }} to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME {{ .Values.service.port }}:80
|
||||
{{- end }}
|
||||
@@ -2,7 +2,7 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "flattener-processor.name" -}}
|
||||
{{- define "alertmanager.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -11,7 +11,7 @@ Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "flattener-processor.fullname" -}}
|
||||
{{- define "alertmanager.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
@@ -27,16 +27,16 @@ If release name contains chart name it will be used as a full name.
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "flattener-processor.chart" -}}
|
||||
{{- define "alertmanager.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "flattener-processor.labels" -}}
|
||||
helm.sh/chart: {{ include "flattener-processor.chart" . }}
|
||||
{{ include "flattener-processor.selectorLabels" . }}
|
||||
{{- define "alertmanager.labels" -}}
|
||||
helm.sh/chart: {{ include "alertmanager.chart" . }}
|
||||
{{ include "alertmanager.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
@@ -46,17 +46,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "flattener-processor.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "flattener-processor.name" . }}
|
||||
{{- define "alertmanager.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "alertmanager.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "flattener-processor.serviceAccountName" -}}
|
||||
{{- define "alertmanager.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "flattener-processor.fullname" .) .Values.serviceAccount.name }}
|
||||
{{ default (include "alertmanager.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.config }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "alertmanager.fullname" . }}
|
||||
labels:
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
data:
|
||||
alertmanager.yml: |
|
||||
{{- toYaml .Values.config | default "{}" | nindent 4 }}
|
||||
{{- range $key, $value := .Values.templates }}
|
||||
{{ $key }}: |-
|
||||
{{- $value | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,61 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "alertmanager.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.podDisruptionBudget -}}
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: {{ template "alertmanager.fullname" . }}
|
||||
labels:
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "alertmanager.selectorLabels" . | nindent 6 }}
|
||||
{{ toYaml .Values.podDisruptionBudget | indent 2 }}
|
||||
{{- end -}}
|
||||
@@ -2,9 +2,9 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "flattener-processor.serviceAccountName" . }}
|
||||
name: {{ include "alertmanager.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "flattener-processor.labels" . | nindent 4 }}
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
@@ -0,0 +1,48 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: alertmanager
|
||||
labels:
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
{{- if .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml .Values.service.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- if (and (eq .Values.service.type "NodePort") .Values.service.nodePort) }}
|
||||
nodePort: {{ .Values.service.nodePort }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "alertmanager.selectorLabels" . | nindent 4 }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "alertmanager.fullname" . }}-headless
|
||||
labels:
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- if or (gt .Values.replicaCount 1.0) (.Values.additionalPeers) }}
|
||||
- port: 9094
|
||||
targetPort: 9094
|
||||
protocol: TCP
|
||||
name: cluster-tcp
|
||||
- port: 9094
|
||||
targetPort: 9094
|
||||
protocol: UDP
|
||||
name: cluster-udp
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "alertmanager.selectorLabels" . | nindent 4 }}
|
||||
@@ -0,0 +1,152 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "alertmanager.fullname" . }}
|
||||
labels:
|
||||
{{- include "alertmanager.labels" . | nindent 4 }}
|
||||
{{- if .Values.statefulSet.annotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.statefulSet.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "alertmanager.selectorLabels" . | nindent 6 }}
|
||||
serviceName: {{ include "alertmanager.fullname" . }}-headless
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "alertmanager.selectorLabels" . | nindent 8 }}
|
||||
{{- if .Values.podLabels }}
|
||||
{{ toYaml .Values.podLabels | nindent 8 }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- if not .Values.configmapReload.enabled }}
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if .Values.podAnnotations }}
|
||||
{{- toYaml .Values.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "alertmanager.serviceAccountName" . }}
|
||||
{{- with .Values.dnsConfig }}
|
||||
dnsConfig:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
{{- if and (.Values.configmapReload.enabled) (.Values.config) }}
|
||||
- name: {{ .Chart.Name }}-{{ .Values.configmapReload.name }}
|
||||
image: "{{ .Values.configmapReload.image.repository }}:{{ .Values.configmapReload.image.tag }}"
|
||||
imagePullPolicy: "{{ .Values.configmapReload.image.pullPolicy }}"
|
||||
args:
|
||||
- --volume-dir=/etc/alertmanager
|
||||
- --webhook-url=http://127.0.0.1:{{ .Values.service.port }}/-/reload
|
||||
resources:
|
||||
{{- toYaml .Values.configmapReload.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/alertmanager
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
env:
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: status.podIP
|
||||
{{- if .Values.command }}
|
||||
command:
|
||||
{{- toYaml .Values.command | nindent 12 }}
|
||||
{{- end }}
|
||||
args:
|
||||
- --storage.path=/alertmanager
|
||||
- --config.file=/etc/alertmanager/alertmanager.yml
|
||||
{{- if or (gt .Values.replicaCount 1.0) (.Values.additionalPeers) }}
|
||||
- --cluster.advertise-address=$(POD_IP):9094
|
||||
- --cluster.listen-address=0.0.0.0:9094
|
||||
{{- end }}
|
||||
{{- if gt .Values.replicaCount 1.0}}
|
||||
{{- $fullName := include "alertmanager.fullname" . }}
|
||||
{{- range $i := until (int .Values.replicaCount) }}
|
||||
- --cluster.peer={{ $fullName }}-{{ $i }}.{{ $fullName }}-headless:9094
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.additionalPeers }}
|
||||
{{- range $item := .Values.additionalPeers }}
|
||||
- --cluster.peer={{ $item }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.extraArgs }}
|
||||
- --{{ $key }}={{ $value }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 9093
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
{{- if .Values.config }}
|
||||
- name: config
|
||||
mountPath: /etc/alertmanager
|
||||
{{- end }}
|
||||
- name: storage
|
||||
mountPath: /alertmanager
|
||||
{{- if .Values.config }}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ include "alertmanager.fullname" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.persistence.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: storage
|
||||
spec:
|
||||
accessModes:
|
||||
{{- toYaml .Values.persistence.accessModes | nindent 10 }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.size }}
|
||||
{{- if .Values.persistence.storageClass }}
|
||||
{{- if (eq "-" .Values.persistence.storageClass) }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: {{ .Values.persistence.storageClass }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- name: storage
|
||||
emptyDir: {}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,48 @@
|
||||
should match snapshot of default values:
|
||||
1: |
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: RELEASE-NAME
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: alertmanager
|
||||
app.kubernetes.io/version: 1.0.0
|
||||
helm.sh/chart: alertmanager-1.0.0
|
||||
name: RELEASE-NAME-alertmanager
|
||||
spec:
|
||||
ingressClassName: nginx-test
|
||||
rules:
|
||||
- host: alertmanager.domain.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: RELEASE-NAME-alertmanager
|
||||
port:
|
||||
number: 9093
|
||||
path: /
|
||||
pathType: ImplementationSpecific
|
||||
should match snapshot of default values with old kubernetes ingress:
|
||||
1: |
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx-test
|
||||
labels:
|
||||
app.kubernetes.io/instance: RELEASE-NAME
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: alertmanager
|
||||
app.kubernetes.io/version: 1.0.0
|
||||
helm.sh/chart: alertmanager-1.0.0
|
||||
name: RELEASE-NAME-alertmanager
|
||||
spec:
|
||||
rules:
|
||||
- host: alertmanager.domain.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: RELEASE-NAME-alertmanager
|
||||
servicePort: 9093
|
||||
path: /
|
||||
@@ -0,0 +1,81 @@
|
||||
suite: test ingress
|
||||
templates:
|
||||
- ingress.yaml
|
||||
tests:
|
||||
- it: should be empty if ingress is not enabled
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
- it: should have apiVersion extensions/v1beta1 for k8s < 1.14
|
||||
set:
|
||||
ingress.enabled: true
|
||||
capabilities:
|
||||
majorVersion: 1
|
||||
minorVersion: 13
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- isKind:
|
||||
of: Ingress
|
||||
- isAPIVersion:
|
||||
of: extensions/v1beta1
|
||||
- it: should have apiVersion networking.k8s.io/v1beta1 for k8s < 1.19
|
||||
set:
|
||||
ingress.enabled: true
|
||||
capabilities:
|
||||
majorVersion: 1
|
||||
minorVersion: 18
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- isKind:
|
||||
of: Ingress
|
||||
- isAPIVersion:
|
||||
of: networking.k8s.io/v1beta1
|
||||
- it: should have apiVersion networking.k8s.io/v1 for k8s >= 1.19
|
||||
set:
|
||||
ingress.enabled: true
|
||||
capabilities:
|
||||
majorVersion: 1
|
||||
minorVersion: 19
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- isKind:
|
||||
of: Ingress
|
||||
- isAPIVersion:
|
||||
of: networking.k8s.io/v1
|
||||
- it: should have an ingressClassName for k8s >= 1.19
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.className: nginx-test
|
||||
capabilities:
|
||||
majorVersion: 1
|
||||
minorVersion: 19
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: spec.ingressClassName
|
||||
value: nginx-test
|
||||
- it: should match snapshot of default values
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.className: nginx-test
|
||||
chart:
|
||||
version: 1.0.0
|
||||
appVersion: 1.0.0
|
||||
asserts:
|
||||
- matchSnapshot: { }
|
||||
- it: should match snapshot of default values with old kubernetes ingress
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.className: nginx-test
|
||||
capabilities:
|
||||
majorVersion: 1
|
||||
minorVersion: 17
|
||||
chart:
|
||||
version: 1.0.0
|
||||
appVersion: 1.0.0
|
||||
asserts:
|
||||
- matchSnapshot: { }
|
||||
@@ -0,0 +1,189 @@
|
||||
# Default values for alertmanager.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: signoz/alertmanager
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: "0.5.0"
|
||||
|
||||
extraArgs: {}
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name:
|
||||
|
||||
podSecurityContext:
|
||||
fsGroup: 65534
|
||||
dnsConfig: {}
|
||||
# nameservers:
|
||||
# - 1.2.3.4
|
||||
# searches:
|
||||
# - ns1.svc.cluster-domain.example
|
||||
# - my.dns.search.suffix
|
||||
# options:
|
||||
# - name: ndots
|
||||
# value: "2"
|
||||
# - name: edns0
|
||||
securityContext:
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
runAsUser: 65534
|
||||
runAsNonRoot: true
|
||||
runAsGroup: 65534
|
||||
|
||||
additionalPeers: []
|
||||
|
||||
service:
|
||||
annotations: {}
|
||||
type: ClusterIP
|
||||
port: 9093
|
||||
# if you want to force a specific nodePort. Must be use with service.type=NodePort
|
||||
# nodePort:
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: alertmanager.domain.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - alertmanager.domain.com
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 10m
|
||||
# memory: 32Mi
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
statefulSet:
|
||||
annotations: {}
|
||||
|
||||
podAnnotations: {}
|
||||
podLabels: {}
|
||||
|
||||
# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
|
||||
podDisruptionBudget: {}
|
||||
# maxUnavailable: 1
|
||||
# minAvailable: 1
|
||||
|
||||
command: []
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
## Persistent Volume Storage Class
|
||||
## If defined, storageClassName: <storageClass>
|
||||
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||
## If undefined (the default) or set to null, no storageClassName spec is
|
||||
## set, choosing the default provisioner.
|
||||
##
|
||||
# storageClass: "-"
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
size: 100Mi
|
||||
|
||||
config:
|
||||
global:
|
||||
resolve_timeout: 1m
|
||||
slack_api_url: 'https://hooks.slack.com/services/xxx'
|
||||
|
||||
templates:
|
||||
- '/etc/alertmanager/*.tmpl'
|
||||
|
||||
receivers:
|
||||
- name: 'slack-notifications'
|
||||
slack_configs:
|
||||
- channel: '#alerts'
|
||||
send_resolved: true
|
||||
icon_url: https://avatars3.githubusercontent.com/u/3380462
|
||||
title: '{{ template "slack.title" . }}'
|
||||
text: '{{ template "slack.text" . }}'
|
||||
|
||||
|
||||
route:
|
||||
receiver: 'slack-notifications'
|
||||
|
||||
## Monitors ConfigMap changes and POSTs to a URL
|
||||
## Ref: https://github.com/jimmidyson/configmap-reload
|
||||
##
|
||||
configmapReload:
|
||||
## If false, the configmap-reload container will not be deployed
|
||||
##
|
||||
enabled: false
|
||||
|
||||
## configmap-reload container name
|
||||
##
|
||||
name: configmap-reload
|
||||
|
||||
## configmap-reload container image
|
||||
##
|
||||
image:
|
||||
repository: jimmidyson/configmap-reload
|
||||
tag: v0.5.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
## configmap-reload resource requests and limits
|
||||
## Ref: http://kubernetes.io/docs/user-guide/compute-resources/
|
||||
##
|
||||
resources: {}
|
||||
|
||||
templates:
|
||||
title.tmpl: |-
|
||||
{{ define "slack.title" }}
|
||||
[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}
|
||||
{{- if gt (len .CommonLabels) (len .GroupLabels) -}}
|
||||
{{" "}}(
|
||||
{{- with .CommonLabels.Remove .GroupLabels.Names }}
|
||||
{{- range $index, $label := .SortedPairs -}}
|
||||
{{ if $index }}, {{ end }}
|
||||
{{- $label.Name }}="{{ $label.Value -}}"
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
)
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
text.tmpl: |-
|
||||
{{ define "slack.text" }}
|
||||
{{ range .Alerts -}}
|
||||
*Alert:* {{ .Annotations.title }}{{ if .Labels.severity }} - `{{ .Labels.severity }}`{{ end }}
|
||||
|
||||
*Description:* {{ .Annotations.description }}
|
||||
|
||||
*Details:*
|
||||
{{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
@@ -1,21 +0,0 @@
|
||||
apiVersion: v2
|
||||
name: flattener-processor
|
||||
description: A Helm chart for Kubernetes
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.3.6
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: 0.3.6
|
||||
@@ -1,65 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "flattener-processor.fullname" . }}
|
||||
labels:
|
||||
{{- include "flattener-processor.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "flattener-processor.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "flattener-processor.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "flattener-processor.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
- "/root/flattener"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: KAFKA_BROKER
|
||||
value: {{ .Values.configVars.KAFKA_BROKER }}
|
||||
- name: KAFKA_INPUT_TOPIC
|
||||
value: {{ .Values.configVars.KAFKA_INPUT_TOPIC }}
|
||||
- name: KAFKA_OUTPUT_TOPIC
|
||||
value: {{ .Values.configVars.KAFKA_OUTPUT_TOPIC }}
|
||||
|
||||
# livenessProbe:
|
||||
# httpGet:
|
||||
# path: /
|
||||
# port: http
|
||||
# readinessProbe:
|
||||
# httpGet:
|
||||
# path: /
|
||||
# port: http
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -1,41 +0,0 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "flattener-processor.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "flattener-processor.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ . }}
|
||||
backend:
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,15 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "flattener-processor.fullname" . }}
|
||||
labels:
|
||||
{{- include "flattener-processor.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "flattener-processor.selectorLabels" . | nindent 4 }}
|
||||
@@ -1,15 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "flattener-processor.fullname" . }}-test-connection"
|
||||
labels:
|
||||
{{- include "flattener-processor.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test-success
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "flattener-processor.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
||||
@@ -1,74 +0,0 @@
|
||||
# Default values for flattener-processor.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: signoz/flattener-processor
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
|
||||
configVars:
|
||||
KAFKA_BROKER: signoz-kafka:9092
|
||||
KAFKA_INPUT_TOPIC: otlp_spans
|
||||
KAFKA_OUTPUT_TOPIC: flattened_spans
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: false
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name:
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8080
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths: []
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
@@ -14,8 +14,8 @@ type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.3.6
|
||||
version: 0.5.3
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: 0.3.6
|
||||
appVersion: 0.5.3
|
||||
|
||||
@@ -24,6 +24,9 @@ data:
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
location /api/alertmanager{
|
||||
proxy_pass http://{{ .Values.config.alertmanagerUrl }}/api/v2;
|
||||
}
|
||||
location /api {
|
||||
proxy_pass http://{{ .Values.config.queryServiceUrl }}/api;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ configVars: {}
|
||||
config:
|
||||
name: signoz-nginx-config
|
||||
queryServiceUrl: signoz-query-service:8080
|
||||
alertmanagerUrl: alertmanager:9093
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
|
||||
@@ -14,8 +14,8 @@ type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
version: 0.3.6
|
||||
version: 0.5.3
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application.
|
||||
appVersion: 0.3.6
|
||||
appVersion: 0.5.3
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: prometheus-config
|
||||
data:
|
||||
prometheus.yml: |
|
||||
# my global config
|
||||
global:
|
||||
scrape_interval: 5s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
|
||||
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
|
||||
# scrape_timeout is set to the global default (10s).
|
||||
|
||||
# Alertmanager configuration
|
||||
alerting:
|
||||
alertmanagers:
|
||||
- static_configs:
|
||||
- targets:
|
||||
- alertmanager:9093
|
||||
|
||||
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
|
||||
rule_files:
|
||||
# - "first_rules.yml"
|
||||
# - "second_rules.yml"
|
||||
- 'alerts.yml'
|
||||
|
||||
# A scrape configuration containing exactly one endpoint to scrape:
|
||||
# Here it's Prometheus itself.
|
||||
scrape_configs:
|
||||
|
||||
|
||||
remote_read:
|
||||
- url: tcp://signoz-clickhouse:9000/?database=signoz_metrics&username=clickhouse_operator&password=clickhouse_operator_password
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "query-service.fullname" . }}
|
||||
labels:
|
||||
{{- include "query-service.labels" . | nindent 4 }}
|
||||
spec:
|
||||
serviceName: query-service
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
@@ -14,19 +15,17 @@ spec:
|
||||
labels:
|
||||
{{- include "query-service.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "query-service.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
args: ["-config=/root/config/prometheus.yml"]
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
@@ -38,7 +37,10 @@ spec:
|
||||
value: {{ .Values.configVars.DruidDatasource }}
|
||||
- name: STORAGE
|
||||
value: {{ .Values.configVars.STORAGE }}
|
||||
|
||||
- name: ClickHouseUrl
|
||||
value: {{ .Values.configVars.ClickHouseUrl}}
|
||||
- name: GODEBUG
|
||||
value: netdns=go
|
||||
# livenessProbe:
|
||||
# httpGet:
|
||||
# path: /
|
||||
@@ -47,6 +49,13 @@ spec:
|
||||
# httpGet:
|
||||
# path: /
|
||||
# port: http
|
||||
volumeMounts:
|
||||
- name: prometheus
|
||||
mountPath: /root/config
|
||||
- name: signoz-db
|
||||
mountPath: /var/lib/signoz/
|
||||
- name: dashboards
|
||||
mountPath: /root/config/dashboards
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
@@ -61,3 +70,18 @@ spec:
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: prometheus
|
||||
configMap:
|
||||
name: prometheus-config
|
||||
- name: dashboards
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: signoz-db
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
@@ -16,7 +16,8 @@ fullnameOverride: ""
|
||||
configVars:
|
||||
DruidClientUrl: http://signoz-druid-router:8888
|
||||
DruidDatasource: flattened_spans
|
||||
STORAGE: druid
|
||||
ClickHouseUrl: http://signoz-clickhouse:9000?username=clickhouse_operator&password=clickhouse_operator_password
|
||||
STORAGE: clickhouse
|
||||
POSTHOG_API_KEY: "H-htDCae7CR3RV57gUzmol6IAKtm5IMCvbcm_fwnL-w"
|
||||
|
||||
|
||||
|
||||
33
deploy/kubernetes/platform/templates/clickhouse-config.yaml
Normal file
33
deploy/kubernetes/platform/templates/clickhouse-config.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: initdb-config
|
||||
data:
|
||||
init-db.sql: |-
|
||||
CREATE TABLE IF NOT EXISTS signoz_index (
|
||||
timestamp DateTime64(9) CODEC(Delta, ZSTD(1)),
|
||||
traceID String CODEC(ZSTD(1)),
|
||||
spanID String CODEC(ZSTD(1)),
|
||||
parentSpanID String CODEC(ZSTD(1)),
|
||||
serviceName LowCardinality(String) CODEC(ZSTD(1)),
|
||||
name LowCardinality(String) CODEC(ZSTD(1)),
|
||||
kind Int32 CODEC(ZSTD(1)),
|
||||
durationNano UInt64 CODEC(ZSTD(1)),
|
||||
tags Array(String) CODEC(ZSTD(1)),
|
||||
tagsKeys Array(String) CODEC(ZSTD(1)),
|
||||
tagsValues Array(String) CODEC(ZSTD(1)),
|
||||
statusCode Int64 CODEC(ZSTD(1)),
|
||||
references String CODEC(ZSTD(1)),
|
||||
externalHttpMethod Nullable(String) CODEC(ZSTD(1)),
|
||||
externalHttpUrl Nullable(String) CODEC(ZSTD(1)),
|
||||
component Nullable(String) CODEC(ZSTD(1)),
|
||||
dbSystem Nullable(String) CODEC(ZSTD(1)),
|
||||
dbName Nullable(String) CODEC(ZSTD(1)),
|
||||
dbOperation Nullable(String) CODEC(ZSTD(1)),
|
||||
peerService Nullable(String) CODEC(ZSTD(1)),
|
||||
INDEX idx_tagsKeys tagsKeys TYPE bloom_filter(0.01) GRANULARITY 64,
|
||||
INDEX idx_tagsValues tagsValues TYPE bloom_filter(0.01) GRANULARITY 64,
|
||||
INDEX idx_duration durationNano TYPE minmax GRANULARITY 1
|
||||
) ENGINE MergeTree()
|
||||
PARTITION BY toDate(timestamp)
|
||||
ORDER BY (serviceName, -toUnixTimestamp(timestamp))
|
||||
104
deploy/kubernetes/platform/templates/clickhouse-instance.yaml
Normal file
104
deploy/kubernetes/platform/templates/clickhouse-instance.yaml
Normal file
@@ -0,0 +1,104 @@
|
||||
{{ if (eq (.Values.cloud | toString) "gcp" )}}
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: gce-resizable
|
||||
provisioner: kubernetes.io/gce-pd
|
||||
parameters:
|
||||
type: pd-standard
|
||||
fstype: ext4
|
||||
replication-type: none
|
||||
reclaimPolicy: Retain
|
||||
#volumeBindingMode: Immediate
|
||||
allowVolumeExpansion: true
|
||||
{{- else if (eq (.Values.cloud | toString) "aws") }}
|
||||
#
|
||||
# AWS resizable disk example
|
||||
#
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: gp2-resizable
|
||||
provisioner: kubernetes.io/aws-ebs
|
||||
parameters:
|
||||
type: gp2
|
||||
reclaimPolicy: Retain
|
||||
#volumeBindingMode: Immediate
|
||||
allowVolumeExpansion: true
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: "clickhouse.altinity.com/v1"
|
||||
kind: "ClickHouseInstallation"
|
||||
metadata:
|
||||
name: signoz
|
||||
spec:
|
||||
defaults:
|
||||
templates:
|
||||
dataVolumeClaimTemplate: default-volume-claim
|
||||
# logVolumeClaimTemplate: default-volume-claim
|
||||
serviceTemplate: chi-service-template
|
||||
configuration:
|
||||
zookeeper:
|
||||
nodes:
|
||||
- host: signoz-zookeeper
|
||||
port: 2181
|
||||
session_timeout_ms: 6000
|
||||
clusters:
|
||||
- name: cluster
|
||||
# Templates are specified for this cluster explicitly
|
||||
templates:
|
||||
dataVolumeClaimTemplate: default-volume-claim
|
||||
# logVolumeClaimTemplate: default-volume-claim
|
||||
podTemplate: pod-template-with-volume
|
||||
layout:
|
||||
shardsCount: 1
|
||||
replicasCount: 1
|
||||
templates:
|
||||
hostTemplates:
|
||||
- name: port-distribution
|
||||
portDistribution:
|
||||
- type: ClusterScopeIndex
|
||||
spec:
|
||||
tcpPort: 9000
|
||||
httpPort: 8123
|
||||
interserverHTTPPort: 9009
|
||||
|
||||
podTemplates:
|
||||
- name: pod-template-with-volume
|
||||
spec:
|
||||
containers:
|
||||
- name: clickhouse
|
||||
image: yandex/clickhouse-server:21.7
|
||||
volumeMounts:
|
||||
- name: default-volume-claim
|
||||
mountPath: /var/lib/clickhouse
|
||||
- name: initdb
|
||||
mountPath: /docker-entrypoint-initdb.d
|
||||
volumes:
|
||||
- name: initdb
|
||||
configMap:
|
||||
name: initdb-config
|
||||
serviceTemplates:
|
||||
- name: chi-service-template
|
||||
generateName: signoz-clickhouse
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 8123
|
||||
- name: tcp
|
||||
port: 9000
|
||||
type: {{ .Values.clickhouseOperator.serviceType }}
|
||||
volumeClaimTemplates:
|
||||
- name: default-volume-claim
|
||||
reclaimPolicy: Retain
|
||||
spec:
|
||||
{{- if (eq (.Values.cloud | toString) "gcp" )}}
|
||||
storageClassName: gce-resizable
|
||||
{{- else if (eq (.Values.cloud | toString) "aws") }}
|
||||
storageClassName: gp2-resizable
|
||||
{{- end }}
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.clickhouseOperator.storage | quote }}
|
||||
@@ -0,0 +1,157 @@
|
||||
{{- if .Values.clickhouseOperator.enabled }}
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=#
|
||||
# ROLE_KIND=ClusterRole
|
||||
# ROLE_NAME=clickhouse-operator-posthog
|
||||
# ROLE_BINDING_KIND=ClusterRoleBinding
|
||||
# ROLE_BINDING_NAME=clickhouse-operator-posthog
|
||||
#
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: clickhouse-operator-posthog
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
- services
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- persistentvolumeclaims
|
||||
verbs:
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- persistentvolumes
|
||||
- pods
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- statefulsets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- replicasets
|
||||
verbs:
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- apps
|
||||
resourceNames:
|
||||
- clickhouse-operator
|
||||
resources:
|
||||
- deployments
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- delete
|
||||
- apiGroups:
|
||||
- policy
|
||||
resources:
|
||||
- poddisruptionbudgets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- clickhouse.altinity.com
|
||||
resources:
|
||||
- clickhouseinstallations
|
||||
verbs:
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- clickhouse.altinity.com
|
||||
resources:
|
||||
- clickhouseinstallations
|
||||
- clickhouseinstallationtemplates
|
||||
- clickhouseoperatorconfigurations
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- clickhouse.altinity.com
|
||||
resources:
|
||||
- clickhouseinstallations/finalizers
|
||||
- clickhouseinstallationtemplates/finalizers
|
||||
- clickhouseoperatorconfigurations/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- clickhouse.altinity.com
|
||||
resources:
|
||||
- clickhouseinstallations/status
|
||||
- clickhouseinstallationtemplates/status
|
||||
- clickhouseoperatorconfigurations/status
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- update
|
||||
- patch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{- if .Values.clickhouseOperator.enabled }}
|
||||
# Setup ClusterRoleBinding between ClusterRole and ServiceAccount.
|
||||
# ClusterRoleBinding is namespace-less and must have unique name
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: clickhouse-operator-posthog
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: clickhouse-operator-posthog
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: clickhouse-operator
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,418 @@
|
||||
{{- if .Values.clickhouseOperator.enabled }}
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAME=etc-clickhouse-operator-files
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: etc-clickhouse-operator-files
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
data:
|
||||
config.yaml: |
|
||||
################################################
|
||||
##
|
||||
## Watch Namespaces Section
|
||||
##
|
||||
################################################
|
||||
|
||||
# List of namespaces where clickhouse-operator watches for events.
|
||||
# Concurrently running operators should watch on different namespaces
|
||||
#watchNamespaces: ["dev", "test"]
|
||||
watchNamespaces: []
|
||||
|
||||
################################################
|
||||
##
|
||||
## Additional Configuration Files Section
|
||||
##
|
||||
################################################
|
||||
|
||||
# Path to folder where ClickHouse configuration files common for all instances within CHI are located.
|
||||
chCommonConfigsPath: config.d
|
||||
|
||||
# Path to folder where ClickHouse configuration files unique for each instance (host) within CHI are located.
|
||||
chHostConfigsPath: conf.d
|
||||
|
||||
# Path to folder where ClickHouse configuration files with users settings are located.
|
||||
# Files are common for all instances within CHI
|
||||
chUsersConfigsPath: users.d
|
||||
|
||||
# Path to folder where ClickHouseInstallation .yaml manifests are located.
|
||||
# Manifests are applied in sorted alpha-numeric order
|
||||
chiTemplatesPath: templates.d
|
||||
|
||||
################################################
|
||||
##
|
||||
## Cluster Create/Update/Delete Objects Section
|
||||
##
|
||||
################################################
|
||||
|
||||
# How many seconds to wait for created/updated StatefulSet to be Ready
|
||||
statefulSetUpdateTimeout: 300
|
||||
|
||||
# How many seconds to wait between checks for created/updated StatefulSet status
|
||||
statefulSetUpdatePollPeriod: 5
|
||||
|
||||
# What to do in case created StatefulSet is not in Ready after `statefulSetUpdateTimeout` seconds
|
||||
# Possible options:
|
||||
# 1. abort - do nothing, just break the process and wait for admin
|
||||
# 2. delete - delete newly created problematic StatefulSet
|
||||
# 3. ignore - ignore error, pretend nothing happened and move on to the next StatefulSet
|
||||
onStatefulSetCreateFailureAction: ignore
|
||||
|
||||
# What to do in case updated StatefulSet is not in Ready after `statefulSetUpdateTimeout` seconds
|
||||
# Possible options:
|
||||
# 1. abort - do nothing, just break the process and wait for admin
|
||||
# 2. rollback - delete Pod and rollback StatefulSet to previous Generation.
|
||||
# Pod would be recreated by StatefulSet based on rollback-ed configuration
|
||||
# 3. ignore - ignore error, pretend nothing happened and move on to the next StatefulSet
|
||||
onStatefulSetUpdateFailureAction: rollback
|
||||
|
||||
################################################
|
||||
##
|
||||
## ClickHouse Settings Section
|
||||
##
|
||||
################################################
|
||||
|
||||
# Default values for ClickHouse user configuration
|
||||
# 1. user/profile - string
|
||||
# 2. user/quota - string
|
||||
# 3. user/networks/ip - multiple strings
|
||||
# 4. user/password - string
|
||||
chConfigUserDefaultProfile: default
|
||||
chConfigUserDefaultQuota: default
|
||||
chConfigUserDefaultNetworksIP:
|
||||
- "::1"
|
||||
- "127.0.0.1"
|
||||
chConfigUserDefaultPassword: "default"
|
||||
|
||||
# Default host_regexp to limit network connectivity from outside
|
||||
chConfigNetworksHostRegexpTemplate: "(chi-{chi}-[^.]+\\d+-\\d+|clickhouse\\-{chi})\\.{namespace}\\.svc\\.cluster\\.local$"
|
||||
|
||||
################################################
|
||||
##
|
||||
## Access to ClickHouse instances
|
||||
##
|
||||
################################################
|
||||
|
||||
# ClickHouse credentials (username, password and port) to be used by operator to connect to ClickHouse instances
|
||||
# for:
|
||||
# 1. Metrics requests
|
||||
# 2. Schema maintenance
|
||||
# 3. DROP DNS CACHE
|
||||
# User with such credentials can be specified in additional ClickHouse .xml config files,
|
||||
# located in `chUsersConfigsPath` folder
|
||||
chUsername: "clickhouse_operator"
|
||||
chPassword: "clickhouse_operator_password"
|
||||
|
||||
# Location of k8s Secret with username and password to be used by operator to connect to ClickHouse instances
|
||||
# Can be used instead of explicitly specified username and password
|
||||
chCredentialsSecretNamespace: ""
|
||||
chCredentialsSecretName: ""
|
||||
|
||||
# Port where to connect to ClickHouse instances to
|
||||
chPort: 8123
|
||||
|
||||
################################################
|
||||
##
|
||||
## Log parameters
|
||||
##
|
||||
################################################
|
||||
|
||||
logtostderr: "true"
|
||||
alsologtostderr: "false"
|
||||
v: "1"
|
||||
stderrthreshold: ""
|
||||
vmodule: ""
|
||||
log_backtrace_at: ""
|
||||
|
||||
################################################
|
||||
##
|
||||
## Runtime parameters
|
||||
##
|
||||
################################################
|
||||
|
||||
# Max number of concurrent reconciles in progress
|
||||
reconcileThreadsNumber: 10
|
||||
reconcileWaitExclude: true
|
||||
reconcileWaitInclude: false
|
||||
|
||||
################################################
|
||||
##
|
||||
## Labels management parameters
|
||||
##
|
||||
################################################
|
||||
|
||||
# When propagating labels from the chi's `metadata.labels` section to child objects' `metadata.labels`,
|
||||
# exclude labels from the following list:
|
||||
#excludeFromPropagationLabels:
|
||||
# - "labelA"
|
||||
# - "labelB"
|
||||
|
||||
# Whether to append *Scope* labels to StatefulSet and Pod.
|
||||
# Full list of available *scope* labels check in labeler.go
|
||||
# LabelShardScopeIndex
|
||||
# LabelReplicaScopeIndex
|
||||
# LabelCHIScopeIndex
|
||||
# LabelCHIScopeCycleSize
|
||||
# LabelCHIScopeCycleIndex
|
||||
# LabelCHIScopeCycleOffset
|
||||
# LabelClusterScopeIndex
|
||||
# LabelClusterScopeCycleSize
|
||||
# LabelClusterScopeCycleIndex
|
||||
# LabelClusterScopeCycleOffset
|
||||
appendScopeLabels: "no"
|
||||
|
||||
################################################
|
||||
##
|
||||
## Pod management parameters
|
||||
##
|
||||
################################################
|
||||
# Grace period for Pod termination.
|
||||
# How many seconds to wait between sending
|
||||
# SIGTERM and SIGKILL during Pod termination process.
|
||||
# Increase this number is case of slow shutdown.
|
||||
terminationGracePeriod: 30
|
||||
|
||||
---
|
||||
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAME=etc-clickhouse-operator-confd-files
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: etc-clickhouse-operator-confd-files
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
data:
|
||||
|
||||
---
|
||||
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAME=etc-clickhouse-operator-configd-files
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: etc-clickhouse-operator-configd-files
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
data:
|
||||
01-clickhouse-01-listen.xml: |
|
||||
<yandex>
|
||||
<!-- Listen wildcard address to allow accepting connections from other containers and host network. -->
|
||||
<listen_host>::</listen_host>
|
||||
<listen_host>0.0.0.0</listen_host>
|
||||
<listen_try>1</listen_try>
|
||||
</yandex>
|
||||
|
||||
01-clickhouse-02-logger.xml: |
|
||||
<yandex>
|
||||
<logger>
|
||||
<!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger.h#L105 -->
|
||||
<level>debug</level>
|
||||
<log>/var/log/clickhouse-server/clickhouse-server.log</log>
|
||||
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
|
||||
<size>1000M</size>
|
||||
<count>10</count>
|
||||
<!-- Default behavior is autodetection (log to console if not daemon mode and is tty) -->
|
||||
<console>1</console>
|
||||
</logger>
|
||||
</yandex>
|
||||
|
||||
01-clickhouse-03-query_log.xml: |
|
||||
<yandex>
|
||||
<query_log replace="1">
|
||||
<database>system</database>
|
||||
<table>query_log</table>
|
||||
<engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_date + interval 30 day</engine>
|
||||
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
|
||||
</query_log>
|
||||
<query_thread_log remove="1"/>
|
||||
</yandex>
|
||||
|
||||
01-clickhouse-04-part_log.xml: |
|
||||
<yandex>
|
||||
<part_log replace="1">
|
||||
<database>system</database>
|
||||
<table>part_log</table>
|
||||
<engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_date + interval 30 day</engine>
|
||||
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
|
||||
</part_log>
|
||||
</yandex>
|
||||
|
||||
---
|
||||
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAME=etc-clickhouse-operator-templatesd-files
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: etc-clickhouse-operator-templatesd-files
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
data:
|
||||
001-templates.json.example: |
|
||||
{
|
||||
"apiVersion": "clickhouse.altinity.com/v1",
|
||||
"kind": "ClickHouseInstallationTemplate",
|
||||
"metadata": {
|
||||
"name": "01-default-volumeclaimtemplate"
|
||||
},
|
||||
"spec": {
|
||||
"templates": {
|
||||
"volumeClaimTemplates": [
|
||||
{
|
||||
"name": "chi-default-volume-claim-template",
|
||||
"spec": {
|
||||
"accessModes": [
|
||||
"ReadWriteOnce"
|
||||
],
|
||||
"resources": {
|
||||
"requests": {
|
||||
"storage": "2Gi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"podTemplates": [
|
||||
{
|
||||
"name": "chi-default-oneperhost-pod-template",
|
||||
"distribution": "OnePerHost",
|
||||
"spec": {
|
||||
"containers" : [
|
||||
{
|
||||
"name": "clickhouse",
|
||||
"image": "yandex/clickhouse-server:19.3.7",
|
||||
"ports": [
|
||||
{
|
||||
"name": "http",
|
||||
"containerPort": 8123
|
||||
},
|
||||
{
|
||||
"name": "client",
|
||||
"containerPort": 9000
|
||||
},
|
||||
{
|
||||
"name": "interserver",
|
||||
"containerPort": 9009
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default-pod-template.yaml.example: |
|
||||
apiVersion: "clickhouse.altinity.com/v1"
|
||||
kind: "ClickHouseInstallationTemplate"
|
||||
metadata:
|
||||
name: "default-oneperhost-pod-template"
|
||||
spec:
|
||||
templates:
|
||||
podTemplates:
|
||||
- name: default-oneperhost-pod-template
|
||||
distribution: "OnePerHost"
|
||||
default-storage-template.yaml.example: |
|
||||
apiVersion: "clickhouse.altinity.com/v1"
|
||||
kind: "ClickHouseInstallationTemplate"
|
||||
metadata:
|
||||
name: "default-storage-template-2Gi"
|
||||
spec:
|
||||
templates:
|
||||
volumeClaimTemplates:
|
||||
- name: default-storage-template-2Gi
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
|
||||
readme: |
|
||||
Templates in this folder are packaged with an operator and available via 'useTemplate'
|
||||
|
||||
---
|
||||
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAME=etc-clickhouse-operator-usersd-files
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
#
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: etc-clickhouse-operator-usersd-files
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
data:
|
||||
01-clickhouse-user.xml: |
|
||||
<yandex>
|
||||
<users>
|
||||
<clickhouse_operator>
|
||||
<networks>
|
||||
<ip>127.0.0.1</ip>
|
||||
<ip>0.0.0.0/0</ip>
|
||||
<ip>::/0</ip>
|
||||
</networks>
|
||||
<password_sha256_hex>716b36073a90c6fe1d445ac1af85f4777c5b7a155cea359961826a030513e448</password_sha256_hex>
|
||||
<profile>clickhouse_operator</profile>
|
||||
<quota>default</quota>
|
||||
</clickhouse_operator>
|
||||
</users>
|
||||
<profiles>
|
||||
<clickhouse_operator>
|
||||
<log_queries>0</log_queries>
|
||||
<skip_unavailable_shards>1</skip_unavailable_shards>
|
||||
<http_connection_timeout>10</http_connection_timeout>
|
||||
</clickhouse_operator>
|
||||
</profiles>
|
||||
</yandex>
|
||||
|
||||
02-clickhouse-default-profile.xml: |
|
||||
<yandex>
|
||||
<profiles>
|
||||
<default>
|
||||
<log_queries>1</log_queries>
|
||||
<connect_timeout_with_failover_ms>1000</connect_timeout_with_failover_ms>
|
||||
<distributed_aggregation_memory_efficient>1</distributed_aggregation_memory_efficient>
|
||||
<parallel_view_processing>1</parallel_view_processing>
|
||||
</default>
|
||||
</profiles>
|
||||
</yandex>
|
||||
03-database-ordinary.xml: |
|
||||
<!-- Remove it for ClickHouse versions before 20.4 -->
|
||||
<yandex>
|
||||
<profiles>
|
||||
<default>
|
||||
<default_database_engine>Ordinary</default_database_engine>
|
||||
</default>
|
||||
</profiles>
|
||||
</yandex>
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,129 @@
|
||||
{{- if .Values.clickhouseOperator.enabled }}
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
# OPERATOR_IMAGE=altinity/clickhouse-operator:latest
|
||||
# METRICS_EXPORTER_IMAGE=altinity/metrics-exporter:latest
|
||||
#
|
||||
# Setup Deployment for clickhouse-operator
|
||||
# Deployment would be created in kubectl-specified namespace
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: clickhouse-operator
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: clickhouse-operator
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
annotations:
|
||||
prometheus.io/port: '8888'
|
||||
prometheus.io/scrape: 'true'
|
||||
spec:
|
||||
serviceAccountName: clickhouse-operator
|
||||
volumes:
|
||||
- name: etc-clickhouse-operator-folder
|
||||
configMap:
|
||||
name: etc-clickhouse-operator-files
|
||||
- name: etc-clickhouse-operator-confd-folder
|
||||
configMap:
|
||||
name: etc-clickhouse-operator-confd-files
|
||||
- name: etc-clickhouse-operator-configd-folder
|
||||
configMap:
|
||||
name: etc-clickhouse-operator-configd-files
|
||||
- name: etc-clickhouse-operator-templatesd-folder
|
||||
configMap:
|
||||
name: etc-clickhouse-operator-templatesd-files
|
||||
- name: etc-clickhouse-operator-usersd-folder
|
||||
configMap:
|
||||
name: etc-clickhouse-operator-usersd-files
|
||||
containers:
|
||||
- name: clickhouse-operator
|
||||
image: altinity/clickhouse-operator:latest
|
||||
imagePullPolicy: Always
|
||||
volumeMounts:
|
||||
- name: etc-clickhouse-operator-folder
|
||||
mountPath: /etc/clickhouse-operator
|
||||
- name: etc-clickhouse-operator-confd-folder
|
||||
mountPath: /etc/clickhouse-operator/conf.d
|
||||
- name: etc-clickhouse-operator-configd-folder
|
||||
mountPath: /etc/clickhouse-operator/config.d
|
||||
- name: etc-clickhouse-operator-templatesd-folder
|
||||
mountPath: /etc/clickhouse-operator/templates.d
|
||||
- name: etc-clickhouse-operator-usersd-folder
|
||||
mountPath: /etc/clickhouse-operator/users.d
|
||||
env:
|
||||
# Pod-specific
|
||||
# spec.nodeName: ip-172-20-52-62.ec2.internal
|
||||
- name: OPERATOR_POD_NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
# metadata.name: clickhouse-operator-6f87589dbb-ftcsf
|
||||
- name: OPERATOR_POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
# metadata.namespace: kube-system
|
||||
- name: OPERATOR_POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
# status.podIP: 100.96.3.2
|
||||
- name: OPERATOR_POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
# spec.serviceAccount: clickhouse-operator
|
||||
# spec.serviceAccountName: clickhouse-operator
|
||||
- name: OPERATOR_POD_SERVICE_ACCOUNT
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.serviceAccountName
|
||||
|
||||
# Container-specific
|
||||
- name: OPERATOR_CONTAINER_CPU_REQUEST
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
containerName: clickhouse-operator
|
||||
resource: requests.cpu
|
||||
- name: OPERATOR_CONTAINER_CPU_LIMIT
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
containerName: clickhouse-operator
|
||||
resource: limits.cpu
|
||||
- name: OPERATOR_CONTAINER_MEM_REQUEST
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
containerName: clickhouse-operator
|
||||
resource: requests.memory
|
||||
- name: OPERATOR_CONTAINER_MEM_LIMIT
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
containerName: clickhouse-operator
|
||||
resource: limits.memory
|
||||
|
||||
- name: metrics-exporter
|
||||
image: altinity/metrics-exporter:latest
|
||||
imagePullPolicy: Always
|
||||
volumeMounts:
|
||||
- name: etc-clickhouse-operator-folder
|
||||
mountPath: /etc/clickhouse-operator
|
||||
- name: etc-clickhouse-operator-confd-folder
|
||||
mountPath: /etc/clickhouse-operator/conf.d
|
||||
- name: etc-clickhouse-operator-configd-folder
|
||||
mountPath: /etc/clickhouse-operator/config.d
|
||||
- name: etc-clickhouse-operator-templatesd-folder
|
||||
mountPath: /etc/clickhouse-operator/templates.d
|
||||
- name: etc-clickhouse-operator-usersd-folder
|
||||
mountPath: /etc/clickhouse-operator/users.d
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,26 @@
|
||||
{{- if .Values.clickhouseOperator.enabled }}
|
||||
# Template Parameters:
|
||||
#
|
||||
# NAMESPACE=posthog
|
||||
# COMMENT=
|
||||
#
|
||||
# Setup ClusterIP Service to provide monitoring metrics for Prometheus
|
||||
# Service would be created in kubectl-specified namespace
|
||||
# In order to get access outside of k8s it should be exposed as:
|
||||
# kubectl --namespace prometheus port-forward service/prometheus 9090
|
||||
# and point browser to localhost:9090
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: clickhouse-operator-metrics
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
labels:
|
||||
app: clickhouse-operator
|
||||
spec:
|
||||
ports:
|
||||
- port: 8888
|
||||
name: clickhouse-operator-metrics
|
||||
selector:
|
||||
app: clickhouse-operator
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.clickhouseOperator.enabled }}
|
||||
# Template Parameters:
|
||||
#
|
||||
# COMMENT=
|
||||
# NAMESPACE=posthog
|
||||
# NAME=clickhouse-operator
|
||||
#
|
||||
# Setup ServiceAccount
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: clickhouse-operator
|
||||
namespace: {{ .Values.clickhouseOperator.namespace | default .Release.Namespace }}
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,53 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: otel-collector-metrics-conf
|
||||
labels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-metrics-conf
|
||||
data:
|
||||
otel-collector-metrics-config: |
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
|
||||
# Data sources: metrics
|
||||
prometheus:
|
||||
config:
|
||||
scrape_configs:
|
||||
- job_name: "otel-collector"
|
||||
scrape_interval: 30s
|
||||
static_configs:
|
||||
- targets: ["otel-collector:8889"]
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
memory_limiter:
|
||||
# Same as --mem-ballast-size-mib CLI argument
|
||||
ballast_size_mib: 683
|
||||
# 80% of maximum memory up to 2G
|
||||
limit_mib: 1500
|
||||
# 25% of limit up to 2G
|
||||
spike_limit_mib: 512
|
||||
check_interval: 5s
|
||||
# queued_retry:
|
||||
# num_workers: 4
|
||||
# queue_size: 100
|
||||
# retry_on_failure: true
|
||||
extensions:
|
||||
health_check: {}
|
||||
zpages: {}
|
||||
exporters:
|
||||
clickhousemetricswrite:
|
||||
endpoint: tcp://signoz-clickhouse:9000/?database=signoz_metrics&username=clickhouse_operator&password=clickhouse_operator_password
|
||||
|
||||
service:
|
||||
extensions: [health_check, zpages]
|
||||
pipelines:
|
||||
metrics:
|
||||
receivers: [otlp, prometheus]
|
||||
processors: [batch]
|
||||
exporters: [clickhousemetricswrite]
|
||||
@@ -0,0 +1,72 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: otel-collector-metrics
|
||||
labels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-metrics
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-metrics
|
||||
minReadySeconds: 5
|
||||
progressDeadlineSeconds: 120
|
||||
replicas: 1 #TODO - adjust this to your own requirements
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-metrics
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- "/otelcontribcol"
|
||||
- "--config=/conf/otel-collector-metrics-config.yaml"
|
||||
# Memory Ballast size should be max 1/3 to 1/2 of memory.
|
||||
- "--mem-ballast-size-mib=683"
|
||||
image: signoz/otelcontribcol:0.4.2
|
||||
name: otel-collector
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 400Mi
|
||||
ports:
|
||||
- containerPort: 55679 # Default endpoint for ZPages.
|
||||
- containerPort: 55680 # Default endpoint for OpenTelemetry receiver.
|
||||
- containerPort: 55681 # Default endpoint for OpenTelemetry HTTP/1.0 receiver.
|
||||
- containerPort: 4317 # Default endpoint for OpenTelemetry GRPC receiver.
|
||||
- containerPort: 14250 # Default endpoint for Jaeger GRPC receiver.
|
||||
- containerPort: 14268 # Default endpoint for Jaeger HTTP receiver.
|
||||
- containerPort: 9411 # Default endpoint for Zipkin receiver.
|
||||
- containerPort: 8888 # Default endpoint for querying metrics.
|
||||
volumeMounts:
|
||||
- name: otel-collector-metrics-config-vol
|
||||
mountPath: /conf
|
||||
# - name: otel-collector-secrets
|
||||
# mountPath: /secrets
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 13133 # Health Check extension default port.
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 13133 # Health Check extension default port.
|
||||
volumes:
|
||||
- configMap:
|
||||
name: otel-collector-metrics-conf
|
||||
items:
|
||||
- key: otel-collector-metrics-config
|
||||
path: otel-collector-metrics-config.yaml
|
||||
name: otel-collector-metrics-config-vol
|
||||
# - secret:
|
||||
# name: otel-collector-secrets
|
||||
# items:
|
||||
# - key: cert.pem
|
||||
# path: cert.pem
|
||||
# - key: key.pem
|
||||
# path: key.pem
|
||||
@@ -0,0 +1,31 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: otel-collector-metrics
|
||||
labels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-metrics
|
||||
spec:
|
||||
ports:
|
||||
- name: otlp # Default endpoint for OpenTelemetry receiver.
|
||||
port: 55680
|
||||
protocol: TCP
|
||||
targetPort: 55680
|
||||
- name: otlp-http-legacy # Default endpoint for OpenTelemetry receiver.
|
||||
port: 55681
|
||||
protocol: TCP
|
||||
targetPort: 55681
|
||||
- name: otlp-grpc # Default endpoint for OpenTelemetry receiver.
|
||||
port: 4317
|
||||
protocol: TCP
|
||||
targetPort: 4317
|
||||
- name: jaeger-grpc # Default endpoing for Jaeger gRPC receiver
|
||||
port: 14250
|
||||
- name: jaeger-thrift-http # Default endpoint for Jaeger HTTP receiver.
|
||||
port: 14268
|
||||
- name: zipkin # Default endpoint for Zipkin receiver.
|
||||
port: 9411
|
||||
- name: metrics # Default endpoint for querying metrics.
|
||||
port: 8888
|
||||
selector:
|
||||
component: otel-collector-metrics
|
||||
@@ -0,0 +1,67 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: otel-collector-conf
|
||||
labels:
|
||||
app: opentelemetry
|
||||
component: otel-collector-conf
|
||||
data:
|
||||
otel-collector-config: |
|
||||
receivers:
|
||||
otlp/spanmetrics:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: "localhost:12345"
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
jaeger:
|
||||
protocols:
|
||||
grpc:
|
||||
thrift_http:
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
signozspanmetrics/prometheus:
|
||||
metrics_exporter: prometheus
|
||||
latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s ]
|
||||
memory_limiter:
|
||||
# Same as --mem-ballast-size-mib CLI argument
|
||||
ballast_size_mib: 683
|
||||
# 80% of maximum memory up to 2G
|
||||
limit_mib: 1500
|
||||
# 25% of limit up to 2G
|
||||
spike_limit_mib: 512
|
||||
check_interval: 5s
|
||||
# queued_retry:
|
||||
# num_workers: 4
|
||||
# queue_size: 100
|
||||
# retry_on_failure: true
|
||||
extensions:
|
||||
health_check: {}
|
||||
zpages: {}
|
||||
exporters:
|
||||
clickhouse:
|
||||
datasource: tcp://signoz-clickhouse:9000?username=clickhouse_operator&password=clickhouse_operator_password
|
||||
clickhousemetricswrite:
|
||||
endpoint: tcp://signoz-clickhouse:9000/?database=signoz_metrics&username=clickhouse_operator&password=clickhouse_operator_password
|
||||
resource_to_telemetry_conversion:
|
||||
enabled: true
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
service:
|
||||
extensions: [health_check, zpages]
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [jaeger, otlp]
|
||||
processors: [signozspanmetrics/prometheus, batch]
|
||||
exporters: [clickhouse]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [clickhousemetricswrite]
|
||||
metrics/spanmetrics:
|
||||
receivers: [otlp/spanmetrics]
|
||||
exporters: [prometheus]
|
||||
@@ -21,11 +21,11 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- "/otelcol"
|
||||
- "/otelcontribcol"
|
||||
- "--config=/conf/otel-collector-config.yaml"
|
||||
# Memory Ballast size should be max 1/3 to 1/2 of memory.
|
||||
- "--mem-ballast-size-mib=683"
|
||||
image: otel/opentelemetry-collector:0.18.0
|
||||
image: signoz/otelcontribcol:0.4.2
|
||||
name: otel-collector
|
||||
resources:
|
||||
limits:
|
||||
@@ -43,6 +43,7 @@ spec:
|
||||
- containerPort: 14268 # Default endpoint for Jaeger HTTP receiver.
|
||||
- containerPort: 9411 # Default endpoint for Zipkin receiver.
|
||||
- containerPort: 8888 # Default endpoint for querying metrics.
|
||||
- containerPort: 8889 # Default endpoint for prometheus exported metrics.
|
||||
volumeMounts:
|
||||
- name: otel-collector-config-vol
|
||||
mountPath: /conf
|
||||
@@ -27,5 +27,7 @@ spec:
|
||||
port: 9411
|
||||
- name: metrics # Default endpoint for querying metrics.
|
||||
port: 8888
|
||||
- name: prometheus-metrics # Default endpoint for querying prometheus metrics.
|
||||
port: 8889
|
||||
selector:
|
||||
component: otel-collector
|
||||
@@ -1,51 +1,15 @@
|
||||
zookeeper:
|
||||
autopurge:
|
||||
purgeInterval: 1
|
||||
|
||||
kafka:
|
||||
zookeeper:
|
||||
enabled: false
|
||||
externalZookeeper:
|
||||
servers: ["signoz-zookeeper:2181"]
|
||||
zookeeperConnectionTimeoutMs: 6000
|
||||
|
||||
druid:
|
||||
image:
|
||||
tag: 0.21.1-rc2
|
||||
|
||||
configVars:
|
||||
|
||||
# To store data on local disks attached
|
||||
druid_extensions_loadList: '["druid-histogram", "druid-datasketches", "druid-lookups-cached-global", "postgresql-metadata-storage", "druid-kafka-indexing-service"]'
|
||||
druid_storage_type: local
|
||||
|
||||
|
||||
# # To store data in S3
|
||||
# druid_extensions_loadList: '["druid-histogram", "druid-datasketches", "druid-lookups-cached-global", "postgresql-metadata-storage", "druid-kafka-indexing-service", "druid-s3-extensions"]'
|
||||
# druid_storage_type: s3
|
||||
# druid_storage_bucket: signoz-druid
|
||||
# druid_storage_baseKey: baseKey
|
||||
# AWS_ACCESS_KEY_ID: <your secret id>
|
||||
# AWS_SECRET_ACCESS_KEY: <your secret key>
|
||||
# AWS_REGION: <your region>
|
||||
|
||||
historical:
|
||||
persistence:
|
||||
size: "20Gi"
|
||||
|
||||
zkHosts: "signoz-zookeeper:2181"
|
||||
|
||||
zookeeper:
|
||||
enabled: false
|
||||
|
||||
flattener-processor:
|
||||
configVars:
|
||||
KAFKA_BROKER: signoz-kafka:9092
|
||||
KAFKA_INPUT_TOPIC: otlp_spans
|
||||
KAFKA_OUTPUT_TOPIC: flattened_spans
|
||||
autopurge:
|
||||
purgeInterval: 1
|
||||
|
||||
query-service:
|
||||
configVars:
|
||||
DruidClientUrl: http://signoz-druid-router:8888
|
||||
DruidDatasource: flattened_spans
|
||||
STORAGE: druid
|
||||
configVars:
|
||||
ClickHouseUrl: http://signoz-clickhouse:9000?username=clickhouse_operator&password=clickhouse_operator_password
|
||||
STORAGE: clickhouse
|
||||
|
||||
cloud: aws
|
||||
|
||||
clickhouseOperator:
|
||||
enabled: true
|
||||
storage: 20Gi
|
||||
serviceType: ClusterIP
|
||||
|
||||
@@ -41,7 +41,8 @@ module.exports = {
|
||||
'react/prop-types': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'error',
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
'react/no-array-index-key': 2,
|
||||
'linebreak-style': ['error', process.platform === 'win32' ? 'windows' : 'unix'],
|
||||
|
||||
// simple sort error
|
||||
'simple-import-sort/imports': 'error',
|
||||
8
frontend/bundlesize.config.json
Normal file
8
frontend/bundlesize.config.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"path": "./build/**.js",
|
||||
"maxSize": "1.2MB"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
frontend/cypress/fixtures/defaultAllChannels.json
Normal file
21
frontend/cypress/fixtures/defaultAllChannels.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"created_at": 1638083159246,
|
||||
"data": "{}",
|
||||
"id": 1,
|
||||
"name": "First Channels",
|
||||
"type": "slack",
|
||||
"updated_at": 1638083159246
|
||||
},
|
||||
{
|
||||
"created_at": 1638083159246,
|
||||
"data": "{}",
|
||||
"id": 2,
|
||||
"name": "Second Channels",
|
||||
"type": "Slack",
|
||||
"updated_at": 1638083159246
|
||||
}
|
||||
],
|
||||
"message": "Success"
|
||||
}
|
||||
28
frontend/cypress/fixtures/defaultRules.json
Normal file
28
frontend/cypress/fixtures/defaultRules.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"rules": [
|
||||
{
|
||||
"labels": { "severity": "warning" },
|
||||
"annotations": {},
|
||||
"state": "firing",
|
||||
"name": "First Rule",
|
||||
"id": 1
|
||||
},
|
||||
{
|
||||
"labels": { "severity": "warning" },
|
||||
"annotations": {},
|
||||
"state": "firing",
|
||||
"name": "Second Rule",
|
||||
"id": 2
|
||||
},
|
||||
{
|
||||
"labels": { "severity": "P0" },
|
||||
"annotations": {},
|
||||
"state": "firing",
|
||||
"name": "Third Rule",
|
||||
"id": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
52
frontend/cypress/integration/channels/index.spec.ts
Normal file
52
frontend/cypress/integration/channels/index.spec.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
import defaultAllChannels from '../../fixtures/defaultAllChannels.json';
|
||||
|
||||
describe('Channels', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.setItem('isLoggedIn', 'yes');
|
||||
|
||||
cy.visit(Cypress.env('baseUrl') + ROUTES.ALL_CHANNELS);
|
||||
});
|
||||
|
||||
it('Channels', () => {
|
||||
cy
|
||||
.intercept('**channels**', {
|
||||
statusCode: 200,
|
||||
fixture: 'defaultAllChannels',
|
||||
})
|
||||
.as('All Channels');
|
||||
|
||||
cy.wait('@All Channels');
|
||||
|
||||
cy
|
||||
.get('.ant-tabs-tab')
|
||||
.children()
|
||||
.then((e) => {
|
||||
const child = e.get();
|
||||
|
||||
const secondChild = child[1];
|
||||
|
||||
expect(secondChild.outerText).to.be.equals('Alert Channels');
|
||||
|
||||
expect(secondChild.ariaSelected).to.be.equals('true');
|
||||
});
|
||||
|
||||
cy
|
||||
.get('tbody')
|
||||
.should('be.visible')
|
||||
.then((e) => {
|
||||
const allChildren = e.children().get();
|
||||
expect(allChildren.length).to.be.equals(defaultAllChannels.data.length);
|
||||
|
||||
allChildren.forEach((e, index) => {
|
||||
expect(e.firstChild?.textContent).not.null;
|
||||
expect(e.firstChild?.textContent).to.be.equals(
|
||||
defaultAllChannels.data[index].name,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -20,7 +20,7 @@ describe('default time', () => {
|
||||
|
||||
it('Trace Page default time', () => {
|
||||
cy.checkDefaultGlobalOption({
|
||||
route: ROUTES.TRACES,
|
||||
route: ROUTES.TRACE,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
128
frontend/cypress/integration/rules/index.spec.ts
Normal file
128
frontend/cypress/integration/rules/index.spec.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
import defaultRules from '../../fixtures/defaultRules.json';
|
||||
|
||||
describe('Alerts', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.setItem('isLoggedIn', 'yes');
|
||||
|
||||
cy
|
||||
.intercept('get', '*rules*', {
|
||||
fixture: 'defaultRules',
|
||||
})
|
||||
.as('defaultRules');
|
||||
|
||||
cy.visit(Cypress.env('baseUrl') + `${ROUTES.LIST_ALL_ALERT}`);
|
||||
|
||||
cy.wait('@defaultRules');
|
||||
});
|
||||
|
||||
it('Edit Rules Page Failure', async () => {
|
||||
cy
|
||||
.intercept('**/rules/**', {
|
||||
statusCode: 500,
|
||||
})
|
||||
.as('Get Rules Error');
|
||||
|
||||
cy.get('button.ant-btn.ant-btn-link:nth-child(2)').then((e) => {
|
||||
const firstDelete = e[0];
|
||||
firstDelete.click();
|
||||
|
||||
cy.waitFor('@Get Rules Error');
|
||||
|
||||
cy
|
||||
.window()
|
||||
.location()
|
||||
.then((e) => {
|
||||
expect(e.pathname).to.be.equals(`/alerts/edit/1`);
|
||||
});
|
||||
|
||||
cy.findByText('Something went wrong').then((e) => {
|
||||
expect(e.length).to.be.equals(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Edit Rules Page Success', async () => {
|
||||
const text = 'this is the sample value';
|
||||
|
||||
cy
|
||||
.intercept('**/rules/**', {
|
||||
statusCode: 200,
|
||||
body: {
|
||||
data: {
|
||||
data: text,
|
||||
},
|
||||
},
|
||||
})
|
||||
.as('Get Rules Success');
|
||||
|
||||
cy.get('button.ant-btn.ant-btn-link:nth-child(2)').then((e) => {
|
||||
const firstDelete = e[0];
|
||||
firstDelete.click();
|
||||
|
||||
cy.waitFor('@Get Rules Success');
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
cy.findByText('Save').then((e) => {
|
||||
const [el] = e.get();
|
||||
|
||||
el.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('All Rules are rendered correctly', async () => {
|
||||
cy
|
||||
.window()
|
||||
.location()
|
||||
.then(({ pathname }) => {
|
||||
expect(pathname).to.be.equals(ROUTES.LIST_ALL_ALERT);
|
||||
|
||||
cy.get('tbody').then((e) => {
|
||||
const tarray = e.children().get();
|
||||
|
||||
expect(tarray.length).to.be.equals(3);
|
||||
|
||||
tarray.forEach(({ children }, index) => {
|
||||
const name = children[1]?.textContent;
|
||||
const label = children[2]?.textContent;
|
||||
|
||||
expect(name).to.be.equals(defaultRules.data.rules[index].name);
|
||||
|
||||
const defaultLabels = defaultRules.data.rules[index].labels;
|
||||
|
||||
expect(label).to.be.equals(defaultLabels['severity']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Rules are Deleted', async () => {
|
||||
cy
|
||||
.intercept('**/rules/**', {
|
||||
body: {
|
||||
data: 'Deleted',
|
||||
message: 'Success',
|
||||
},
|
||||
statusCode: 200,
|
||||
})
|
||||
.as('deleteRules');
|
||||
|
||||
cy.get('button.ant-btn.ant-btn-link:first-child').then((e) => {
|
||||
const firstDelete = e[0];
|
||||
|
||||
firstDelete.click();
|
||||
});
|
||||
|
||||
cy.wait('@deleteRules');
|
||||
|
||||
cy.get('tbody').then((e) => {
|
||||
const trray = e.children().get();
|
||||
expect(trray.length).to.be.equals(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
const gulp = require('gulp');
|
||||
const gulpless = require('gulp-less');
|
||||
const postcss = require('gulp-postcss');
|
||||
const debug = require('gulp-debug');
|
||||
var csso = require('gulp-csso');
|
||||
const autteoprefixer = require('autoprefixer');
|
||||
const NpmImportPlugin = require('less-plugin-npm-import');
|
||||
|
||||
gulp.task('less', function () {
|
||||
const plugins = [autteoprefixer()];
|
||||
|
||||
return gulp
|
||||
.src('src/themes/*-theme.less')
|
||||
.pipe(debug({ title: 'Less files:' }))
|
||||
.pipe(
|
||||
gulpless({
|
||||
javascriptEnabled: true,
|
||||
plugins: [new NpmImportPlugin({ prefix: '~' })],
|
||||
}),
|
||||
)
|
||||
.pipe(postcss(plugins))
|
||||
.pipe(
|
||||
csso({
|
||||
debug: true,
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest('./public'));
|
||||
});
|
||||
@@ -4,8 +4,8 @@
|
||||
"description": "",
|
||||
"main": "webpack.config.js",
|
||||
"scripts": {
|
||||
"dev": "NODE_OPTIONS=\"--loader ts-node/esm\" NODE_ENV=development webpack serve --config=webpack.config.ts --progress",
|
||||
"build": "NODE_OPTIONS=\"--loader ts-node/esm\" webpack --config=webpack.config.prod.ts --progress",
|
||||
"dev": "NODE_ENV=development webpack serve --progress",
|
||||
"build": "webpack --config=webpack.config.prod.js --progress",
|
||||
"prettify": "prettier --write .",
|
||||
"lint": "eslint . --debug",
|
||||
"lint:fix": "eslint . --fix --debug",
|
||||
@@ -13,31 +13,19 @@
|
||||
"cypress:run": "cypress run",
|
||||
"jest": "jest",
|
||||
"jest:coverage": "jest --coverage",
|
||||
"jest:watch": "jest --watch"
|
||||
"jest:watch": "jest --watch",
|
||||
"bundle:size": "bundlesize"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.13.0"
|
||||
},
|
||||
"type": "module",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^4.6.2",
|
||||
"@auth0/auth0-react": "^1.2.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "0.4.2",
|
||||
"@svgr/webpack": "5.4.0",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@types/d3": "^6.2.0",
|
||||
"@types/jest": "^26.0.15",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^16.9.9",
|
||||
"@types/react-redux": "^7.1.11",
|
||||
"@types/react-router-dom": "^5.1.6",
|
||||
"@types/redux": "^3.6.0",
|
||||
"@types/styled-components": "^5.1.4",
|
||||
"@types/vis": "^4.21.21",
|
||||
"antd": "^4.16.13",
|
||||
"axios": "^0.21.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
@@ -46,74 +34,40 @@
|
||||
"babel-plugin-named-asset-import": "^0.3.7",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"babel-preset-react-app": "^10.0.0",
|
||||
"bfj": "^7.0.2",
|
||||
"camelcase": "^6.1.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.3.0",
|
||||
"chart.js": "^3.4.0",
|
||||
"chartjs-adapter-date-fns": "^2.0.0",
|
||||
"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",
|
||||
"dotenv": "8.2.0",
|
||||
"dotenv-expand": "5.1.0",
|
||||
"eslint-config-react-app": "^6.0.0",
|
||||
"eslint-plugin-flowtype": "^5.2.0",
|
||||
"eslint-plugin-jest": "^24.1.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.3.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-testing-library": "^3.9.2",
|
||||
"eslint-webpack-plugin": "^2.1.0",
|
||||
"file-loader": "6.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"history": "4.10.1",
|
||||
"html-webpack-plugin": "5.1.0",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"jest": "26.6.0",
|
||||
"jest-circus": "26.6.0",
|
||||
"jest-resolve": "26.6.0",
|
||||
"jest-watch-typeahead": "0.6.1",
|
||||
"mini-css-extract-plugin": "^2.4.5",
|
||||
"monaco-editor": "^0.30.0",
|
||||
"pnp-webpack-plugin": "1.6.4",
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-normalize": "8.0.1",
|
||||
"postcss-preset-env": "6.7.0",
|
||||
"postcss-safe-parser": "5.0.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "17.0.0",
|
||||
"react-app-polyfill": "^2.0.0",
|
||||
"react-chips": "^0.8.0",
|
||||
"react-css-theme-switcher": "^0.1.6",
|
||||
"react-dev-utils": "^11.0.0",
|
||||
"react-dom": "17.0.0",
|
||||
"react-force-graph": "^1.41.0",
|
||||
"react-graph-vis": "^1.0.5",
|
||||
"react-grid-layout": "^1.2.5",
|
||||
"react-modal": "^3.12.1",
|
||||
"react-redux": "^7.2.2",
|
||||
"react-refresh": "^0.8.3",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-vis": "^1.11.7",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"resolve": "1.18.1",
|
||||
"resolve-url-loader": "^3.1.2",
|
||||
"sass-loader": "8.0.2",
|
||||
"semver": "7.3.2",
|
||||
"style-loader": "1.3.0",
|
||||
"styled-components": "^5.2.1",
|
||||
"terser-webpack-plugin": "4.2.3",
|
||||
"terser-webpack-plugin": "^5.2.5",
|
||||
"ts-node": "^10.2.1",
|
||||
"ts-pnp": "1.2.0",
|
||||
"tsconfig-paths-webpack-plugin": "^3.5.1",
|
||||
"typescript": "^4.0.5",
|
||||
"url-loader": "4.1.1",
|
||||
"uuid": "^8.3.2",
|
||||
"web-vitals": "^0.2.4",
|
||||
"webpack": "^5.23.0",
|
||||
"webpack-dev-server": "^4.3.1",
|
||||
"webpack-manifest-plugin": "2.2.0",
|
||||
"workbox-webpack-plugin": "5.1.4"
|
||||
"webpack-dev-server": "^4.3.1"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
@@ -137,11 +91,20 @@
|
||||
"@testing-library/cypress": "^8.0.0",
|
||||
"@types/compression-webpack-plugin": "^9.0.0",
|
||||
"@types/copy-webpack-plugin": "^8.0.1",
|
||||
"@types/d3": "^6.2.0",
|
||||
"@types/d3-tip": "^3.5.5",
|
||||
"@types/jest": "^26.0.15",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^16.9.9",
|
||||
"@types/react-grid-layout": "^1.1.2",
|
||||
"@types/react-redux": "^7.1.11",
|
||||
"@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",
|
||||
@@ -149,6 +112,7 @@
|
||||
"@welldone-software/why-did-you-render": "^6.2.1",
|
||||
"autoprefixer": "^9.0.0",
|
||||
"babel-plugin-styled-components": "^1.12.0",
|
||||
"bundlesize": "^0.18.1",
|
||||
"compression-webpack-plugin": "^9.0.0",
|
||||
"copy-webpack-plugin": "^8.1.0",
|
||||
"cypress": "^8.3.0",
|
||||
@@ -161,11 +125,6 @@
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-csso": "^4.0.1",
|
||||
"gulp-debug": "^4.0.0",
|
||||
"gulp-less": "^4.0.1",
|
||||
"gulp-postcss": "^9.0.0",
|
||||
"husky": "4.3.8",
|
||||
"less-plugin-npm-import": "^2.1.0",
|
||||
"lint-staged": "10.5.3",
|
||||
@@ -173,7 +132,6 @@
|
||||
"portfinder-sync": "^0.0.2",
|
||||
"prettier": "2.2.1",
|
||||
"react-hot-loader": "^4.13.0",
|
||||
"react-is": "^17.0.1",
|
||||
"ts-node": "^10.2.1",
|
||||
"webpack-cli": "^4.5.0"
|
||||
}
|
||||
|
||||
@@ -4,24 +4,43 @@ import ROUTES from 'constants/routes';
|
||||
import AppLayout from 'container/AppLayout';
|
||||
import history from 'lib/history';
|
||||
import React, { Suspense } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Redirect, Route, Router, Switch } from 'react-router-dom';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import routes from './routes';
|
||||
|
||||
const App = (): JSX.Element => (
|
||||
<Router history={history}>
|
||||
<AppLayout>
|
||||
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
|
||||
<Switch>
|
||||
{routes.map(({ path, component, exact }, index) => (
|
||||
<Route key={index} exact={exact} path={path} component={component} />
|
||||
))}
|
||||
<Redirect from="/" to={ROUTES.APPLICATION} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</AppLayout>
|
||||
</Router>
|
||||
);
|
||||
|
||||
const App = (): JSX.Element => {
|
||||
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
|
||||
return (
|
||||
<Router history={history}>
|
||||
<AppLayout>
|
||||
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
|
||||
<Switch>
|
||||
{routes.map(({ path, component, exact }, index) => (
|
||||
<Route key={index} exact={exact} path={path} component={component} />
|
||||
))}
|
||||
<Route
|
||||
path="/"
|
||||
exact
|
||||
render={(): JSX.Element =>
|
||||
isLoggedIn ? (
|
||||
<Redirect to={ROUTES.APPLICATION} />
|
||||
) : (
|
||||
<Redirect to={ROUTES.SIGN_UP} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route path="*" component={NotFound} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</AppLayout>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { apiV1, AxiosAlertManagerInstance } from 'api';
|
||||
import { apiV2 } from 'api/apiV1';
|
||||
import { AxiosAlertManagerInstance } from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
const get = (key: string): string | null => {
|
||||
return localStorage.getItem(key);
|
||||
try {
|
||||
const value = localStorage.getItem(key);
|
||||
return value;
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
export default get;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
const remove = (key: string): void => {
|
||||
window.localStorage.removeItem(key);
|
||||
const remove = (key: string): boolean => {
|
||||
try {
|
||||
window.localStorage.removeItem(key);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export default remove;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
const set = (key: string, value: string): void => {
|
||||
localStorage.setItem(key, value);
|
||||
const set = (key: string, value: string): boolean => {
|
||||
try {
|
||||
localStorage.setItem(key, value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export default set;
|
||||
|
||||
@@ -8,7 +8,10 @@ const signup = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<undefined> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.post(`/user?email=${props.email}`);
|
||||
const response = await axios.post(`/user`, {
|
||||
email: props.email,
|
||||
name: props.name,
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
|
||||
21
frontend/src/api/userFeedback/sendFeedback.ts
Normal file
21
frontend/src/api/userFeedback/sendFeedback.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import axios from 'api';
|
||||
import { Props } from 'types/api/userFeedback/sendResponse';
|
||||
|
||||
const sendFeedback = async (props: Props): Promise<number> => {
|
||||
const response = await axios.post(
|
||||
'/feedback',
|
||||
{
|
||||
email: props.email,
|
||||
message: props.message,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return response.status;
|
||||
};
|
||||
|
||||
export default sendFeedback;
|
||||
@@ -3,7 +3,7 @@ import React, { useEffect, useRef } from 'react';
|
||||
|
||||
import { Container } from './styles';
|
||||
|
||||
const Editor = ({ value }: EditorProps) => {
|
||||
const Editor = ({ value }: EditorProps): JSX.Element => {
|
||||
const divEl = useRef<HTMLDivElement>(null);
|
||||
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();
|
||||
|
||||
@@ -28,7 +28,7 @@ const Editor = ({ value }: EditorProps) => {
|
||||
value.current = editor?.getValue() || '';
|
||||
});
|
||||
|
||||
return () => {
|
||||
return (): void => {
|
||||
if (editor) {
|
||||
editor.dispose();
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Typography } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
import { ColorContainer, Container } from './styles';
|
||||
|
||||
const Legend = ({ text, color }: LegendProps): JSX.Element => {
|
||||
if (text.length === 0) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ColorContainer color={color}></ColorContainer>
|
||||
<Typography>{text}</Typography>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
interface LegendProps {
|
||||
text: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export default Legend;
|
||||
@@ -1,20 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Container = styled.div`
|
||||
margin-left: 2rem;
|
||||
margin-right: 2rem;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const ColorContainer = styled.div<Props>`
|
||||
background-color: ${({ color }): string => color};
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 0.5rem;
|
||||
`;
|
||||
91
frontend/src/components/Graph/Plugin/Legend.ts
Normal file
91
frontend/src/components/Graph/Plugin/Legend.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { Plugin, ChartType, Chart, ChartOptions } from 'chart.js';
|
||||
import { colors } from 'lib/getRandomColor';
|
||||
|
||||
const getOrCreateLegendList = (chart: Chart, id: string, isLonger: boolean) => {
|
||||
const legendContainer = document.getElementById(id);
|
||||
let listContainer = legendContainer?.querySelector('ul');
|
||||
|
||||
if (!listContainer) {
|
||||
listContainer = document.createElement('ul');
|
||||
listContainer.style.display = 'flex';
|
||||
// listContainer.style.flexDirection = isLonger ? 'column' : 'row';
|
||||
listContainer.style.margin = '0';
|
||||
listContainer.style.padding = '0';
|
||||
listContainer.style.overflowY = 'scroll';
|
||||
listContainer.style.justifyContent = isLonger ? 'start' : 'center';
|
||||
listContainer.style.alignItems = isLonger ? 'start' : 'center';
|
||||
listContainer.style.height = '100%';
|
||||
listContainer.style.flexWrap = 'wrap';
|
||||
listContainer.style.justifyContent = 'center';
|
||||
|
||||
legendContainer?.appendChild(listContainer);
|
||||
}
|
||||
|
||||
return listContainer;
|
||||
};
|
||||
|
||||
export const legend = (id: string, isLonger: boolean): Plugin<ChartType> => {
|
||||
return {
|
||||
id: 'htmlLegend',
|
||||
afterUpdate(chart, args, options: ChartOptions) {
|
||||
const ul = getOrCreateLegendList(chart, id || 'legend', isLonger);
|
||||
|
||||
// Remove old legend items
|
||||
while (ul.firstChild) {
|
||||
ul.firstChild.remove();
|
||||
}
|
||||
|
||||
// Reuse the built-in legendItems generator
|
||||
const items = chart?.options?.plugins?.legend?.labels?.generateLabels(chart);
|
||||
|
||||
items?.forEach((item, index) => {
|
||||
const li = document.createElement('li');
|
||||
li.style.alignItems = 'center';
|
||||
li.style.cursor = 'pointer';
|
||||
li.style.display = 'flex';
|
||||
li.style.marginLeft = '10px';
|
||||
li.style.marginTop = '5px';
|
||||
|
||||
li.onclick = () => {
|
||||
const { type } = chart.config;
|
||||
if (type === 'pie' || type === 'doughnut') {
|
||||
// Pie and doughnut charts only have a single dataset and visibility is per item
|
||||
chart.toggleDataVisibility(index);
|
||||
} else {
|
||||
chart.setDatasetVisibility(
|
||||
item.datasetIndex,
|
||||
!chart.isDatasetVisible(item.datasetIndex),
|
||||
);
|
||||
}
|
||||
chart.update();
|
||||
};
|
||||
|
||||
// Color box
|
||||
const boxSpan = document.createElement('span');
|
||||
boxSpan.style.background = item.strokeStyle || colors[0];
|
||||
boxSpan.style.borderColor = item?.strokeStyle;
|
||||
boxSpan.style.borderWidth = item.lineWidth + 'px';
|
||||
boxSpan.style.display = 'inline-block';
|
||||
boxSpan.style.minHeight = '20px';
|
||||
boxSpan.style.marginRight = '10px';
|
||||
boxSpan.style.minWidth = '20px';
|
||||
boxSpan.style.borderRadius = '50%';
|
||||
|
||||
if (item.text) {
|
||||
// Text
|
||||
const textContainer = document.createElement('span');
|
||||
textContainer.style.margin = '0';
|
||||
textContainer.style.padding = '0';
|
||||
textContainer.style.textDecoration = item.hidden ? 'line-through' : '';
|
||||
|
||||
const text = document.createTextNode(item.text);
|
||||
textContainer.appendChild(text);
|
||||
|
||||
li.appendChild(boxSpan);
|
||||
li.appendChild(textContainer);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
1
frontend/src/components/Graph/Plugin/index.ts
Normal file
1
frontend/src/components/Graph/Plugin/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Legend';
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
Decimation,
|
||||
Filler,
|
||||
Legend,
|
||||
// LegendItem,
|
||||
LinearScale,
|
||||
LineController,
|
||||
LineElement,
|
||||
@@ -23,15 +22,11 @@ import {
|
||||
Tooltip,
|
||||
} from 'chart.js';
|
||||
import * as chartjsAdapter from 'chartjs-adapter-date-fns';
|
||||
// import { colors } from 'lib/getRandomColor';
|
||||
// import stringToHTML from 'lib/stringToHTML';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
// import Legends from './Legend';
|
||||
// import { LegendsContainer } from './styles';
|
||||
Chart.register(
|
||||
LineElement,
|
||||
PointElement,
|
||||
@@ -49,6 +44,8 @@ Chart.register(
|
||||
BarController,
|
||||
BarElement,
|
||||
);
|
||||
import { legend } from './Plugin';
|
||||
import { LegendsContainer } from './styles';
|
||||
|
||||
const Graph = ({
|
||||
data,
|
||||
@@ -56,6 +53,7 @@ const Graph = ({
|
||||
title,
|
||||
isStacked,
|
||||
onClickHandler,
|
||||
name,
|
||||
}: GraphProps): JSX.Element => {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||
@@ -95,20 +93,7 @@ const Graph = ({
|
||||
text: title,
|
||||
},
|
||||
legend: {
|
||||
// just making sure that label is present
|
||||
display: !(
|
||||
data.datasets.find((e) => {
|
||||
if (e.label?.length === 0) {
|
||||
return false;
|
||||
}
|
||||
return e.label !== undefined;
|
||||
}) === undefined
|
||||
),
|
||||
labels: {
|
||||
usePointStyle: true,
|
||||
pointStyle: 'circle',
|
||||
},
|
||||
position: 'bottom',
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
@@ -126,7 +111,7 @@ const Graph = ({
|
||||
time: {
|
||||
unit: 'minute',
|
||||
},
|
||||
type: 'timeseries',
|
||||
type: 'time',
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
@@ -156,6 +141,7 @@ const Graph = ({
|
||||
type: type,
|
||||
data: data,
|
||||
options,
|
||||
plugins: [legend(name, data.datasets.length > 3)],
|
||||
});
|
||||
}
|
||||
}, [chartRef, data, type, title, isStacked, getGridColor, onClickHandler]);
|
||||
@@ -164,7 +150,12 @@ const Graph = ({
|
||||
buildChart();
|
||||
}, [buildChart]);
|
||||
|
||||
return <canvas ref={chartRef} />;
|
||||
return (
|
||||
<div style={{ height: '85%' }}>
|
||||
<canvas ref={chartRef} />
|
||||
<LegendsContainer id={name} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface GraphProps {
|
||||
@@ -174,6 +165,7 @@ interface GraphProps {
|
||||
isStacked?: boolean;
|
||||
label?: string[];
|
||||
onClickHandler?: graphOnClickHandler;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type graphOnClickHandler = (
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const LegendsContainer = styled.div`
|
||||
display: flex;
|
||||
overflow-y: scroll;
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
height: 15%;
|
||||
|
||||
* {
|
||||
::-webkit-scrollbar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
-ms-overflow-style: none !important; /* IE and Edge */
|
||||
scrollbar-width: none !important; /* Firefox */
|
||||
}
|
||||
`;
|
||||
|
||||
127
frontend/src/container/AppLayout/FeedBack/index.tsx
Normal file
127
frontend/src/container/AppLayout/FeedBack/index.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import { CloseCircleOutlined, CommentOutlined } from '@ant-design/icons';
|
||||
import { Button, Divider, Form, Input, notification, Typography } from 'antd';
|
||||
import { Callbacks } from 'rc-field-form/lib/interface';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
|
||||
import {
|
||||
Button as IconButton,
|
||||
ButtonContainer,
|
||||
Card,
|
||||
CenterText,
|
||||
Container,
|
||||
TitleContainer,
|
||||
FormItem,
|
||||
} from './styles';
|
||||
const { Title } = Typography;
|
||||
const { TextArea } = Input;
|
||||
import sendFeedbackApi from 'api/userFeedback/sendFeedback';
|
||||
|
||||
const Feedback = (): JSX.Element => {
|
||||
const [isOpen, setisOpen] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
const [notifications, Element] = notification.useNotification();
|
||||
|
||||
const isToggleHandler = useCallback(() => {
|
||||
setisOpen((state) => !state);
|
||||
}, []);
|
||||
|
||||
const onFinishHandler: Callbacks<Feedback>['onFinish'] = async (
|
||||
value: Feedback,
|
||||
): Promise<void> => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const { feedback, email = '' } = value;
|
||||
|
||||
const response = await sendFeedbackApi({
|
||||
email,
|
||||
message: feedback,
|
||||
});
|
||||
|
||||
if (response === 200) {
|
||||
notifications.success({
|
||||
message: 'Thanks for your feedback!',
|
||||
description:
|
||||
'We have noted down your feedback and will work on improving SIgNoz based on that!',
|
||||
});
|
||||
|
||||
isToggleHandler();
|
||||
} else {
|
||||
notifications.error({
|
||||
message: 'Error!',
|
||||
description: 'Something went wrong',
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Something went wrong',
|
||||
});
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Container>
|
||||
{!isOpen && (
|
||||
<IconButton onClick={isToggleHandler} type="primary" size="large">
|
||||
<CommentOutlined />
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
{Element}
|
||||
|
||||
{isOpen && (
|
||||
<Form onFinish={onFinishHandler} form={form}>
|
||||
<Card>
|
||||
<TitleContainer>
|
||||
<Title
|
||||
aria-label="How can we improve SigNoz?"
|
||||
style={{ margin: 0 }}
|
||||
level={5}
|
||||
>
|
||||
How can we improve SigNoz?
|
||||
</Title>
|
||||
<CloseCircleOutlined onClick={isToggleHandler} />
|
||||
</TitleContainer>
|
||||
|
||||
<Divider />
|
||||
|
||||
<FormItem name="feedback" required>
|
||||
<TextArea
|
||||
required
|
||||
rows={3}
|
||||
placeholder="Share what can we improve ( e.g. Not able to find how to see metrics... )"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem name="email">
|
||||
<Input type="email" placeholder="Email (optional)" />
|
||||
</FormItem>
|
||||
|
||||
<CenterText>This will just be visible to our maintainers</CenterText>
|
||||
|
||||
<ButtonContainer>
|
||||
<Button
|
||||
disabled={isLoading}
|
||||
loading={isLoading}
|
||||
htmlType="submit"
|
||||
type="primary"
|
||||
>
|
||||
Share
|
||||
</Button>
|
||||
</ButtonContainer>
|
||||
</Card>
|
||||
</Form>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
interface Feedback {
|
||||
email?: string;
|
||||
feedback: string;
|
||||
}
|
||||
|
||||
export default Feedback;
|
||||
64
frontend/src/container/AppLayout/FeedBack/styles.ts
Normal file
64
frontend/src/container/AppLayout/FeedBack/styles.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
Button as ButtonComponent,
|
||||
Card as CardComponent,
|
||||
Typography,
|
||||
Form,
|
||||
} from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Container = styled.div`
|
||||
position: fixed;
|
||||
bottom: 5%;
|
||||
right: 4%;
|
||||
z-index: 999999;
|
||||
`;
|
||||
|
||||
export const CenterText = styled(Typography)`
|
||||
&&& {
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const TitleContainer = styled.div`
|
||||
&&& {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Card = styled(CardComponent)`
|
||||
&&& {
|
||||
min-width: 400px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ButtonContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const Button = styled(ButtonComponent)`
|
||||
height: 4rem !important;
|
||||
width: 4rem !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
border-radius: 25px !important;
|
||||
|
||||
background-color: #65b7f3;
|
||||
|
||||
svg {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FormItem = styled(Form.Item)`
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0.75rem;
|
||||
`;
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Layout } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import TopNav from 'container/Header';
|
||||
import SideNav from 'container/SideNav';
|
||||
@@ -8,7 +7,8 @@ import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
const { Content, Footer } = Layout;
|
||||
import Feedback from './FeedBack';
|
||||
import { Content, Footer, Layout } from './styles';
|
||||
|
||||
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
@@ -31,17 +31,17 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Layout>
|
||||
{!isSignUpPage && <SideNav />}
|
||||
<Layout className="site-layout">
|
||||
<Content style={{ margin: '0 16px' }}>
|
||||
<Layout>
|
||||
<Content>
|
||||
{!isSignUpPage && <TopNav />}
|
||||
{children}
|
||||
</Content>
|
||||
<Footer style={{ textAlign: 'center', fontSize: 10 }}>
|
||||
SigNoz Inc. ©{currentYear}
|
||||
</Footer>
|
||||
<Footer>{`SigNoz Inc. © ${currentYear}`}</Footer>
|
||||
</Layout>
|
||||
|
||||
<Feedback />
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Layout as LayoutComponent } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Layout = styled.div`
|
||||
export const Layout = styled(LayoutComponent)`
|
||||
&&& {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -20,7 +21,3 @@ export const Footer = styled(LayoutComponent.Footer)`
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Main = styled.main`
|
||||
min-height: 80vh;
|
||||
`;
|
||||
|
||||
@@ -19,7 +19,7 @@ const FormAlertChannels = ({
|
||||
type,
|
||||
setSelectedConfig,
|
||||
onTypeChangeHandler,
|
||||
onTestHandler,
|
||||
// onTestHandler,
|
||||
onSaveHandler,
|
||||
savingState,
|
||||
NotificationElement,
|
||||
@@ -92,8 +92,8 @@ interface FormAlertChannelsProps {
|
||||
onSaveHandler: (props: ChannelType) => void;
|
||||
savingState: boolean;
|
||||
NotificationElement: React.ReactElement<
|
||||
any,
|
||||
string | React.JSXElementConstructor<any>
|
||||
unknown,
|
||||
string | React.JSXElementConstructor<unknown>
|
||||
>;
|
||||
title: string;
|
||||
initialValue: Store;
|
||||
|
||||
@@ -56,17 +56,18 @@ const Retention = ({
|
||||
|
||||
const onChangeHandler = (
|
||||
e: React.ChangeEvent<HTMLInputElement>,
|
||||
func: React.Dispatch<React.SetStateAction<number>>,
|
||||
func: React.Dispatch<React.SetStateAction<string>>,
|
||||
): void => {
|
||||
const value = e.target.value;
|
||||
const integerValue = parseInt(value, 10);
|
||||
|
||||
if (value.length > 0) {
|
||||
const parsedValue = Math.abs(parseInt(value, 10));
|
||||
if (value.length > 0 && integerValue.toString() === value) {
|
||||
const parsedValue = Math.abs(integerValue).toString();
|
||||
func(parsedValue);
|
||||
}
|
||||
|
||||
if (value.length === 0) {
|
||||
func(0);
|
||||
func('');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -96,9 +97,9 @@ interface Option {
|
||||
}
|
||||
|
||||
interface RetentionProps {
|
||||
retentionValue: number;
|
||||
retentionValue: string;
|
||||
text: string;
|
||||
setRentionValue: React.Dispatch<React.SetStateAction<number>>;
|
||||
setRentionValue: React.Dispatch<React.SetStateAction<string>>;
|
||||
selectedRetentionPeroid: SettingPeroid;
|
||||
setSelectedRetentionPeroid: React.Dispatch<
|
||||
React.SetStateAction<SettingPeroid>
|
||||
|
||||
@@ -9,7 +9,12 @@ import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { PayloadProps } from 'types/api/settings/getRetention';
|
||||
|
||||
import Retention from './Retention';
|
||||
import { ButtonContainer, Container } from './styles';
|
||||
import {
|
||||
ButtonContainer,
|
||||
Container,
|
||||
ErrorText,
|
||||
ErrorTextContainer,
|
||||
} from './styles';
|
||||
|
||||
const GeneralSettings = (): JSX.Element => {
|
||||
const [
|
||||
@@ -18,8 +23,8 @@ const GeneralSettings = (): JSX.Element => {
|
||||
] = useState<SettingPeroid>('month');
|
||||
const [notifications, Element] = notification.useNotification();
|
||||
|
||||
const [retentionPeroidMetrics, setRetentionPeroidMetrics] = useState<number>(
|
||||
0,
|
||||
const [retentionPeroidMetrics, setRetentionPeroidMetrics] = useState<string>(
|
||||
'',
|
||||
);
|
||||
const [modal, setModal] = useState<boolean>(false);
|
||||
const [postApiLoading, setPostApiLoading] = useState<boolean>(false);
|
||||
@@ -28,7 +33,9 @@ const GeneralSettings = (): JSX.Element => {
|
||||
'hr',
|
||||
);
|
||||
|
||||
const [retentionPeroidTrace, setRetentionPeroidTrace] = useState<number>(0);
|
||||
const [retentionPeroidTrace, setRetentionPeroidTrace] = useState<string>('');
|
||||
const [isDefaultMetrics, setIsDefaultMetrics] = useState<boolean>(false);
|
||||
const [isDefaultTrace, setIsDefaultTrace] = useState<boolean>(false);
|
||||
|
||||
const onClickSaveHandler = useCallback(() => {
|
||||
onModalToggleHandler();
|
||||
@@ -43,17 +50,33 @@ const GeneralSettings = (): JSX.Element => {
|
||||
setModal((modal) => !modal);
|
||||
};
|
||||
|
||||
const checkMetricTraceDefault = (trace: number, metric: number): void => {
|
||||
if (metric === -1) {
|
||||
setIsDefaultMetrics(true);
|
||||
} else {
|
||||
setIsDefaultMetrics(false);
|
||||
}
|
||||
|
||||
if (trace === -1) {
|
||||
setIsDefaultTrace(true);
|
||||
} else {
|
||||
setIsDefaultTrace(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && payload !== undefined) {
|
||||
const { metrics_ttl_duration_hrs, traces_ttl_duration_hrs } = payload;
|
||||
|
||||
checkMetricTraceDefault(traces_ttl_duration_hrs, metrics_ttl_duration_hrs);
|
||||
|
||||
const traceValue = getSettingsPeroid(traces_ttl_duration_hrs);
|
||||
const metricsValue = getSettingsPeroid(metrics_ttl_duration_hrs);
|
||||
|
||||
setRetentionPeroidTrace(traceValue.value);
|
||||
setRetentionPeroidTrace(traceValue.value.toString());
|
||||
setSelectedTracePeroid(traceValue.peroid);
|
||||
|
||||
setRetentionPeroidMetrics(metricsValue.value);
|
||||
setRetentionPeroidMetrics(metricsValue.value.toString());
|
||||
setSelectedMetricsPeroid(metricsValue.peroid);
|
||||
}
|
||||
}, [setSelectedMetricsPeroid, loading, payload]);
|
||||
@@ -61,14 +84,25 @@ const GeneralSettings = (): JSX.Element => {
|
||||
const onOkHandler = async (): Promise<void> => {
|
||||
try {
|
||||
setPostApiLoading(true);
|
||||
const retentionTraceValue =
|
||||
retentionPeroidTrace === '0' && (payload?.traces_ttl_duration_hrs || 0) < 0
|
||||
? payload?.traces_ttl_duration_hrs || 0
|
||||
: parseInt(retentionPeroidTrace, 10);
|
||||
|
||||
const retentionMetricsValue =
|
||||
retentionPeroidMetrics === '0' &&
|
||||
(payload?.metrics_ttl_duration_hrs || 0) < 0
|
||||
? payload?.metrics_ttl_duration_hrs || 0
|
||||
: parseInt(retentionPeroidMetrics, 10);
|
||||
|
||||
const [tracesResponse, metricsResponse] = await Promise.all([
|
||||
setRetentionApi({
|
||||
duration: `${convertIntoHr(retentionPeroidTrace, selectedTracePeroid)}h`,
|
||||
duration: `${convertIntoHr(retentionTraceValue, selectedTracePeroid)}h`,
|
||||
type: 'traces',
|
||||
}),
|
||||
setRetentionApi({
|
||||
duration: `${convertIntoHr(
|
||||
retentionPeroidMetrics,
|
||||
retentionMetricsValue,
|
||||
selectedMetricsPeroid,
|
||||
)}h`,
|
||||
type: 'metrics',
|
||||
@@ -84,6 +118,9 @@ const GeneralSettings = (): JSX.Element => {
|
||||
placement: 'topRight',
|
||||
description: 'Congrats. The retention periods were updated correctly.',
|
||||
});
|
||||
|
||||
checkMetricTraceDefault(retentionTraceValue, retentionMetricsValue);
|
||||
|
||||
onModalToggleHandler();
|
||||
} else {
|
||||
notifications.error({
|
||||
@@ -112,10 +149,45 @@ const GeneralSettings = (): JSX.Element => {
|
||||
return <Spinner tip="Loading.." height="70vh" />;
|
||||
}
|
||||
|
||||
const getErrorText = (): string => {
|
||||
const getValue = (value: string): string =>
|
||||
`Retention Peroid for ${value} is not set yet. Please set by choosing below`;
|
||||
|
||||
if (!isDefaultMetrics && !isDefaultTrace) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (isDefaultMetrics && !isDefaultTrace) {
|
||||
return `${getValue('Metrics')}`;
|
||||
}
|
||||
|
||||
if (!isDefaultMetrics && isDefaultTrace) {
|
||||
return `${getValue('Trace')}`;
|
||||
}
|
||||
|
||||
return `${getValue('Trace , Metrics')}`;
|
||||
};
|
||||
|
||||
const isDisabledHandler = (): boolean => {
|
||||
if (retentionPeroidTrace === '' || retentionPeroidMetrics === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const errorText = getErrorText();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
{Element}
|
||||
|
||||
{errorText && (
|
||||
<ErrorTextContainer>
|
||||
<ErrorText>{errorText}</ErrorText>
|
||||
</ErrorTextContainer>
|
||||
)}
|
||||
|
||||
<Retention
|
||||
text={'Retention Period for Metrics'}
|
||||
selectedRetentionPeroid={selectedMetricsPeroid}
|
||||
@@ -150,7 +222,11 @@ const GeneralSettings = (): JSX.Element => {
|
||||
</Modal>
|
||||
|
||||
<ButtonContainer>
|
||||
<Button onClick={onClickSaveHandler} type="primary">
|
||||
<Button
|
||||
onClick={onClickSaveHandler}
|
||||
disabled={isDisabledHandler()}
|
||||
type="primary"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</ButtonContainer>
|
||||
|
||||
@@ -59,3 +59,17 @@ export const TextContainer = styled.div`
|
||||
min-width: 100px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ErrorTextContainer = styled.div`
|
||||
&&& {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ErrorText = styled(TypographyComponent)`
|
||||
&&& {
|
||||
color: #e89a3c;
|
||||
font-style: italic;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -15,6 +15,7 @@ const GridGraphComponent = ({
|
||||
opacity,
|
||||
isStacked,
|
||||
onClickHandler,
|
||||
name,
|
||||
}: GridGraphComponentProps): JSX.Element | null => {
|
||||
const location = history.location.pathname;
|
||||
|
||||
@@ -31,6 +32,7 @@ const GridGraphComponent = ({
|
||||
opacity,
|
||||
xAxisType: 'time',
|
||||
onClickHandler: onClickHandler,
|
||||
name,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -69,6 +71,7 @@ export interface GridGraphComponentProps {
|
||||
opacity?: string;
|
||||
isStacked?: boolean;
|
||||
onClickHandler?: graphOnClickHandler;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default GridGraphComponent;
|
||||
|
||||
@@ -27,6 +27,7 @@ const FullView = ({
|
||||
fullViewOptions = true,
|
||||
onClickHandler,
|
||||
noDataGraph = false,
|
||||
name,
|
||||
}: FullViewProps): JSX.Element => {
|
||||
const { minTime, maxTime } = useSelector<AppState, GlobalTime>(
|
||||
(state) => state.globalTime,
|
||||
@@ -189,18 +190,19 @@ const FullView = ({
|
||||
</TimeContainer>
|
||||
)}
|
||||
|
||||
<GraphContainer>
|
||||
<GridGraphComponent
|
||||
{...{
|
||||
GRAPH_TYPES: widget.panelTypes,
|
||||
data: state.payload,
|
||||
isStacked: widget.isStacked,
|
||||
opacity: widget.opacity,
|
||||
title: widget.title,
|
||||
onClickHandler: onClickHandler,
|
||||
}}
|
||||
/>
|
||||
</GraphContainer>
|
||||
{/* <GraphContainer> */}
|
||||
<GridGraphComponent
|
||||
{...{
|
||||
GRAPH_TYPES: widget.panelTypes,
|
||||
data: state.payload,
|
||||
isStacked: widget.isStacked,
|
||||
opacity: widget.opacity,
|
||||
title: widget.title,
|
||||
onClickHandler: onClickHandler,
|
||||
name,
|
||||
}}
|
||||
/>
|
||||
{/* </GraphContainer> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -217,6 +219,7 @@ interface FullViewProps {
|
||||
fullViewOptions?: boolean;
|
||||
onClickHandler?: graphOnClickHandler;
|
||||
noDataGraph?: boolean;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default FullView;
|
||||
|
||||
@@ -23,12 +23,13 @@ import { Widgets } from 'types/api/dashboard/getAll';
|
||||
|
||||
import Bar from './Bar';
|
||||
import FullView from './FullView';
|
||||
import { Modal } from './styles';
|
||||
import { Modal, FullViewContainer } from './styles';
|
||||
|
||||
const GridCardGraph = ({
|
||||
widget,
|
||||
deleteWidget,
|
||||
isDeleted,
|
||||
name,
|
||||
}: GridCardGraphProps): JSX.Element => {
|
||||
const [state, setState] = useState<GridCardGraphState>({
|
||||
loading: true,
|
||||
@@ -166,7 +167,9 @@ const GridCardGraph = ({
|
||||
width="85%"
|
||||
destroyOnClose
|
||||
>
|
||||
<FullView widget={widget} />
|
||||
<FullViewContainer>
|
||||
<FullView name={name} widget={widget} />
|
||||
</FullViewContainer>
|
||||
</Modal>
|
||||
|
||||
<GridGraphComponent
|
||||
@@ -176,6 +179,7 @@ const GridCardGraph = ({
|
||||
isStacked: widget.isStacked,
|
||||
opacity: widget.opacity,
|
||||
title: widget.title,
|
||||
name,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
@@ -198,6 +202,7 @@ interface DispatchProps {
|
||||
interface GridCardGraphProps extends DispatchProps {
|
||||
widget: Widgets;
|
||||
isDeleted: React.MutableRefObject<boolean>;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (
|
||||
|
||||
@@ -11,3 +11,7 @@ export const Modal = styled(ModalComponent)<Props>`
|
||||
min-height: ${({ height = '80vh' }): string => height};
|
||||
}
|
||||
`;
|
||||
|
||||
export const FullViewContainer = styled.div`
|
||||
height: 70vh;
|
||||
`;
|
||||
|
||||
@@ -60,7 +60,11 @@ const GridGraph = (): JSX.Element => {
|
||||
i: (index + 1).toString(),
|
||||
x: (index % 2) * 6,
|
||||
Component: (): JSX.Element => (
|
||||
<Graph isDeleted={isDeleted} widget={widgets[index]} />
|
||||
<Graph
|
||||
name={e.id + index}
|
||||
isDeleted={isDeleted}
|
||||
widget={widgets[index]}
|
||||
/>
|
||||
),
|
||||
};
|
||||
});
|
||||
@@ -69,7 +73,7 @@ const GridGraph = (): JSX.Element => {
|
||||
...e,
|
||||
y: 0,
|
||||
Component: (): JSX.Element => (
|
||||
<Graph isDeleted={isDeleted} widget={widgets[index]} />
|
||||
<Graph name={e.i + index} isDeleted={isDeleted} widget={widgets[index]} />
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export const Card = styled(CardComponent)<Props>`
|
||||
}
|
||||
|
||||
.ant-card-body {
|
||||
height: 100%;
|
||||
height: 95%;
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -4,8 +4,8 @@ import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { getDefaultOption, getOptions, Time } from './config';
|
||||
import { Container, Form, FormItem } from './styles';
|
||||
const { Option } = DefaultSelect;
|
||||
import get from 'api/browser/localstorage/get';
|
||||
import set from 'api/browser/localstorage/set';
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
import { LOCAL_STORAGE } from 'constants/localStorage';
|
||||
import getTimeString from 'lib/getTimeString';
|
||||
import moment from 'moment';
|
||||
@@ -32,8 +32,8 @@ const DateTimeSelection = ({
|
||||
const searchStartTime = params.get('startTime');
|
||||
const searchEndTime = params.get('endTime');
|
||||
|
||||
const localstorageStartTime = get('startTime');
|
||||
const localstorageEndTime = get('endTime');
|
||||
const localstorageStartTime = getLocalStorageKey('startTime');
|
||||
const localstorageEndTime = getLocalStorageKey('endTime');
|
||||
|
||||
const getTime = useCallback((): [number, number] | undefined => {
|
||||
if (searchEndTime && searchStartTime) {
|
||||
@@ -83,10 +83,10 @@ const DateTimeSelection = ({
|
||||
const getDefaultTime = (pathName: string): Time => {
|
||||
const defaultSelectedOption = getDefaultOption(pathName);
|
||||
|
||||
const routes = get(LOCAL_STORAGE.METRICS_TIME_IN_DURATION);
|
||||
const routes = getLocalStorageKey(LOCAL_STORAGE.METRICS_TIME_IN_DURATION);
|
||||
|
||||
if (routes !== null) {
|
||||
const routesObject = JSON.parse(routes);
|
||||
const routesObject = JSON.parse(routes || '{}');
|
||||
const selectedTime = routesObject[pathName];
|
||||
|
||||
if (selectedTime) {
|
||||
@@ -102,7 +102,7 @@ const DateTimeSelection = ({
|
||||
);
|
||||
|
||||
const updateLocalStorageForRoutes = (value: Time): void => {
|
||||
const preRoutes = get(LOCAL_STORAGE.METRICS_TIME_IN_DURATION);
|
||||
const preRoutes = getLocalStorageKey(LOCAL_STORAGE.METRICS_TIME_IN_DURATION);
|
||||
if (preRoutes !== null) {
|
||||
const preRoutesObject = JSON.parse(preRoutes);
|
||||
|
||||
@@ -111,7 +111,10 @@ const DateTimeSelection = ({
|
||||
};
|
||||
preRoute[location.pathname] = value;
|
||||
|
||||
set(LOCAL_STORAGE.METRICS_TIME_IN_DURATION, JSON.stringify(preRoute));
|
||||
setLocalStorageKey(
|
||||
LOCAL_STORAGE.METRICS_TIME_IN_DURATION,
|
||||
JSON.stringify(preRoute),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -194,8 +197,8 @@ const DateTimeSelection = ({
|
||||
startTimeMoment?.toDate().getTime() || 0,
|
||||
endTimeMoment?.toDate().getTime() || 0,
|
||||
]);
|
||||
set('startTime', startTimeMoment.toString());
|
||||
set('endTime', endTimeMoment.toString());
|
||||
setLocalStorageKey('startTime', startTimeMoment.toString());
|
||||
setLocalStorageKey('endTime', endTimeMoment.toString());
|
||||
updateLocalStorageForRoutes('custom');
|
||||
}
|
||||
}
|
||||
@@ -203,10 +206,15 @@ const DateTimeSelection = ({
|
||||
|
||||
// this is triggred when we change the routes and based on that we are changing the default options
|
||||
useEffect(() => {
|
||||
const metricsTimeDuration = get(LOCAL_STORAGE.METRICS_TIME_IN_DURATION);
|
||||
const metricsTimeDuration = getLocalStorageKey(
|
||||
LOCAL_STORAGE.METRICS_TIME_IN_DURATION,
|
||||
);
|
||||
|
||||
if (metricsTimeDuration === null) {
|
||||
set(LOCAL_STORAGE.METRICS_TIME_IN_DURATION, JSON.stringify({}));
|
||||
setLocalStorageKey(
|
||||
LOCAL_STORAGE.METRICS_TIME_IN_DURATION,
|
||||
JSON.stringify({}),
|
||||
);
|
||||
}
|
||||
|
||||
const currentRoute = location.pathname;
|
||||
|
||||
@@ -2,12 +2,18 @@ import { Col } from 'antd';
|
||||
import ROUTES from 'constants/routes';
|
||||
import history from 'lib/history';
|
||||
import React from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import ShowBreadcrumbs from './Breadcrumbs';
|
||||
import DateTimeSelector from './DateTimeSelection';
|
||||
import { Container } from './styles';
|
||||
|
||||
const routesToSkip = [ROUTES.SETTINGS, ROUTES.LIST_ALL_ALERT];
|
||||
|
||||
|
||||
const TopNav = (): JSX.Element | null => {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
if (history.location.pathname === ROUTES.SIGN_UP) {
|
||||
return null;
|
||||
}
|
||||
@@ -18,9 +24,11 @@ const TopNav = (): JSX.Element | null => {
|
||||
<ShowBreadcrumbs />
|
||||
</Col>
|
||||
|
||||
<Col span={8}>
|
||||
<DateTimeSelector />
|
||||
</Col>
|
||||
{!routesToSkip.includes(pathname) && (
|
||||
<Col span={8}>
|
||||
<DateTimeSelector />
|
||||
</Col>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user