diff --git a/docker-compose.yaml b/docker-compose.yaml index 6e06b4b..4813c2b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -28,5 +28,96 @@ services: ports: - "8080:8080" + grafana: + image: grafana/grafana:10.3.1 + container_name: grafana + ports: + - "3000:3000" + depends_on: + prometheus: + condition: service_healthy + loki: + condition: service_healthy + tempo: + condition: service_started + alloy: + condition: service_started + environment: + GF_AUTH_ANONYMOUS_ENABLED: true + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: admin + GF_METRICS_ENABLED: "true" + volumes: + - ./infrastructure/grafana/provisioning:/etc/grafana/provisioning + - ./infrastructure/grafana/dashboards:/var/lib/grafana/dashboards + healthcheck: + test: [ "CMD", "wget", "--spider", "http://localhost:3000/api/health" ] + interval: 10s + timeout: 5s + retries: 10 + + prometheus: + image: prom/prometheus:latest + container_name: prometheus + ports: + - "9090:9090" + volumes: + - ./infrastructure/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml + healthcheck: + test: [ "CMD", "wget", "--spider", "http://localhost:9090/-/healthy" ] + interval: 10s + timeout: 5s + retries: 5 + + loki: + image: grafana/loki:2.9.2 + container_name: loki + ports: + - "3100:3100" + volumes: + - ./infrastructure/loki/loki-config.yaml:/etc/loki/loki-config.yaml:ro + healthcheck: + test: [ "CMD", "wget", "--spider", "-q", "http://localhost:3100/ready" ] + interval: 10s + timeout: 5s + retries: 5 + + tempo: + image: grafana/tempo:2.4.1 + container_name: tempo + command: [ "-config.file=/etc/tempo/tempo.yaml" ] + volumes: + - ./infrastructure/tempo/tempo.yaml:/etc/tempo/tempo.yaml + - tempo_data:/var/tempo + ports: + - "3200:3200" + + alloy: + image: grafana/alloy:latest + container_name: alloy + user: root + ports: + - "9080:9080" # HTTP interface + - "4317:4317" # OTLP gRPC + - "4318:4318" # OTLP http + volumes: + - ./infrastructure/alloy/config.alloy:/etc/alloy/config.alloy:ro + - /var/lib/docker/containers:/var/lib/docker/containers:ro + - /var/run/docker.sock:/var/run/docker.sock + - /var/log:/var/log:ro + environment: + GRAFANA_LOKI_URL: http://loki:3100/loki/api/v1/push + command: + - run + - --server.http.listen-addr=0.0.0.0:9080 + - --storage.path=/var/lib/alloy/data + - /etc/alloy/config.alloy + volumes: - pgdata: \ No newline at end of file + pgdata: + artifacts: + tempo_data: + loki_data: + loki_chunks: + loki_index: + loki_rules: \ No newline at end of file diff --git a/infrastructure/alloy/config.alloy b/infrastructure/alloy/config.alloy new file mode 100644 index 0000000..ff0acbd --- /dev/null +++ b/infrastructure/alloy/config.alloy @@ -0,0 +1,74 @@ +loki.write "local" { + endpoint { + url = "http://loki:3100/loki/api/v1/push" + } +} + +discovery.docker "containers" { + host = "unix:///var/run/docker.sock" + refresh_interval = "5s" +} + +discovery.relabel "containers" { + targets = discovery.docker.containers.targets + + rule { + source_labels = ["__meta_docker_container_name"] + regex = "/(.*)" + target_label = "container" + } + + rule { + target_label = "job" + replacement = "docker" + } + + rule { + target_label = "host" + replacement = constants.hostname + } + + rule { + source_labels = ["__meta_docker_container_name"] + regex = "/(.*)" + target_label = "service" + } + + rule { + source_labels = ["__meta_docker_container_log_stream"] + target_label = "stream" + } +} + +loki.source.docker "containers" { + host = "unix:///var/run/docker.sock" + targets = discovery.docker.containers.targets + relabel_rules = discovery.relabel.containers.rules + forward_to = [loki.write.local.receiver] +} + +otelcol.receiver.otlp "default" { + grpc { + endpoint = "0.0.0.0:4317" + } + http { + endpoint = "0.0.0.0:4318" + } + output { + traces = [otelcol.exporter.otlp.tempo.input] + metrics = [otelcol.exporter.prometheus.default.input] + } +} + +otelcol.exporter.otlp "tempo" { + client { + endpoint = "tempo:4317" + tls { + insecure = true + } + } +} + +otelcol.exporter.prometheus "default" { + forward_to = [] +} \ No newline at end of file diff --git a/infrastructure/grafana/dashboards/postgres-overview.json b/infrastructure/grafana/dashboards/postgres-overview.json new file mode 100644 index 0000000..0fee3c9 --- /dev/null +++ b/infrastructure/grafana/dashboards/postgres-overview.json @@ -0,0 +1,43 @@ +{ + "title": "Postgres Overview", + "timezone": "browser", + "schemaVersion": 39, + "version": 1, + "refresh": "10s", + "panels": [ + { + "type": "gauge", + "title": "pg_up", + "targets": [{ "expr": "pg_up", "refId": "A" }], + "gridPos": { "x": 0, "y": 0, "w": 4, "h": 6 } + }, + { + "type": "timeseries", + "title": "Active sessions by state", + "targets": [ + { "expr": "sum by (state,instance) (pg_stat_activity_count)", "refId": "A" } + ], + "gridPos": { "x": 4, "y": 0, "w": 20, "h": 6 } + }, + { + "type": "timeseries", + "title": "Transactions per second (commits+rollbacks)", + "targets": [ + { "expr": "sum(rate(pg_stat_database_xact_commit[1m])) + sum(rate(pg_stat_database_xact_rollback[1m]))", "refId": "A" } + ], + "gridPos": { "x": 0, "y": 6, "w": 12, "h": 8 } + }, + { + "type": "timeseries", + "title": "Tuples fetched/returned/inserted/updated/deleted", + "targets": [ + { "expr": "sum(rate(pg_stat_database_tup_fetched[1m]))", "legendFormat": "fetched", "refId": "A" }, + { "expr": "sum(rate(pg_stat_database_tup_returned[1m]))", "legendFormat": "returned", "refId": "B" }, + { "expr": "sum(rate(pg_stat_database_tup_inserted[1m]))", "legendFormat": "inserted", "refId": "C" }, + { "expr": "sum(rate(pg_stat_database_tup_updated[1m]))", "legendFormat": "updated", "refId": "D" }, + { "expr": "sum(rate(pg_stat_database_tup_deleted[1m]))", "legendFormat": "deleted", "refId": "E" } + ], + "gridPos": { "x": 12, "y": 6, "w": 12, "h": 8 } + } + ] +} \ No newline at end of file diff --git a/infrastructure/grafana/datasources/datasources.yaml b/infrastructure/grafana/datasources/datasources.yaml new file mode 100644 index 0000000..751bc8d --- /dev/null +++ b/infrastructure/grafana/datasources/datasources.yaml @@ -0,0 +1,20 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + - name: Loki + type: loki + access: proxy + url: http://loki:3100 + isDefault: false + editable: true + - name: Tempo + type: tempo + access: proxy + url: http://tempo:3200 + isDefault: false + editable: true \ No newline at end of file diff --git a/infrastructure/grafana/provisioning/dashboards/dashboards.yml b/infrastructure/grafana/provisioning/dashboards/dashboards.yml new file mode 100644 index 0000000..51eb472 --- /dev/null +++ b/infrastructure/grafana/provisioning/dashboards/dashboards.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: 'default' + folder: 'Individuals-api' + type: file + disableDeletion: false + editable: true + options: + path: /var/lib/grafana/dashboards + foldersFromFilesStructure: true \ No newline at end of file diff --git a/infrastructure/grafana/provisioning/datasources/datasources.yaml b/infrastructure/grafana/provisioning/datasources/datasources.yaml new file mode 100644 index 0000000..751bc8d --- /dev/null +++ b/infrastructure/grafana/provisioning/datasources/datasources.yaml @@ -0,0 +1,20 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + - name: Loki + type: loki + access: proxy + url: http://loki:3100 + isDefault: false + editable: true + - name: Tempo + type: tempo + access: proxy + url: http://tempo:3200 + isDefault: false + editable: true \ No newline at end of file diff --git a/infrastructure/loki/loki-config.yaml b/infrastructure/loki/loki-config.yaml new file mode 100644 index 0000000..78c8f3b --- /dev/null +++ b/infrastructure/loki/loki-config.yaml @@ -0,0 +1,56 @@ +auth_enabled: false + +server: + http_listen_post: 3100 + +ingester: + lifecycler: + address: 0.0.0.0 + ring: + kvstore: + store: summary + replication_factor: 1 + final_sleep: 0s + chunk_idle_period: 5m + chunk_retain_period: 30s + max_transfer_retries: 0 + +schema_config: + configs: + - from: 2018-04-15 + store: boltdb + object_store: filesystem + schema: v11 + index: + prefix: index_ + period: 168h + +storage_config: + boltdb: + directory: /loki/index + filesystem: + directory: /loki/chunks + +limits_config: + enforce_metric_name: false + reject_old_samples: true + reject_old_samples_max_age: 168h + ingestion_rate_mb: 8 + ingestion_burst_size_md: 10 + +chunk_storage_config: + max_look_back_period: 0s + +table_manager: + chunk_tables_provisioning: + inactive_read_throughput: 0 + inactive_write_throughput: 0 + provisioned_read_throughput: 0 + provisioned_write_throughput: 0 + index_tables_provisioning: + inactive_read_throughput: 0 + inactive_write_throughput: 0 + provisioned_read_throughput: 0 + provisioned_write_throughput: 0 + retention_deletes_enabled: true + retention_period: 672h \ No newline at end of file diff --git a/infrastructure/prometheus/prometheus.yml b/infrastructure/prometheus/prometheus.yml new file mode 100644 index 0000000..13d29f8 --- /dev/null +++ b/infrastructure/prometheus/prometheus.yml @@ -0,0 +1,53 @@ +global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + + +scrape_configs: + - job_name: prometheus + static_configs: + - targets: [ "prometheus:9090" ] + + - job_name: api + metrics_path: /actuator/prometheus + static_configs: + - targets: [ 'api:8091' ] + + - job_name: persons-api + metrics_path: /actuator/prometheus + static_configs: + - targets: [ 'persons-api:8092' ] + + - job_name: keycloak + metrics_path: /metrics + static_configs: + - targets: [ 'keycloak:9000' ] + + - job_name: grafana + metrics_path: /metrics + static_configs: + - targets: [ 'grafana:3000' ] + + - job_name: alloy + metrics_path: /metrics + static_configs: + - targets: [ 'alloy:9080' ] + + - job_name: loki + metrics_path: /metrics + static_configs: + - targets: [ 'loki:3100' ] + + - job_name: tempo + metrics_path: /metrics + static_configs: + - targets: [ 'tempo:3200' ] + + - job_name: person-postgres + static_configs: + - targets: [ 'person-postgres-exporter:9187' ] + + - job_name: keycloak-postgres + static_configs: + - targets: [ 'keycloak-postgres-exporter:9187' ] \ No newline at end of file diff --git a/infrastructure/tempo/tempo.yaml b/infrastructure/tempo/tempo.yaml new file mode 100644 index 0000000..76a1227 --- /dev/null +++ b/infrastructure/tempo/tempo.yaml @@ -0,0 +1,22 @@ +server: + http_listen_port: 3200 + +distributor: + receivers: + otlp: + protocols: + grpc: + http: + +ingester: + trace_idle_period: 10s + +compactor: + compaction: + compacted_block_retention: 48h + +storage: + trace: + backend: local + local: + path: /var/tempo/traces \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..9f387a3 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,21 @@ + + + + + + + + + + {"timestamp":"%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}", "trace_id": "%X{trace_id}", + "span_id":"%X{span_id}", "level":"%level", "thread":"%thread", + "logger":"%logger{36}","message":"%msg"}%n + + + + + + + + + \ No newline at end of file