├── requirements.txt ├── .gitignore ├── flask ├── wsgi.py └── app.py ├── images ├── entsoe.png ├── kepler.png ├── energymix.png └── Traffic_FRA_DEU.jpg.webp ├── presentations └── openinfraday-germany-2024 │ └── Starting_GreenOps_OpenInfra_2024.pdf ├── chart ├── Chart.lock ├── templates │ ├── grafana-dashboards.yaml │ ├── entsoe-service.yaml │ ├── entsoe-secret.yaml │ ├── entsoe-servicemonitor.yaml │ ├── entsoe-networkpolicy.yaml │ ├── _helpers.tpl │ ├── entsoe-deployment.yaml │ └── policyexception.yaml ├── Chart.yaml ├── values.yaml └── files │ ├── kepler-dashboard.json │ └── caas-carbon-dashboard.json ├── examples ├── hpa │ ├── hpa.yaml │ ├── deployment.yaml │ └── carbon-cronjob.yaml ├── resources │ ├── deployment.yaml │ └── carbon-cronjob.yaml ├── keda-prometheus │ └── prometheus-scale.yaml ├── README.md └── quota │ └── carbon-cronjob.yaml ├── Dockerfile ├── .github └── workflows │ ├── helm.yaml │ ├── build.yaml │ └── e2e.yaml └── README.md /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | gunicorn 3 | entsoe-py 4 | jq 5 | xmltodict 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | secret.yaml 3 | schiff* 4 | chart/charts/ 5 | chart/s01.yaml 6 | -------------------------------------------------------------------------------- /flask/wsgi.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | 3 | if __name__ == "__main__": 4 | app.run() 5 | -------------------------------------------------------------------------------- /images/entsoe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caas-team/caas-carbon-footprint/HEAD/images/entsoe.png -------------------------------------------------------------------------------- /images/kepler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caas-team/caas-carbon-footprint/HEAD/images/kepler.png -------------------------------------------------------------------------------- /images/energymix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caas-team/caas-carbon-footprint/HEAD/images/energymix.png -------------------------------------------------------------------------------- /images/Traffic_FRA_DEU.jpg.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caas-team/caas-carbon-footprint/HEAD/images/Traffic_FRA_DEU.jpg.webp -------------------------------------------------------------------------------- /presentations/openinfraday-germany-2024/Starting_GreenOps_OpenInfra_2024.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caas-team/caas-carbon-footprint/HEAD/presentations/openinfraday-germany-2024/Starting_GreenOps_OpenInfra_2024.pdf -------------------------------------------------------------------------------- /chart/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: kepler 3 | repository: https://sustainable-computing-io.github.io/kepler-helm-chart 4 | version: 0.6.1 5 | digest: sha256:bb0a8fc267337faf6b59f2f2025fb56dd0bad6a46f371ac67a380ddb2721f942 6 | generated: "2025-11-21T18:22:55.723152041+01:00" 7 | -------------------------------------------------------------------------------- /examples/hpa/hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v2 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: demoapp 5 | spec: 6 | maxReplicas: 1 7 | metrics: 8 | - resource: 9 | name: cpu 10 | target: 11 | averageUtilization: 90 12 | type: Utilization 13 | type: Resource 14 | minReplicas: 1 15 | scaleTargetRef: 16 | apiVersion: apps/v1 17 | kind: Deployment 18 | name: demoapp 19 | -------------------------------------------------------------------------------- /chart/templates/grafana-dashboards.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ include "caas-carbon-footprint.fullname" . }}-dashboards 6 | {{- if .Values.rancher.cattleDashboards }} 7 | namespace: cattle-dashboards 8 | {{- end }} 9 | labels: 10 | grafana_dashboard: "1" 11 | {{- if .Values.rancher.cattleDashboards }} 12 | release: rancher-monitoring 13 | {{- end }} 14 | data: 15 | {{ (.Files.Glob "files/*").AsConfig | indent 2 }} 16 | -------------------------------------------------------------------------------- /chart/templates/entsoe-service.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.entsoe.enabled }} 2 | --- 3 | kind: Service 4 | apiVersion: v1 5 | metadata: 6 | name: entsoe-{{ include "caas-carbon-footprint.fullname" . }} 7 | labels: 8 | app.kubernetes.io/component: entsoe 9 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 10 | spec: 11 | selector: 12 | {{- include "caas-carbon-footprint.selectorLabels" . | nindent 4 }} 13 | ports: 14 | - name: http 15 | port: 80 16 | targetPort: 9091 17 | {{ end }} 18 | -------------------------------------------------------------------------------- /chart/templates/entsoe-secret.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.entsoe.enabled }} 2 | {{- if .Values.entsoe.entsoe_api_key}} 3 | apiVersion: v1 4 | kind: Secret 5 | type: Opaque 6 | metadata: 7 | annotations: 8 | "helm.sh/resource-policy": keep 9 | name: entsoe-{{ include "caas-carbon-footprint.fullname" . }} 10 | labels: 11 | app.kubernetes.io/component: entsoe 12 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }}-entso 13 | data: 14 | entsoe_api_key: {{ .Values.entsoe.entsoe_api_key | b64enc | quote }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /chart/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | annotations: 3 | catalog.cattle.io/display-name: CaaS Carbon Footprint 4 | name: caas-carbon-footprint 5 | description: A Helm chart for carbon footprint measurement 6 | version: "1.0.0" 7 | appVersion: "1.0.0" 8 | keywords: 9 | - monitoring 10 | dependencies: 11 | - name: kepler 12 | version: "0.6.1" 13 | repository: "https://sustainable-computing-io.github.io/kepler-helm-chart" 14 | condition: kepler.enabled 15 | sources: 16 | - https://github.com/sustainable-computing-io/kepler 17 | maintainers: 18 | - name: eumel8 19 | email: f.kloeker@telekom.de 20 | url: https://www.telekom.com 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mtr.devops.telekom.de/mcsps/python:3.12-slim 2 | LABEL org.opencontainers.image.authors="caas-request@telekom.de" 3 | LABEL version="1.0.1" 4 | LABEL description="Python Flask Entsoe App" 5 | 6 | ENV DEBIAN_FRONTEND=noninteractive 7 | RUN apt-get update && apt-get -y upgrade 8 | RUN apt-get install -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew vim-tiny python3-venv python3-dev net-tools libssl-dev curl libcurl4-openssl-dev gcc 9 | 10 | COPY flask/app.py /home/appuser/app.py 11 | COPY flask/wsgi.py /home/appuser/wsgi.py 12 | COPY requirements.txt /tmp/requirements.txt 13 | 14 | RUN pip install -r /tmp/requirements.txt 15 | RUN useradd --create-home appuser 16 | WORKDIR /home/appuser 17 | USER appuser 18 | ENV PYTHONUNBUFFERED=0 19 | ENV WEBHOOKPORT=9091 20 | ENTRYPOINT gunicorn --bind 0.0.0.0:${WEBHOOKPORT} --access-logfile /dev/stdout wsgi:app 21 | -------------------------------------------------------------------------------- /chart/templates/entsoe-servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.entsoe.enabled }} 2 | {{- if and .Values.entsoe.serviceMonitor.enabled (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} 3 | --- 4 | apiVersion: monitoring.coreos.com/v1 5 | kind: ServiceMonitor 6 | metadata: 7 | labels: 8 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 9 | {{- if .Values.rancher.enabled }} 10 | release: rancher-monitoring 11 | {{- end }} 12 | name: entsoe-{{ include "caas-carbon-footprint.fullname" . }} 13 | spec: 14 | endpoints: 15 | - interval: {{ .Values.entsoe.serviceMonitor.interval }} 16 | path: /metrics 17 | port: http 18 | scheme: http 19 | relabelings: 20 | - action: replace 21 | replacement: caasglobal 22 | sourceLabels: 23 | - container 24 | targetLabel: namespace 25 | jobLabel: app.kubernetes.io/name 26 | selector: 27 | matchLabels: 28 | app.kubernetes.io/component: entsoe 29 | {{- include "caas-carbon-footprint.selectorLabels" . | nindent 6 }} 30 | {{ end }} 31 | {{ end }} 32 | -------------------------------------------------------------------------------- /.github/workflows/helm.yaml: -------------------------------------------------------------------------------- 1 | name: Build Chart 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'chart/' 7 | branches: 8 | - main 9 | tags: 10 | - '*' 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout Repo 17 | uses: actions/checkout@v2 18 | - name: Install Cosign 19 | uses: sigstore/cosign-installer@main 20 | with: 21 | cosign-release: 'v2.2.0' 22 | - name: Helm lint & package & push 23 | run: | 24 | cd chart 25 | helm repo add kepler https://sustainable-computing-io.github.io/kepler-helm-chart 26 | helm registry login ${GHR} -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} 27 | helm registry login ${MTR} -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} 28 | helm dependency build 29 | helm lint . 30 | helm package . 31 | helm push $(ls *.tgz| head -1) oci://${GHR}/${{ github.repository_owner }}/charts 32 | helm push $(ls *.tgz| head -1) oci://${MTR}/${ORG}/charts 33 | env: 34 | DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} 35 | DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}} 36 | GHR: ghcr.io 37 | MTR: mtr.devops.telekom.de 38 | ORG: caas 39 | -------------------------------------------------------------------------------- /chart/templates/entsoe-networkpolicy.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.entsoe.enabled }} 2 | apiVersion: networking.k8s.io/v1 3 | kind: NetworkPolicy 4 | metadata: 5 | name: entsoe-monitor-{{ include "caas-carbon-footprint.fullname" . }} 6 | labels: 7 | app.kubernetes.io/component: entsoe-monitor 8 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 9 | spec: 10 | egress: 11 | - {} 12 | ingress: 13 | - ports: 14 | - port: 80 15 | protocol: TCP 16 | - port: 9091 17 | protocol: TCP 18 | podSelector: 19 | matchLabels: 20 | {{- include "caas-carbon-footprint.selectorLabels" . | nindent 6 }} 21 | policyTypes: 22 | - Ingress 23 | - Egress 24 | {{ if .Values.entsoe.proxy.enabled }} 25 | --- 26 | apiVersion: networking.k8s.io/v1 27 | kind: NetworkPolicy 28 | metadata: 29 | name: entsoe-proxy-{{ include "caas-carbon-footprint.fullname" . }} 30 | labels: 31 | app.kubernetes.io/component: entsoe-proxy 32 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 33 | spec: 34 | egress: 35 | - ports: 36 | - port: {{ .Values.entsoe.proxy.port }} 37 | protocol: TCP 38 | to: 39 | - ipBlock: 40 | cidr: {{ .Values.entsoe.proxy.host }}/32 41 | podSelector: 42 | matchLabels: 43 | {{- include "caas-carbon-footprint.selectorLabels" . | nindent 6 }} 44 | policyTypes: 45 | - Egress 46 | {{ end }} 47 | {{ end }} 48 | -------------------------------------------------------------------------------- /examples/hpa/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: demoapp 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: demoapp 10 | replicas: 1 11 | template: 12 | metadata: 13 | labels: 14 | app: demoapp 15 | spec: 16 | containers: 17 | - args: 18 | - --vm 19 | - "1" 20 | - --vm-bytes 21 | - 256M 22 | - -c 23 | - "2" 24 | - --vm-hang 25 | - "1" 26 | command: 27 | - stress 28 | name: demoapp 29 | image: mtr.devops.telekom.de/caas/stress:latest 30 | resources: 31 | requests: 32 | cpu: 1000m 33 | memory: 256Mi 34 | limits: 35 | cpu: 1000m 36 | memory: 256Mi 37 | securityContext: 38 | allowPrivilegeEscalation: false 39 | capabilities: 40 | drop: 41 | - ALL 42 | privileged: false 43 | readOnlyRootFilesystem: true 44 | runAsUser: 1000 45 | runAsGroup: 1000 46 | stdin: true 47 | terminationMessagePath: /dev/termination-log 48 | terminationMessagePolicy: File 49 | restartPolicy: Always 50 | securityContext: 51 | fsGroup: 1000 52 | supplementalGroups: 53 | - 1000 54 | terminationGracePeriodSeconds: 1 55 | -------------------------------------------------------------------------------- /examples/resources/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: demoapp 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: demoapp 10 | replicas: 1 11 | template: 12 | metadata: 13 | labels: 14 | app: demoapp 15 | spec: 16 | containers: 17 | - args: 18 | - --vm 19 | - "1" 20 | - --vm-bytes 21 | - 128M 22 | - -c 23 | - "1" 24 | - --vm-hang 25 | - "1" 26 | command: 27 | - stress 28 | name: demoapp 29 | image: mtr.devops.telekom.de/caas/stress:latest 30 | resources: 31 | requests: 32 | cpu: 1000m 33 | memory: 256Mi 34 | limits: 35 | cpu: 1000m 36 | memory: 256Mi 37 | securityContext: 38 | allowPrivilegeEscalation: false 39 | capabilities: 40 | drop: 41 | - ALL 42 | privileged: false 43 | readOnlyRootFilesystem: true 44 | runAsUser: 1000 45 | runAsGroup: 1000 46 | stdin: true 47 | terminationMessagePath: /dev/termination-log 48 | terminationMessagePolicy: File 49 | restartPolicy: Always 50 | securityContext: 51 | fsGroup: 1000 52 | supplementalGroups: 53 | - 1000 54 | terminationGracePeriodSeconds: 1 55 | -------------------------------------------------------------------------------- /examples/keda-prometheus/prometheus-scale.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keda.sh/v1alpha1 2 | kind: ScaledObject 3 | metadata: 4 | name: carbon-keda-scaledobject 5 | spec: 6 | scaleTargetRef: 7 | apiVersion: apps/v1 8 | kind: Deployment 9 | name: demoapp 10 | pollingInterval: 10 # Optional. Default: 30 seconds 11 | cooldownPeriod: 300 # Optional. Default: 300 seconds 12 | minReplicaCount: 1 # Optional. Default: 0 13 | maxReplicaCount: 4 # Optional. Default: 100 14 | fallback: # Optional. Section to specify fallback options 15 | failureThreshold: 3 # Mandatory if fallback section is included 16 | replicas: 1 17 | advanced: # Optional. Section to specify advanced options 18 | horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options 19 | behavior: # Optional. Use to modify HPA's scaling behavior 20 | scaleDown: 21 | stabilizationWindowSeconds: 150 22 | policies: 23 | - type: Percent 24 | value: 100 25 | periodSeconds: 15 26 | triggers: 27 | - type: prometheus 28 | metadata: 29 | serverAddress: http://carbon-prometheus-server.carbon 30 | metricName: entsoe_generation_eco 31 | query: entsoe_generation_eco{job="entsoe-carbon-footprint"}*100 32 | threshold: '65' 33 | 34 | 35 | -------------------------------------------------------------------------------- /chart/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "caas-carbon-footprint.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "caas-carbon-footprint.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "caas-carbon-footprint.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "caas-carbon-footprint.labels" -}} 37 | helm.sh/chart: {{ include "caas-carbon-footprint.chart" . }} 38 | {{ include "caas-carbon-footprint.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "caas-carbon-footprint.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "caas-carbon-footprint.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build Image 2 | on: 3 | push: 4 | branches: 5 | - main 6 | tags: 7 | - '*' 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | - name: Docker meta 15 | id: meta 16 | uses: docker/metadata-action@v5 17 | with: 18 | images: | 19 | mtr.devops.telekom.de/caas/entsoe 20 | ghcr.io/caas-team/entsoe 21 | tags: | 22 | type=ref,event=tag 23 | type=ref,event=branch 24 | type=ref,event=pr 25 | type=raw,value=latest 26 | - name: Install Cosign 27 | uses: sigstore/cosign-installer@main 28 | with: 29 | cosign-release: 'v2.2.0' 30 | - name: Set up QEMU 31 | uses: docker/setup-qemu-action@v3 32 | - name: Set up Docker Buildx 33 | uses: docker/setup-buildx-action@v3 34 | - name: Login to MTR 35 | uses: docker/login-action@v3 36 | with: 37 | registry: mtr.devops.telekom.de 38 | username: ${{ secrets.DOCKER_USERNAME }} 39 | password: ${{ secrets.DOCKER_PASSWORD }} 40 | - name: Login to GitHub Container Registry 41 | uses: docker/login-action@v3 42 | with: 43 | registry: ghcr.io 44 | username: ${{ github.repository_owner }} 45 | password: ${{ secrets.GITHUB_TOKEN }} 46 | - name: Build and push 47 | uses: docker/build-push-action@v5 48 | id: build-push 49 | with: 50 | context: . 51 | platforms: linux/amd64,linux/arm64 52 | push: true 53 | tags: | 54 | mtr.devops.telekom.de/caas/entsoe:latest 55 | ghcr.io/caas-team/entsoe:latest 56 | ${{ steps.meta.outputs.tags }} 57 | - name: Sign Push 58 | run: | 59 | cosign sign --key env://COSIGN_KEY --tlog-upload=false ghcr.io/caas-team/entsoe@${{ steps.build-push.outputs.digest }} 60 | cosign sign --key env://COSIGN_KEY --tlog-upload=false mtr.devops.telekom.de/caas/entsoe@${{ steps.build-push.outputs.digest }} 61 | env: 62 | COSIGN_KEY: ${{secrets.COSIGN_KEY}} 63 | -------------------------------------------------------------------------------- /chart/templates/entsoe-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.entsoe.enabled }} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | labels: 6 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 7 | name: entsoe-{{ include "caas-carbon-footprint.fullname" . }} 8 | spec: 9 | progressDeadlineSeconds: 600 10 | replicas: 1 11 | revisionHistoryLimit: 10 12 | selector: 13 | matchLabels: 14 | {{- include "caas-carbon-footprint.selectorLabels" . | nindent 6 }} 15 | strategy: 16 | rollingUpdate: 17 | maxSurge: 25% 18 | maxUnavailable: 25% 19 | type: RollingUpdate 20 | template: 21 | metadata: 22 | labels: 23 | {{- include "caas-carbon-footprint.selectorLabels" . | nindent 8 }} 24 | spec: 25 | containers: 26 | - image: "{{ .Values.entsoe.image.repository }}:{{ .Values.entsoe.image.tag }}" 27 | imagePullPolicy: {{ .Values.entsoe.image.pullPolicy }} 28 | name: entsoe 29 | ports: 30 | - containerPort: 9091 31 | env: 32 | - name: entsoe_api_key 33 | valueFrom: 34 | secretKeyRef: 35 | name: entsoe-{{ include "caas-carbon-footprint.fullname" . }} 36 | key: entsoe_api_key 37 | - name: PYTHONUNBUFFERED 38 | value: "1" 39 | - name: entsoe_end 40 | value: "{{ .Values.entsoe.end }}" 41 | - name: entsoe_start 42 | value: "{{ .Values.entsoe.start }}" 43 | {{- if .Values.entsoe.proxy.enabled }} 44 | - name: https_proxy 45 | value: "{{ .Values.entsoe.proxy.protocol }}://{{ .Values.entsoe.proxy.host }}:{{ .Values.entsoe.proxy.port }}" 46 | {{- end }} 47 | resources: 48 | {{- toYaml .Values.entsoe.resources | nindent 12 }} 49 | securityContext: 50 | {{- toYaml .Values.entsoe.securityContext | nindent 12 }} 51 | terminationMessagePath: /dev/termination-log 52 | terminationMessagePolicy: File 53 | volumeMounts: 54 | - name: tmp 55 | mountPath: /tmp 56 | dnsPolicy: ClusterFirst 57 | restartPolicy: Always 58 | schedulerName: default-scheduler 59 | securityContext: 60 | {{- toYaml .Values.entsoe.podSecurityContext | nindent 8 }} 61 | terminationGracePeriodSeconds: 3 62 | volumes: 63 | - name: tmp 64 | emptyDir: 65 | medium: Memory 66 | {{ end }} 67 | -------------------------------------------------------------------------------- /chart/values.yaml: -------------------------------------------------------------------------------- 1 | # Install Kepler Exporter from Kepler Chart 2 | kepler: 3 | enabled: true 4 | # dashboard setting remark: https://www.eia.gov/tools/faqs/faq.php?id=74&t=11 5 | #global: 6 | # namespace: cattle-monitoring-system 7 | selectorLabels: 8 | app.kubernetes.io/name: caas-carbon-footprint 9 | image: 10 | repository: mtr.devops.telekom.de/caas/kepler 11 | pullPolicy: Always 12 | tag: release-0.9 13 | resources: 14 | limits: 15 | cpu: 800m 16 | memory: 1024Mi 17 | requests: 18 | cpu: 200m 19 | memory: 128Mi 20 | rbac: 21 | create: true 22 | serviceAccount: 23 | create: true 24 | # name: 25 | serviceMonitor: 26 | enabled: false 27 | 28 | # Add PolicyException if Kyverno is installed 29 | kyverno: 30 | enabled: false 31 | # addexception as well for the nodes clusterrole 32 | clusterRole: false 33 | # target namespace to apply the PolicyException if this is not release namespace 34 | # namespace: kyverno-policies 35 | 36 | # Install Entsoe Exporter 37 | entsoe: 38 | enabled: true 39 | # apply for token here: https://transparency.entsoe.eu/content/static_content/download?path=/Static%20content/API-Token-Management.pdf 40 | #entsoe_api_key: 41 | image: 42 | repository: mtr.devops.telekom.de/caas/entsoe 43 | tag: 1.0.0 44 | pullPolicy: Always 45 | podSecurityContext: 46 | fsGroup: 1000 47 | supplementalGroups: 48 | - 1000 49 | # proxy settings for outside API requests to https://web-api.tp.entsoe.eu:443 50 | proxy: 51 | enabled: false 52 | #host: 10.0.0.1 53 | #port: 3128 54 | #protocol: http 55 | resources: 56 | limits: 57 | cpu: 200m 58 | memory: 256Mi 59 | requests: 60 | cpu: 100m 61 | memory: 128Mi 62 | securityContext: 63 | allowPrivilegeEscalation: false 64 | capabilities: 65 | drop: 66 | - ALL 67 | privileged: false 68 | readOnlyRootFilesystem: true 69 | runAsNonRoot: true 70 | runAsUser: 1000 71 | runAsGroup: 1000 72 | # beware of the API request limit 73 | # sec. 1.8 https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html 74 | serviceMonitor: 75 | enabled: false 76 | interval: 10m 77 | # hours back when entsoe metrics should collected 78 | # note: sometimes no real time data for Germany, must be at least one day back 79 | start: 1 80 | end: 0 81 | # install app in Rancher environment 82 | # this will user Rancher defined namespaces and labels 83 | rancher: 84 | enabled: false 85 | cattleDashboards: false 86 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # examples 2 | 3 | Some show cased howto operate workload based on carbon emission. 4 | 5 | Precondition: A installed [Prometheus Stack with Entsoe Exporter](https://github.com/eumel8/carbon-footprint) to provide the current carbon footprint of power generation. 6 | 7 | ## Update resourcequotas per Cron 8 | 9 | In [this cronjob](quota/carbon-cronjob.yaml) a Prometheus API will ask for current carbon state of power generation. 10 | On this decision `resourcequotas` for the target namespace will adjusted. 11 | 12 | Works technically but has no effects on running workload or the workload won't start if the quota is reached 13 | 14 | ## Modify cgroups/cpu.max in Pod 15 | 16 | Resourcequotas are realized by cgroup settings in Kubelet and the underlying [Cgroup Driver](https://kubernetes.io/docs/concepts/architecture/cgroups/), which manifests by the underlying Container Runtime Interface(CRI). Usually, and without HostPath this resources are only read-only in the Pod and can't be modified. [Alibaba Cloud](https://www.alibabacloud.com/help/en/ack/ack-managed-and-ack-dedicated/user-guide/dynamically-modify-the-resource-parameters-of-a-pod) has a cgroup controller running, so the user can do this and act as in the example above 17 | 18 | ## In-Place update Pod resources 19 | 20 | In Kubernetes 1.27 this [Kep](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/1287-in-place-update-pod-resources/kep.yaml) was realized, which makes the resouces in containers.spec writable. 21 | 22 | Requires, like K3S start flag: 23 | 24 | ```bash 25 | ... 26 | --kube-apiserver-arg feature-gates="InPlacePodVerticalScaling=true" \ 27 | --kube-controller-arg feature-gates="InPlacePodVerticalScaling=true" \ 28 | --kubelet-arg feature-gates="InPlacePodVerticalScaling=true" \ 29 | ``` 30 | 31 | Then you can use the carbon-cronjob.yaml and make a patch based on the current carbon emission: 32 | 33 | ```bash 34 | kubectl -n carbon patch pod pod-demo --patch '{"spec":{"containers":[{"name":"pod-demo", "resources":{"requests":{"cpu":"550m"}}}]}}' 35 | pod/pod-demo patched 36 | ``` 37 | 38 | ## Deployment Resources 39 | 40 | see [./resources/](resources) 41 | 42 | Patch deployment and adjust cpu resources based on eco power generation 43 | 44 | ## Horizontal Pod Autoscaler (HPA) 45 | 46 | see [./hpa/](hpa) 47 | 48 | Patch hpa and adjust replicas based on eco power generation 49 | 50 | ## Keda Prometheus 51 | 52 | see [./keda-prometheus/](keda-prometheus) 53 | 54 | Use ScaledObject from [https://keda.io](Keda) to fetch Prometheus metrics of carbon emission and act on workload deployment 55 | -------------------------------------------------------------------------------- /chart/templates/policyexception.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.kyverno.enabled }} 2 | apiVersion: kyverno.io/v2 3 | kind: PolicyException 4 | metadata: 5 | annotations: 6 | "helm.sh/hook": pre-install 7 | name: kepler-{{ include "caas-carbon-footprint.fullname" . }} 8 | labels: 9 | app.kubernetes.io/component: kepler 10 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 11 | {{- if .Values.kyverno.namespace }} 12 | namespace: {{ .Values.kyverno.namespace }} 13 | {{- end }} 14 | spec: 15 | exceptions: 16 | - policyName: disallow-host-namespaces 17 | ruleNames: 18 | - autogen-host-namespaces 19 | - host-namespaces 20 | - policyName: disallow-host-path 21 | ruleNames: 22 | - autogen-host-path 23 | - host-path 24 | - policyName: disallow-host-ports 25 | ruleNames: 26 | - autogen-host-ports-none 27 | - host-ports-none 28 | - policyName: disallow-privilege-escalation 29 | ruleNames: 30 | - autogen-privilege-escalation 31 | - privilege-escalation 32 | - policyName: disallow-privileged-containers 33 | ruleNames: 34 | - autogen-privileged-containers 35 | - privileged-containers 36 | - policyName: drop-all-capabilities 37 | ruleNames: 38 | - autogen-require-drop-all 39 | - autogen-validate-readOnlyRootFilesystem 40 | - require-drop-all 41 | - validate-readOnlyRootFilesystem 42 | - policyName: require-run-as-nonroot 43 | ruleNames: 44 | - autogen-run-as-non-root 45 | - run-as-non-root 46 | - policyName: restrict-controlplane-scheduling 47 | ruleNames: 48 | - autogen-restrict-controlplane-scheduling-control-plane 49 | - restrict-controlplane-scheduling-control-plane 50 | - policyName: require-ro-rootfs 51 | ruleNames: 52 | - autogen-validate-readOnlyRootFilesystem 53 | - validate-readOnlyRootFilesystem 54 | match: 55 | any: 56 | - resources: 57 | kinds: 58 | - Pod 59 | - DaemonSet 60 | names: 61 | - {{ .Release.Name }}-kepler 62 | - entsoe-{{ .Release.Name }}-caas-carbon-footprint* 63 | namespaces: 64 | - {{ .Release.Namespace }} 65 | {{- end }} 66 | {{ if .Values.kyverno.clusterRole }} 67 | --- 68 | apiVersion: kyverno.io/v2 69 | kind: PolicyException 70 | metadata: 71 | name: kepler-{{ include "caas-carbon-footprint.fullname" . }}-clusterrole 72 | labels: 73 | app.kubernetes.io/component: kepler 74 | {{- include "caas-carbon-footprint.labels" . | nindent 4 }} 75 | {{- if .Values.kyverno.namespace }} 76 | namespace: {{ .Values.kyverno.namespace }} 77 | {{- end }} 78 | spec: 79 | exceptions: 80 | - policyName: restrict-clusterrole-nodesproxy 81 | ruleNames: 82 | - clusterrole-nodesproxy 83 | match: 84 | any: 85 | - clusterRoles: 86 | - {{ .Release.Name }}-kepler-clusterrole 87 | {{- end }} 88 | -------------------------------------------------------------------------------- /examples/hpa/carbon-cronjob.yaml: -------------------------------------------------------------------------------- 1 | # This cronjob queries an existing Prometheus for `entsoe_generation_co2` 2 | # and makes decission how many resourcequotas are allowed for the workload in the running namespace. 3 | --- 4 | apiVersion: v1 5 | kind: ServiceAccount 6 | metadata: 7 | labels: 8 | app: carbon-cronjob 9 | name: carbon-cronjob 10 | --- 11 | kind: Role 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | metadata: 14 | labels: 15 | app: carbon-cronjob 16 | name: carbon-cronjob 17 | rules: 18 | - apiGroups: 19 | - "autoscaling" 20 | resources: 21 | - horizontalpodautoscalers 22 | verbs: 23 | - create 24 | - get 25 | - list 26 | - watch 27 | - patch 28 | - update 29 | --- 30 | apiVersion: rbac.authorization.k8s.io/v1 31 | kind: RoleBinding 32 | metadata: 33 | labels: 34 | app: carbon-cronjob 35 | name: carbon-cronjob 36 | roleRef: 37 | apiGroup: rbac.authorization.k8s.io 38 | kind: Role 39 | name: carbon-cronjob 40 | subjects: 41 | - kind: ServiceAccount 42 | name: carbon-cronjob 43 | --- 44 | apiVersion: v1 45 | data: 46 | run.sh: | 47 | #!/bin/bash 48 | # set 3 carbon emission limits to operate resource quotas 49 | highlimit=80 50 | middlelimit=50 51 | smalllimit=40 52 | quota=10 53 | # get the current carbon emission from entsoe 54 | carbon=$(curl -s http://carbon-prometheus-server:80/api/v1/query?query=entsoe_generation_eco | jq -r '.data.result[]|select(.metric.job=="entsoe-carbon-footprint")|.value[-1]') 55 | if [ "${#carbon}" -lt 1 ]; then 56 | echo "no carbon emission data at this time" 57 | exit 58 | fi 59 | # unit is g/s, multiplicate and round because bash can't handle floating numbers 60 | carbon=$(printf "%.0f\n" $( bc -l <<<"100*$carbon" )) 61 | echo "carbon factor is "$carbon" , operate the deployment now" 62 | # set the cpu resource limit based on the current carbon emission factor 63 | if [[ $carbon -gt $highlimit ]]; then 64 | kubectl patch hpa demoapp --patch '{"spec":{"maxReplicas":4}}' 65 | elif [[ $carbon -gt $middlelimit ]] && [[ $carbon -lt $highlimit ]]; then 66 | kubectl patch hpa demoapp --patch '{"spec":{"maxReplicas":3}}' 67 | elif [[ $carbon -lt $middlelimit ]] && [[ $carbon -gt $smalllimit ]]; then 68 | kubectl patch hpa demoapp --patch '{"spec":{"maxReplicas":2}}' 69 | elif [[ $carbon -lt $smalllimit ]] && [[ $carbon -gt 0 ]]; then 70 | kubectl patch hpa demoapp --patch '{"spec":{"maxReplicas":1}}' 71 | fi 72 | 73 | kind: ConfigMap 74 | metadata: 75 | labels: 76 | app: carbon-cronjob 77 | name: carbon-cronjob 78 | --- 79 | apiVersion: batch/v1 80 | kind: CronJob 81 | metadata: 82 | labels: 83 | job-name: carbon-cronjob 84 | name: carbon-cronjob 85 | spec: 86 | concurrencyPolicy: Forbid 87 | failedJobsHistoryLimit: 1 88 | successfulJobsHistoryLimit: 1 89 | suspend: false 90 | schedule: "*/1 * * * *" 91 | jobTemplate: 92 | spec: 93 | template: 94 | spec: 95 | restartPolicy: Never 96 | containers: 97 | - image: mtr.devops.telekom.de/caas/k8s-tools:latest 98 | imagePullPolicy: Always 99 | name: carbon-cronjob 100 | command: ["sh","-c"] 101 | args: ["/sidecar/run.sh"] 102 | resources: 103 | limits: 104 | cpu: 400m 105 | memory: 512Mi 106 | requests: 107 | cpu: 100m 108 | memory: 128Mi 109 | securityContext: 110 | allowPrivilegeEscalation: false 111 | capabilities: 112 | drop: 113 | - ALL 114 | privileged: false 115 | readOnlyRootFilesystem: true 116 | runAsUser: 1000 117 | runAsGroup: 1000 118 | volumeMounts: 119 | - name: carbon-cronjob 120 | mountPath: /sidecar 121 | securityContext: 122 | fsGroup: 1000 123 | supplementalGroups: 124 | - 1000 125 | serviceAccountName: carbon-cronjob 126 | volumes: 127 | - name: carbon-cronjob 128 | configMap: 129 | defaultMode: 0755 130 | name: carbon-cronjob 131 | -------------------------------------------------------------------------------- /examples/quota/carbon-cronjob.yaml: -------------------------------------------------------------------------------- 1 | # This cronjob queries an existing Prometheus for `entsoe_generation_co2` 2 | # and makes decission how many resourcequotas are allowed for the workload in the running namespace. 3 | --- 4 | apiVersion: v1 5 | kind: ServiceAccount 6 | metadata: 7 | labels: 8 | app: carbon-cronjob 9 | name: carbon-cronjob 10 | --- 11 | kind: Role 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | metadata: 14 | labels: 15 | app: carbon-cronjob 16 | name: carbon-cronjob 17 | rules: 18 | - apiGroups: 19 | - "" 20 | resources: 21 | - resourcequotas 22 | verbs: 23 | - create 24 | - get 25 | - list 26 | - watch 27 | - patch 28 | - update 29 | --- 30 | apiVersion: rbac.authorization.k8s.io/v1 31 | kind: RoleBinding 32 | metadata: 33 | labels: 34 | app: carbon-cronjob 35 | name: carbon-cronjob 36 | roleRef: 37 | apiGroup: rbac.authorization.k8s.io 38 | kind: Role 39 | name: carbon-cronjob 40 | subjects: 41 | - kind: ServiceAccount 42 | name: carbon-cronjob 43 | --- 44 | apiVersion: v1 45 | data: 46 | run.sh: | 47 | #!/bin/bash 48 | # set 3 carbon emission limits to operate resource quotas 49 | highlimit=80 50 | middlelimit=50 51 | smalllimit=40 52 | quota=10 53 | # get the current carbon emission from entsoe 54 | carbon=$(curl -s http://project-monitoring-prometheus.cattle-monitoring-system:9090/api/v1/query?query=entsoe_generation_co2 | jq -r '.data.result[]|select(.metric.job=="caas-carbon-footprint")|.value[-1]') 55 | if [ "${#carbon}" -lt 1 ]; then 56 | echo "no carbon emission data at this time" 57 | exit 58 | fi 59 | # unit is g/s, multiplicate and round because bash can't handle floating numbers 60 | carbon=$(printf "%.0f\n" $( bc -l <<<"10000*$carbon" )) 61 | echo "carbon factor is "$carbon" , operate the quota now" 62 | # set the cpu resource limit based on the current carbon emission factor 63 | if [[ $carbon -gt $highlimit ]]; then 64 | quota=10 65 | elif [[ $carbon -gt $middlelimit ]] && [[ $carbon -lt $highlimit ]]; then 66 | quota=1 67 | elif [[ $carbon -lt $middlelimit ]] && [[ $carbon -gt $smalllimit ]]; then 68 | quota=500m 69 | elif [[ $carbon -lt $smalllimit ]] && [[ $carbon -gt 0 ]]; then 70 | quota=100m 71 | fi 72 | cat </tmp/pf.log 2>&1 & 99 | 100 | # Wait until the port-forward is up 101 | for i in {1..20}; do 102 | sleep 1 103 | curl -sf http://localhost:8080 && break || true 104 | done 105 | 106 | # test output 107 | #curl -v http://localhost:8080/metrics 108 | #kubectl logs -l app.kubernetes.io/name=caas-carbon-footprint -n caas --tail=200 || true 109 | 110 | OUTPUT=$(curl -s http://localhost:8080/metrics) 111 | echo "Output: $OUTPUT" 112 | 113 | if [[ "$OUTPUT" != *"$EXPECTED"* ]]; then 114 | echo "❌ Expected output not found!" 115 | exit 1 116 | fi 117 | 118 | echo "✔ Output validated successfully" 119 | 120 | # ------------------------------------------------------- 121 | # Debug info on failure 122 | # ------------------------------------------------------- 123 | - name: Dump logs on failure 124 | if: failure() 125 | run: | 126 | kubectl get all -A 127 | kubectl describe pods -A 128 | kubectl logs -l app.kubernetes.io/name=caas-carbon-footprint -n caas --tail=200 || true 129 | 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CaaS Carbon Footprint 2 | 3 | This repository contains stuff related [Sustainable Computing](https://sustainable-computing.io/). 4 | 5 | ## Abstract 6 | 7 | Climate change is an omnipresent issue. We are confronted with this in the news every day. The state should do something, or someone, preferably someone else. In addition to all the pollution from cars, planes, ships, the largest producers of carbon dioxide are: data centers. The Internet has had an indescribable career over the last 30 years. If you look at the traffic density at the German internet node De-Cix, there is an all-time high almost every day. 8 | 9 | 10 | 11 | (C) https://www.cloudexpoeurope.de/news/de-cix-thomas-king 12 | 13 | And this will increase significantly due to all the computing needs of AI/AI. 14 | 15 | Saving computing power is not only necessary for cost reasons, but also for climate protection reasons. 16 | 17 | ## The project 18 | 19 | Measuring the power consumption of electrical devices is relatively easy if you simply connect a measuring device between the socket and the consumer. In physical computers we have the [ACPI service](https://de.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface). More complicated in goes on Virtual Machines and our target service at CaaS: Container and Kubernetes. 20 | For a long time a lot of science and research was required to become results of Virtual Machine Power Measurements. 21 | 22 | Luckily enough the CNCF taking care of it and invented [Kepler - Kubernetes Efficient Power Level Exporter](https://sustainable-computing.io/). Initial inspired to start of CaaS Carbon Footprint was the talk "Using Green Metrics to Monitor your Carbon Footprint by Ida Fürjesová & Niki Manoledaki at the PromCon 2023 in Berlin. You can watch the session on [Youtube Prometheus Channel](https://www.youtube.com/live/pKYhMTJgJUU?si=V1ILM6_cPRAaVxJ6&t=18972) 23 | 24 | Project goal is to create awareness to our customer for environmental pollution caused by computing power. First we make environmental pollution visible with power consumption per workload on our Kubernetes cluster. Second, we show when it makes sense to produce workload in an environmentally friendly way. 25 | 26 | We imagine the following possibilities: 27 | 28 | - Shift workload in time frames when Green Energy is generated, especially batch jobs, AI train model, system upgrades 29 | - Limit workload if only energy from coal, oil and gas is produced 30 | - Use Green Energy over capacity for social computing like [Folding at Home](https://github.com/eumel8/k8s-supporting-folding-at-home) 31 | 32 | For sure, we work in the Enterprise Business, most of our hosted application must run all the time. But you can start in small steps to support environmental protection. Not all goals can reach on the first day. 33 | 34 | ## Kepler 35 | 36 | [Kepler](https://github.com/sustainable-computing-io/kepler) (Kubernetes-based Efficient Power Level Exporter) uses eBPF to probe performance counters and other system stats, use ML models to estimate workload energy consumption based on these stats, and exports them as Prometheus metrics. With Kepler Dashboard this stats are visible in Grafana: 37 | 38 | 39 | 40 | We provide a bundled [Helm Chart](chart) with the origin Kepler chart, to install on cluster level, and a ServiceMonitor which rewrites the namespace label. With that the customer can collect namespaces metrics in [CaaS Project Monitoring](https://github.com/caas-team/caas-project-monitoring) and make the metrics visible on project level. 41 | 42 | Kepler has also the option to operate with your own [model server](https://github.com/sustainable-computing-io/kepler-model-server) to train a ML model for your own infrastructre. Nevertheless this can be a lot of work on a multi-cluster environment with different backends (Cloud, VM, Bare Metal). Also the energy mix must be manually configured based on the power consumption of the underlying data center. For sure, there are marketung aspects: "Our energy consumption is always green", but that's not true. It means on days without Green Energy generation you must switch of the data center. And nobody will do this. Look at this [Blog Post](https://www.climatiq.io/blog/measure-greenhouse-gas-emissions-carbon-data-centres-cloud-computing) which compares for example the Green Energy only for the AWS data center world-wide. 43 | 44 | ## ENTSO-E 45 | 46 | [Entso-e](https://transparency.entsoe.eu/dashboard/show) provides central collection and publication of electricity generation in the EU region. It has a [Restful API](https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html) to query power generation in EU regions like Germany separated by generation type like Brown Coal, Gas, Oil, Solar, Nuclear, Wind. 47 | 48 | 49 | 50 | There is a [Python Package](https://github.com/EnergieID/entsoe-py) available to query the API. With this [Flask App](flask/app.py) the related data are collected by type and provided as Prometheus metrics. This [Dockerfile](Dockerfile) builds an image which can be used for a ServiceMonitor to pump the data to Prometheus. 51 | 52 | example output with current metrics: 53 | 54 | ``` 55 | # HELP entsoe_factor_b01 Factor CO2g/kWh Biomass 56 | # TYPE entsoe_factor_b01 gauge 57 | entsoe_factor_b01 230 58 | # HELP entsoe_factor_b02 Factor CO2g/kWh Brown Coal 59 | # TYPE entsoe_factor_b02 gauge 60 | entsoe_factor_b02 996 61 | # HELP entsoe_factor_b04 Factor CO2g/kWh Gas 62 | # TYPE entsoe_factor_b04 gauge 63 | entsoe_factor_b04 378 64 | # HELP entsoe_factor_b05 Factor CO2g/kWh Hard Coal 65 | # TYPE entsoe_factor_b05 gauge 66 | entsoe_factor_b05 880 67 | # HELP entsoe_factor_b10 Factor CO2g/kWh Hydro Pumped Storage 68 | # TYPE entsoe_factor_b10 gauge 69 | entsoe_factor_b10 23 70 | # HELP entsoe_factor_b11 Factor CO2g/kWh Hydro Run River 71 | # TYPE entsoe_factor_b11 gauge 72 | entsoe_factor_b11 23 73 | # HELP entsoe_factor_b12 Factor CO2g/kWh Hydro Water Reservoir 74 | # TYPE entsoe_factor_b12 gauge 75 | entsoe_factor_b12 23 76 | # HELP entsoe_factor_b14 Factor CO2g/kWh Nuclear 77 | # TYPE entsoe_factor_b14 gauge 78 | entsoe_factor_b14 39 79 | # HELP entsoe_factor_b16 Factor CO2g/kWh Solar 80 | # TYPE entsoe_factor_b16 gauge 81 | entsoe_factor_b16 26 82 | # HELP entsoe_factor_b17 Factor CO2g/kWh Waste 83 | # TYPE entsoe_factor_b17 gauge 84 | entsoe_factor_b17 494 85 | # HELP entsoe_factor_b18 Factor CO2g/kWh Wind Offshore 86 | # TYPE entsoe_factor_b18 gauge 87 | entsoe_factor_b18 4 88 | # HELP entsoe_factor_b19 Factor CO2g/kWh Wind Onshore 89 | # TYPE entsoe_factor_b19 gauge 90 | entsoe_factor_b19 9 91 | # HELP entsoe_generation_b01 Current generation of energy with Biomass in MW 92 | # TYPE entsoe_generation_b01 gauge 93 | entsoe_generation_b01 4515 94 | # HELP entsoe_generation_b02 Current generation of energy with Fossil Brown coal/Lignite in MW 95 | # TYPE entsoe_generation_b02 gauge 96 | entsoe_generation_b02 13202 97 | # HELP entsoe_generation_b04 Current generation of energy with Fossil Gas in MW 98 | # TYPE entsoe_generation_b04 gauge 99 | entsoe_generation_b04 7422 100 | # HELP entsoe_generation_b05 Current generation of energy with Fossil Hard coal in MW 101 | # TYPE entsoe_generation_b05 gauge 102 | entsoe_generation_b05 4485 103 | # HELP entsoe_generation_b09 Current generation of energy with Geothermal in MW 104 | # TYPE entsoe_generation_b09 gauge 105 | entsoe_generation_b09 21 106 | # HELP entsoe_generation_b10 Current generation of energy with Hydro Pumped Storage in MW 107 | # TYPE entsoe_generation_b10 gauge 108 | entsoe_generation_b10 5509 109 | # HELP entsoe_generation_b11 Current generation of energy with Hydro Run-of-river and poundage in MW 110 | # TYPE entsoe_generation_b11 gauge 111 | entsoe_generation_b11 1420 112 | # HELP entsoe_generation_b12 Current generation of energy with Hydro Water Reservoir in MW 113 | # TYPE entsoe_generation_b12 gauge 114 | entsoe_generation_b12 94 115 | # HELP entsoe_generation_b14 Current generation of energy with Nuclear in MW 116 | # TYPE entsoe_generation_b14 gauge 117 | entsoe_generation_b14 0 118 | # HELP entsoe_generation_b16 Current generation of energy with Solar in MW 119 | # TYPE entsoe_generation_b16 gauge 120 | entsoe_generation_b16 0 121 | # HELP entsoe_generation_b17 Current generation of energy with Waste in MW 122 | # TYPE entsoe_generation_b17 gauge 123 | entsoe_generation_b17 814 124 | # HELP entsoe_generation_b18 Current generation of energy with Wind Offshore in MW 125 | # TYPE entsoe_generation_b18 gauge 126 | entsoe_generation_b18 1371 127 | # HELP entsoe_generation_b19 Current generation of energy with Wind Onshore in MW 128 | # TYPE entsoe_generation_b19 gauge 129 | entsoe_generation_b19 5208 130 | # HELP entsoe_generation_sum Current generation of energy summary in MW 131 | # TYPE entsoe_generation_sum gauge 132 | entsoe_generation_sum 44061 133 | # HELP entsoe_generation_eco Current generation of eco energy summary rate 134 | # TYPE entsoe_generation_eco gauge 135 | entsoe_generation_eco 0.4301309548126461 136 | # HELP entsoe_generation_fos Current generation of fossil energy summary rate 137 | # TYPE entsoe_generation_fos gauge 138 | entsoe_generation_fos 0.5698690451873539 139 | # HELP entsoe_generation_co2 Current generation of co2 per watt per second 140 | # TYPE entsoe_generation_co2 gauge 141 | entsoe_generation_co2 0.00598829722222222 142 | ``` 143 | 144 | 145 | 146 | ## Helm Chart 147 | 148 | The [Helm Chart](./chart) caas-carbon-footprint puts all together. Beware there are options to install in Rancher environment. If not, you have to disable it. And you need an Entsoe API key (see description) 149 | 150 | ## Reference 151 | 152 | CO2 emissions factor: 153 | 154 | - https://iinas.org/app/uploads/2023/10/IINAS_2023_KEV_THG_Strom-2022_2030-2050.pdf 155 | - https://impactful.ninja/the-carbon-footprint-of-biomass-energy/ 156 | - https://www.hydropower.org/blog/carbon-emissions-from-hydropower-reservoirs-facts-and-myths 157 | - https://www.rte-france.com/en/eco2mix/co2-emissions 158 | - https://www.geothermal-energy.org/pdf/IGAstandard/WGC/2010/0209.pdf 159 | 160 | ## Use Cases 161 | 162 | In [Example folder](./examples) are use cases and ideas. 163 | 164 | 165 | ## Presentations 166 | 167 | The [Presentation folder](./presentations) is used for presentation on conferences and meetups. 168 | 169 | ## Credits 170 | 171 | Life is for sharing. If you have an issue with the code or want to improve it, feel free to open an issue or an pull request. 172 | 173 | -------------------------------------------------------------------------------- /flask/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | from os import environ 3 | from entsoe import EntsoeRawClient 4 | from datetime import datetime, date, timedelta 5 | from entsoe.mappings import lookup_area 6 | import pandas as pd 7 | import json 8 | import jq 9 | import xmltodict 10 | 11 | app = Flask(__name__) 12 | 13 | # https://github.com/EnergieID/entsoe-py 14 | entsoe_api_key = environ.get('entsoe_api_key') 15 | entsoe_start = environ.get('entsoe_start') or 25 16 | entsoe_end = environ.get('entsoe_end') or 24 17 | 18 | @app.route('/metrics', methods=['GET']) 19 | def metrics(): 20 | ####################################### 21 | # Create Entsoe client with API key 22 | ####################################### 23 | client = EntsoeRawClient(api_key=entsoe_api_key) 24 | # Compute the time window from yesterday within 1 hour 25 | today = datetime.today() 26 | TwentyFour = (today - timedelta(hours = int(entsoe_end) )) 27 | TwentyFive = (today - timedelta(hours = int(entsoe_start) )) 28 | start = pd.Timestamp(TwentyFive, tz='Europe/Berlin') 29 | end = pd.Timestamp(TwentyFour, tz='Europe/Berlin') 30 | # Relates country is Germany 31 | country_code = 'DE' 32 | 33 | ####################################### 34 | # Query all energy generation in this time window for this country 35 | ####################################### 36 | try: 37 | df_generation = client.query_generation(country_code, start=start,end=end, nett=True) 38 | data_dict = xmltodict.parse(df_generation) 39 | except: 40 | message = "No data from API" 41 | return message, 500, {'Content-Type': 'text/plain'} 42 | 43 | ####################################### 44 | # Filter Biomass 45 | # ref: https://transparency.entsoe.eu/content/static_content/Static%20content/web%20api/Guide.html#_psrtype 46 | ####################################### 47 | try: 48 | filter_b01 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B01") | .Period.Point[0].quantity') 49 | result_b01 = filter_b01.input(data_dict).first() 50 | except: 51 | result_b01=0 52 | ####################################### 53 | # Filter Fossil Brown coal/Lignite 54 | ####################################### 55 | try: 56 | filter_b02 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B02") | .Period.Point[0].quantity') 57 | result_b02 = filter_b02.input(data_dict).first() 58 | except: 59 | result_b02=0 60 | ####################################### 61 | # Filter Fossil Gas 62 | ####################################### 63 | try: 64 | filter_b04 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B04") | .Period.Point[0].quantity') 65 | result_b04 = filter_b04.input(data_dict).first() 66 | except: 67 | result_b04=0 68 | ####################################### 69 | # Filter Fossil Hard coal 70 | ####################################### 71 | try: 72 | filter_b05 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B05") | .Period.Point[0].quantity') 73 | result_b05 = filter_b05.input(data_dict).first() 74 | except: 75 | result_b05=0 76 | ####################################### 77 | # Filter Geothermal 78 | ####################################### 79 | try: 80 | filter_b09 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B09") | .Period.Point[0].quantity') 81 | result_b09 = filter_b09.input(data_dict).first() 82 | except: 83 | result_b09=0 84 | ####################################### 85 | # Filter Hydro Pumped Storage 86 | ####################################### 87 | try: 88 | filter_b10 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B10") | .Period.Point[0].quantity') 89 | result_b10 = filter_b10.input(data_dict).first() 90 | except: 91 | result_b10=0 92 | ####################################### 93 | # Filter Hydro Run-over-river and poundage 94 | ####################################### 95 | try: 96 | filter_b11 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B11") | .Period.Point[0].quantity') 97 | result_b11 = filter_b11.input(data_dict).first() 98 | except: 99 | result_b11=0 100 | ####################################### 101 | # Filter Hydro Water Reservoir 102 | ####################################### 103 | try: 104 | filter_b12 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B12") | .Period.Point[0].quantity') 105 | result_b12 = filter_b12.input(data_dict).first() 106 | except: 107 | result_b12=0 108 | ####################################### 109 | # Filter Nuclear 110 | ####################################### 111 | try: 112 | filter_b14 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B14") | .Period.Point[0].quantity') 113 | result_b14 = filter_b14.input(data_dict).first() 114 | except: 115 | result_b14=0 116 | ####################################### 117 | # Filter Solar 118 | ####################################### 119 | try: 120 | filter_b16 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B16") | .Period.Point[0].quantity') 121 | result_b16 = filter_b16.input(data_dict).first() 122 | except: 123 | result_b16=0 124 | ####################################### 125 | # Filter Waste 126 | ####################################### 127 | try: 128 | filter_b17 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B17") | .Period.Point[0].quantity') 129 | result_b17 = filter_b17.input(data_dict).first() 130 | except: 131 | result_b17=0 132 | ####################################### 133 | # Filter Wind Offshore 134 | ####################################### 135 | try: 136 | filter_b18 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B18") | .Period.Point[0].quantity') 137 | result_b18 = filter_b18.input(data_dict).first() 138 | except: 139 | result_b18=0 140 | ####################################### 141 | # Filter Wind Onshore 142 | ####################################### 143 | try: 144 | filter_b19 = jq.compile('.GL_MarketDocument.TimeSeries[] | select(.MktPSRType.psrType == "B19") | .Period.Point[0].quantity') 145 | result_b19 = filter_b19.input(data_dict).first() 146 | except: 147 | result_b19=0 148 | ####################################### 149 | # Factor CO2g/kWh 150 | ####################################### 151 | fac_b01 = 230 152 | fac_b02 = 996 153 | fac_b05 = 880 154 | fac_b04 = 378 155 | fac_b09 = 91 156 | fac_b14 = 39 157 | fac_b19 = 9 158 | fac_b18 = 4 159 | fac_b16 = 26 160 | fac_b17 = 494 161 | fac_b10 = 23 162 | fac_b11 = 23 163 | fac_b12 = 23 164 | ####################################### 165 | # Summary Energy Generation 166 | ####################################### 167 | result_sum = int(float(result_b01)) + int(float(result_b02)) + int(float(result_b04)) + int(float(result_b05)) + int(float(result_b09)) + int(float(result_b10)) + int(float(result_b11)) + int(float(result_b12)) + int(float(result_b14)) + int(float(result_b16)) + int(float(result_b17)) + int(float(result_b18)) + int(float(result_b19)) 168 | ####################################### 169 | # Bio efficience 170 | ####################################### 171 | if result_sum: 172 | result_eco = (int(float(result_b01)) + int(float(result_b09)) + int(float(result_b10)) + int(float(result_b11)) + int(float(result_b12)) + int(float(result_b16)) + int(float(result_b17)) + int(float(result_b18)) + int(float(result_b19))) / int(result_sum) 173 | else: 174 | result_eco = -1 175 | ####################################### 176 | # Fossil part 177 | ####################################### 178 | if result_sum: 179 | result_fos = (int(float(result_b02)) + int(float(result_b04)) + int(float(result_b05))) / int(result_sum) 180 | else: 181 | result_sum = -1 182 | result_fos = -1 183 | ####################################### 184 | # CO2 gramm/watt second 185 | ####################################### 186 | result_co2 = ((int(float(result_b02)) * (fac_b02 / 3600) / 1000 / 1000) + (int(float(result_b04)) * (fac_b04 / 3600) / 1000 / 1000) + (int(float(result_b05)) * (fac_b05 / 3600) / 1000 / 1000) + (int(float(result_b01)) * (fac_b01 / 3600) / 1000 / 1000) + (int(float(result_b09)) * (fac_b09/ 3600) / 1000 / 1000) + (int(float(result_b10)) * (fac_b10 / 3600) / 1000 / 1000) + (int(float(result_b11)) * (fac_b11 / 3600) / 1000 / 1000) + (int(float(result_b12)) * (fac_b12 / 3600) / 1000 / 1000) + (int(float(result_b16)) * (fac_b16 / 3600) / 1000 / 1000) + (int(float(result_b17)) * (fac_b17 / 3600) / 1000 / 1000) + (int(float(result_b18)) * (fac_b18 / 3600) / 1000 / 1000) + (int(float(result_b19)) * (fac_b19 / 3600) / 1000 / 1000)) 187 | ####################################### 188 | # Print Out Metrics 189 | ####################################### 190 | counter = "# HELP entsoe_factor_b01 Factor CO2g/kWh Biomass" + "\n" 191 | counter += "# TYPE entsoe_factor_b01 gauge" + "\n" 192 | counter += "entsoe_factor_b01 " + str(fac_b01) + "\n" 193 | counter += "# HELP entsoe_factor_b02 Factor CO2g/kWh Brown Coal" + "\n" 194 | counter += "# TYPE entsoe_factor_b02 gauge" + "\n" 195 | counter += "entsoe_factor_b02 " + str(fac_b02) + "\n" 196 | counter += "# HELP entsoe_factor_b04 Factor CO2g/kWh Gas" + "\n" 197 | counter += "# TYPE entsoe_factor_b04 gauge" + "\n" 198 | counter += "entsoe_factor_b04 " + str(fac_b04) + "\n" 199 | counter += "# HELP entsoe_factor_b05 Factor CO2g/kWh Hard Coal" + "\n" 200 | counter += "# TYPE entsoe_factor_b05 gauge" + "\n" 201 | counter += "entsoe_factor_b05 " + str(fac_b05) + "\n" 202 | counter += "# HELP entsoe_factor_b10 Factor CO2g/kWh Hydro Pumped Storage" + "\n" 203 | counter += "# TYPE entsoe_factor_b10 gauge" + "\n" 204 | counter += "entsoe_factor_b10 " + str(fac_b10) + "\n" 205 | counter += "# HELP entsoe_factor_b11 Factor CO2g/kWh Hydro Run River" + "\n" 206 | counter += "# TYPE entsoe_factor_b11 gauge" + "\n" 207 | counter += "entsoe_factor_b11 " + str(fac_b11) + "\n" 208 | counter += "# HELP entsoe_factor_b12 Factor CO2g/kWh Hydro Water Reservoir" + "\n" 209 | counter += "# TYPE entsoe_factor_b12 gauge" + "\n" 210 | counter += "entsoe_factor_b12 " + str(fac_b12) + "\n" 211 | counter += "# HELP entsoe_factor_b14 Factor CO2g/kWh Nuclear" + "\n" 212 | counter += "# TYPE entsoe_factor_b14 gauge" + "\n" 213 | counter += "entsoe_factor_b14 " + str(fac_b14) + "\n" 214 | counter += "# HELP entsoe_factor_b16 Factor CO2g/kWh Solar" + "\n" 215 | counter += "# TYPE entsoe_factor_b16 gauge" + "\n" 216 | counter += "entsoe_factor_b16 " + str(fac_b16) + "\n" 217 | counter += "# HELP entsoe_factor_b17 Factor CO2g/kWh Waste" + "\n" 218 | counter += "# TYPE entsoe_factor_b17 gauge" + "\n" 219 | counter += "entsoe_factor_b17 " + str(fac_b17) + "\n" 220 | counter += "# HELP entsoe_factor_b18 Factor CO2g/kWh Wind Offshore" + "\n" 221 | counter += "# TYPE entsoe_factor_b18 gauge" + "\n" 222 | counter += "entsoe_factor_b18 " + str(fac_b18) + "\n" 223 | counter += "# HELP entsoe_factor_b19 Factor CO2g/kWh Wind Onshore" + "\n" 224 | counter += "# TYPE entsoe_factor_b19 gauge" + "\n" 225 | counter += "entsoe_factor_b19 " + str(fac_b19) + "\n" 226 | counter += "# HELP entsoe_generation_b01 Current generation of energy with Biomass in MW" + "\n" 227 | counter += "# TYPE entsoe_generation_b01 gauge" + "\n" 228 | counter += "entsoe_generation_b01 " + str(result_b01) + "\n" 229 | counter += "# HELP entsoe_generation_b02 Current generation of energy with Fossil Brown coal/Lignite in MW" + "\n" 230 | counter += "# TYPE entsoe_generation_b02 gauge" + "\n" 231 | counter += "entsoe_generation_b02 " + str(result_b02) + "\n" 232 | counter += "# HELP entsoe_generation_b04 Current generation of energy with Fossil Gas in MW" + "\n" 233 | counter += "# TYPE entsoe_generation_b04 gauge" + "\n" 234 | counter += "entsoe_generation_b04 " + str(result_b04) + "\n" 235 | counter += "# HELP entsoe_generation_b05 Current generation of energy with Fossil Hard coal in MW" + "\n" 236 | counter += "# TYPE entsoe_generation_b05 gauge" + "\n" 237 | counter += "entsoe_generation_b05 " + str(result_b05) + "\n" 238 | counter += "# HELP entsoe_generation_b09 Current generation of energy with Geothermal in MW" + "\n" 239 | counter += "# TYPE entsoe_generation_b09 gauge" + "\n" 240 | counter += "entsoe_generation_b09 " + str(result_b09) + "\n" 241 | counter += "# HELP entsoe_generation_b10 Current generation of energy with Hydro Pumped Storage in MW" + "\n" 242 | counter += "# TYPE entsoe_generation_b10 gauge" + "\n" 243 | counter += "entsoe_generation_b10 " + str(result_b10) + "\n" 244 | counter += "# HELP entsoe_generation_b11 Current generation of energy with Hydro Run-of-river and poundage in MW" + "\n" 245 | counter += "# TYPE entsoe_generation_b11 gauge" + "\n" 246 | counter += "entsoe_generation_b11 " + str(result_b11) + "\n" 247 | counter += "# HELP entsoe_generation_b12 Current generation of energy with Hydro Water Reservoir in MW" + "\n" 248 | counter += "# TYPE entsoe_generation_b12 gauge" + "\n" 249 | counter += "entsoe_generation_b12 " + str(result_b12) + "\n" 250 | counter += "# HELP entsoe_generation_b14 Current generation of energy with Nuclear in MW" + "\n" 251 | counter += "# TYPE entsoe_generation_b14 gauge" + "\n" 252 | counter += "entsoe_generation_b14 " + str(result_b14) + "\n" 253 | counter += "# HELP entsoe_generation_b16 Current generation of energy with Solar in MW" + "\n" 254 | counter += "# TYPE entsoe_generation_b16 gauge" + "\n" 255 | counter += "entsoe_generation_b16 " + str(result_b16) + "\n" 256 | counter += "# HELP entsoe_generation_b17 Current generation of energy with Waste in MW" + "\n" 257 | counter += "# TYPE entsoe_generation_b17 gauge" + "\n" 258 | counter += "entsoe_generation_b17 " + str(result_b17) + "\n" 259 | counter += "# HELP entsoe_generation_b18 Current generation of energy with Wind Offshore in MW" + "\n" 260 | counter += "# TYPE entsoe_generation_b18 gauge" + "\n" 261 | counter += "entsoe_generation_b18 " + str(result_b18) + "\n" 262 | counter += "# HELP entsoe_generation_b19 Current generation of energy with Wind Onshore in MW" + "\n" 263 | counter += "# TYPE entsoe_generation_b19 gauge" + "\n" 264 | counter += "entsoe_generation_b19 " + str(result_b19) + "\n" 265 | counter += "# HELP entsoe_generation_sum Current generation of energy summary in MW" + "\n" 266 | counter += "# TYPE entsoe_generation_sum gauge" + "\n" 267 | counter += "entsoe_generation_sum " + str(result_sum) + "\n" 268 | counter += "# HELP entsoe_generation_eco Current generation of eco energy summary rate" + "\n" 269 | counter += "# TYPE entsoe_generation_eco gauge" + "\n" 270 | counter += "entsoe_generation_eco " + str(result_eco) + "\n" 271 | counter += "# HELP entsoe_generation_fos Current generation of fossil energy summary rate" + "\n" 272 | counter += "# TYPE entsoe_generation_fos gauge" + "\n" 273 | counter += "entsoe_generation_fos " + str(result_fos) + "\n" 274 | counter += "# HELP entsoe_generation_co2 Current generation of co2 per watt per second" + "\n" 275 | counter += "# TYPE entsoe_generation_co2 gauge" + "\n" 276 | counter += "entsoe_generation_co2 " + str(result_co2) + "\n" 277 | 278 | ####################################### 279 | #json_data = json.dumps(data_dict) 280 | #print(json_data,file=open('data.json','w')) 281 | 282 | return counter, 200, {'Content-Type': 'text/plain'} 283 | 284 | @app.errorhandler(404) 285 | def not_found_error(error): 286 | message = "Couldn't found your requested page" 287 | return message, 404, {'Content-Type': 'text/plain'} 288 | 289 | @app.errorhandler(500) 290 | def internal_error(error): 291 | message = "Something went wrong" 292 | return message, 500, {'Content-Type': 'text/plain'} 293 | 294 | if __name__ == '__main__': 295 | 296 | app.run( 297 | host = "0.0.0.0", 298 | port = 9091, 299 | debug = 0 300 | ) 301 | -------------------------------------------------------------------------------- /chart/files/kepler-dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "target": { 12 | "limit": 100, 13 | "matchAny": false, 14 | "tags": [], 15 | "type": "dashboard" 16 | }, 17 | "type": "dashboard" 18 | } 19 | ] 20 | }, 21 | "description": "Dashboard for Kepler Exporter", 22 | "editable": true, 23 | "fiscalYearStartMonth": 0, 24 | "graphTooltip": 0, 25 | "id": 2, 26 | "links": [], 27 | "liveNow": false, 28 | "panels": [ 29 | { 30 | "collapsed": false, 31 | "datasource": "prometheus", 32 | "gridPos": { 33 | "h": 1, 34 | "w": 24, 35 | "x": 0, 36 | "y": 0 37 | }, 38 | "id": 11, 39 | "panels": [], 40 | "title": "Carbon Emissions", 41 | "type": "row" 42 | }, 43 | { 44 | "datasource": { 45 | "type": "prometheus", 46 | "uid": "${datasource}" 47 | }, 48 | "description": "Using CO2 emissions by power generation type as reported by US Energy Information Administration https://www.eia.gov/tools/faqs/faq.php?id=74&t=11", 49 | "fieldConfig": { 50 | "defaults": { 51 | "color": { 52 | "mode": "thresholds" 53 | }, 54 | "mappings": [], 55 | "thresholds": { 56 | "mode": "percentage", 57 | "steps": [ 58 | { 59 | "color": "green", 60 | "value": null 61 | }, 62 | { 63 | "color": "#EAB839", 64 | "value": 60 65 | }, 66 | { 67 | "color": "red", 68 | "value": 80 69 | } 70 | ] 71 | } 72 | }, 73 | "overrides": [] 74 | }, 75 | "gridPos": { 76 | "h": 6, 77 | "w": 19, 78 | "x": 2, 79 | "y": 1 80 | }, 81 | "id": 12, 82 | "options": { 83 | "orientation": "auto", 84 | "reduceOptions": { 85 | "calcs": [ 86 | "lastNotNull" 87 | ], 88 | "fields": "", 89 | "values": false 90 | }, 91 | "showThresholdLabels": false, 92 | "showThresholdMarkers": true, 93 | "text": {} 94 | }, 95 | "pluginVersion": "9.1.0", 96 | "targets": [ 97 | { 98 | "datasource": { 99 | "type": "prometheus", 100 | "uid": "${datasource}" 101 | }, 102 | "editorMode": "code", 103 | "expr": "sum by (container_namespace)(\n (\n increase(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n ) * $watt_per_second_to_kWh * $coal\n)", 104 | "hide": false, 105 | "legendFormat": "CO2 Coal", 106 | "range": true, 107 | "refId": "A" 108 | }, 109 | { 110 | "datasource": { 111 | "type": "prometheus", 112 | "uid": "${datasource}" 113 | }, 114 | "editorMode": "code", 115 | "expr": "sum by (container_namespace)(\n (\n increase(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n ) * $watt_per_second_to_kWh * $petroleum\n)", 116 | "hide": false, 117 | "legendFormat": "CO2 Petroleum", 118 | "range": true, 119 | "refId": "B" 120 | }, 121 | { 122 | "datasource": { 123 | "type": "prometheus", 124 | "uid": "${datasource}" 125 | }, 126 | "editorMode": "code", 127 | "expr": "sum by (container_namespace)(\n (\n increase(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n ) * $watt_per_second_to_kWh * $natural_gas\n)", 128 | "hide": false, 129 | "legendFormat": "CO2 Natural Gas", 130 | "range": true, 131 | "refId": "C" 132 | } 133 | ], 134 | "title": "Carbon Footprint (pounds per kWh per day) in Namespace: $namespace (PKG+DRAM+OTHER+GPU)", 135 | "transparent": true, 136 | "type": "gauge" 137 | }, 138 | { 139 | "collapsed": false, 140 | "datasource": "prometheus", 141 | "gridPos": { 142 | "h": 1, 143 | "w": 24, 144 | "x": 0, 145 | "y": 7 146 | }, 147 | "id": 8, 148 | "panels": [], 149 | "title": "Power Consumption", 150 | "type": "row" 151 | }, 152 | { 153 | "datasource": { 154 | "type": "prometheus", 155 | "uid": "${datasource}" 156 | }, 157 | "description": "", 158 | "fieldConfig": { 159 | "defaults": { 160 | "color": { 161 | "mode": "palette-classic" 162 | }, 163 | "custom": { 164 | "axisCenteredZero": false, 165 | "axisColorMode": "text", 166 | "axisLabel": "watt", 167 | "axisPlacement": "left", 168 | "barAlignment": 0, 169 | "drawStyle": "bars", 170 | "fillOpacity": 44, 171 | "gradientMode": "opacity", 172 | "hideFrom": { 173 | "graph": false, 174 | "legend": false, 175 | "tooltip": false, 176 | "viz": false 177 | }, 178 | "lineInterpolation": "linear", 179 | "lineWidth": 0, 180 | "pointSize": 5, 181 | "scaleDistribution": { 182 | "type": "linear" 183 | }, 184 | "showPoints": "always", 185 | "spanNulls": false, 186 | "stacking": { 187 | "group": "A", 188 | "mode": "normal" 189 | }, 190 | "thresholdsStyle": { 191 | "mode": "off" 192 | } 193 | }, 194 | "mappings": [], 195 | "thresholds": { 196 | "mode": "absolute", 197 | "steps": [ 198 | { 199 | "color": "green", 200 | "value": null 201 | }, 202 | { 203 | "color": "red", 204 | "value": 80 205 | } 206 | ] 207 | } 208 | }, 209 | "overrides": [ 210 | { 211 | "matcher": { 212 | "id": "byRegexp", 213 | "options": ".*DRAM.*" 214 | }, 215 | "properties": [ 216 | { 217 | "id": "color", 218 | "value": { 219 | "fixedColor": "orange", 220 | "mode": "fixed" 221 | } 222 | } 223 | ] 224 | }, 225 | { 226 | "matcher": { 227 | "id": "byRegexp", 228 | "options": ".*OTHER.*" 229 | }, 230 | "properties": [ 231 | { 232 | "id": "color", 233 | "value": { 234 | "fixedColor": "blue", 235 | "mode": "fixed" 236 | } 237 | } 238 | ] 239 | }, 240 | { 241 | "matcher": { 242 | "id": "byRegexp", 243 | "options": ".*GPU.*" 244 | }, 245 | "properties": [ 246 | { 247 | "id": "color", 248 | "value": { 249 | "fixedColor": "semi-dark-green", 250 | "mode": "fixed" 251 | } 252 | } 253 | ] 254 | }, 255 | { 256 | "matcher": { 257 | "id": "byRegexp", 258 | "options": ".*PKG.*" 259 | }, 260 | "properties": [ 261 | { 262 | "id": "color", 263 | "value": { 264 | "fixedColor": "red", 265 | "mode": "fixed" 266 | } 267 | } 268 | ] 269 | } 270 | ] 271 | }, 272 | "gridPos": { 273 | "h": 10, 274 | "w": 24, 275 | "x": 0, 276 | "y": 8 277 | }, 278 | "id": 16, 279 | "options": { 280 | "legend": { 281 | "calcs": [ 282 | "mean" 283 | ], 284 | "displayMode": "table", 285 | "placement": "right", 286 | "showLegend": true, 287 | "sortBy": "Mean", 288 | "sortDesc": true 289 | }, 290 | "tooltip": { 291 | "mode": "single", 292 | "sort": "none" 293 | } 294 | }, 295 | "targets": [ 296 | { 297 | "datasource": "prometheus", 298 | "editorMode": "code", 299 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 300 | "hide": false, 301 | "interval": "", 302 | "legendFormat": "{{pod_name}} / {{container_namespace}} / PKG", 303 | "range": true, 304 | "refId": "A" 305 | }, 306 | { 307 | "datasource": "prometheus", 308 | "editorMode": "code", 309 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 310 | "hide": false, 311 | "interval": "", 312 | "legendFormat": "{{pod_name}} / {{container_namespace}} / DRAM", 313 | "range": true, 314 | "refId": "B" 315 | }, 316 | { 317 | "datasource": { 318 | "type": "prometheus", 319 | "uid": "${datasource}" 320 | }, 321 | "editorMode": "code", 322 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 323 | "hide": false, 324 | "interval": "", 325 | "legendFormat": "{{pod_name}} / {{container_namespace}} / OTHER", 326 | "range": true, 327 | "refId": "C" 328 | }, 329 | { 330 | "datasource": { 331 | "type": "prometheus", 332 | "uid": "${datasource}" 333 | }, 334 | "editorMode": "code", 335 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 336 | "hide": false, 337 | "legendFormat": "{{pod_name}} / {{container_namespace}} / GPU", 338 | "range": true, 339 | "refId": "D" 340 | } 341 | ], 342 | "title": "Pod/Process Power Consumption (W) in Namespace: $namespace", 343 | "type": "timeseries" 344 | }, 345 | { 346 | "datasource": { 347 | "type": "prometheus", 348 | "uid": "${datasource}" 349 | }, 350 | "description": "", 351 | "fieldConfig": { 352 | "defaults": { 353 | "color": { 354 | "mode": "palette-classic" 355 | }, 356 | "custom": { 357 | "axisCenteredZero": false, 358 | "axisColorMode": "text", 359 | "axisLabel": "watt", 360 | "axisPlacement": "left", 361 | "barAlignment": 0, 362 | "drawStyle": "bars", 363 | "fillOpacity": 44, 364 | "gradientMode": "opacity", 365 | "hideFrom": { 366 | "graph": false, 367 | "legend": false, 368 | "tooltip": false, 369 | "viz": false 370 | }, 371 | "lineInterpolation": "linear", 372 | "lineWidth": 0, 373 | "pointSize": 5, 374 | "scaleDistribution": { 375 | "type": "linear" 376 | }, 377 | "showPoints": "always", 378 | "spanNulls": false, 379 | "stacking": { 380 | "group": "A", 381 | "mode": "normal" 382 | }, 383 | "thresholdsStyle": { 384 | "mode": "off" 385 | } 386 | }, 387 | "mappings": [], 388 | "thresholds": { 389 | "mode": "absolute", 390 | "steps": [ 391 | { 392 | "color": "green", 393 | "value": null 394 | }, 395 | { 396 | "color": "red", 397 | "value": 80 398 | } 399 | ] 400 | } 401 | }, 402 | "overrides": [ 403 | { 404 | "matcher": { 405 | "id": "byRegexp", 406 | "options": ".*Package.*" 407 | }, 408 | "properties": [ 409 | { 410 | "id": "color", 411 | "value": { 412 | "fixedColor": "red", 413 | "mode": "fixed" 414 | } 415 | } 416 | ] 417 | }, 418 | { 419 | "matcher": { 420 | "id": "byRegexp", 421 | "options": ".*DRAM.*" 422 | }, 423 | "properties": [ 424 | { 425 | "id": "color", 426 | "value": { 427 | "fixedColor": "orange", 428 | "mode": "fixed" 429 | } 430 | } 431 | ] 432 | }, 433 | { 434 | "matcher": { 435 | "id": "byRegexp", 436 | "options": ".*OtherComponents.*" 437 | }, 438 | "properties": [ 439 | { 440 | "id": "color", 441 | "value": { 442 | "fixedColor": "blue", 443 | "mode": "fixed" 444 | } 445 | } 446 | ] 447 | }, 448 | { 449 | "matcher": { 450 | "id": "byRegexp", 451 | "options": ".*GPU.*" 452 | }, 453 | "properties": [ 454 | { 455 | "id": "color", 456 | "value": { 457 | "fixedColor": "semi-dark-green", 458 | "mode": "fixed" 459 | } 460 | } 461 | ] 462 | } 463 | ] 464 | }, 465 | "gridPos": { 466 | "h": 8, 467 | "w": 12, 468 | "x": 0, 469 | "y": 18 470 | }, 471 | "id": 2, 472 | "options": { 473 | "legend": { 474 | "calcs": [ 475 | "mean", 476 | "max" 477 | ], 478 | "displayMode": "table", 479 | "placement": "bottom", 480 | "showLegend": true 481 | }, 482 | "tooltip": { 483 | "mode": "single", 484 | "sort": "none" 485 | } 486 | }, 487 | "targets": [ 488 | { 489 | "datasource": { 490 | "type": "prometheus", 491 | "uid": "${datasource}" 492 | }, 493 | "editorMode": "code", 494 | "expr": "sum(irate(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 495 | "hide": false, 496 | "interval": "", 497 | "legendFormat": "PKG", 498 | "range": true, 499 | "refId": "A" 500 | }, 501 | { 502 | "datasource": { 503 | "type": "prometheus", 504 | "uid": "${datasource}" 505 | }, 506 | "editorMode": "code", 507 | "expr": "sum(irate(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 508 | "hide": false, 509 | "interval": "", 510 | "legendFormat": "DRAM", 511 | "range": true, 512 | "refId": "B" 513 | }, 514 | { 515 | "datasource": { 516 | "type": "prometheus", 517 | "uid": "${datasource}" 518 | }, 519 | "editorMode": "code", 520 | "expr": "sum(irate(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 521 | "hide": false, 522 | "legendFormat": "OTHER", 523 | "range": true, 524 | "refId": "C" 525 | }, 526 | { 527 | "datasource": { 528 | "type": "prometheus", 529 | "uid": "${datasource}" 530 | }, 531 | "editorMode": "code", 532 | "expr": "sum(irate(kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[5m]))", 533 | "hide": false, 534 | "legendFormat": " GPU", 535 | "range": true, 536 | "refId": "D" 537 | } 538 | ], 539 | "title": "Total Power Consumption (W) in Namespace: $namespace", 540 | "type": "timeseries" 541 | }, 542 | { 543 | "datasource": { 544 | "type": "prometheus", 545 | "uid": "${datasource}" 546 | }, 547 | "description": "", 548 | "fieldConfig": { 549 | "defaults": { 550 | "color": { 551 | "mode": "palette-classic" 552 | }, 553 | "custom": { 554 | "axisCenteredZero": false, 555 | "axisColorMode": "text", 556 | "axisLabel": "kWh", 557 | "axisPlacement": "left", 558 | "barAlignment": 0, 559 | "drawStyle": "bars", 560 | "fillOpacity": 44, 561 | "gradientMode": "opacity", 562 | "hideFrom": { 563 | "graph": false, 564 | "legend": false, 565 | "tooltip": false, 566 | "viz": false 567 | }, 568 | "lineInterpolation": "linear", 569 | "lineWidth": 0, 570 | "pointSize": 5, 571 | "scaleDistribution": { 572 | "type": "linear" 573 | }, 574 | "showPoints": "always", 575 | "spanNulls": false, 576 | "stacking": { 577 | "group": "A", 578 | "mode": "normal" 579 | }, 580 | "thresholdsStyle": { 581 | "mode": "off" 582 | } 583 | }, 584 | "mappings": [], 585 | "thresholds": { 586 | "mode": "absolute", 587 | "steps": [ 588 | { 589 | "color": "green", 590 | "value": null 591 | }, 592 | { 593 | "color": "red", 594 | "value": 80 595 | } 596 | ] 597 | } 598 | }, 599 | "overrides": [ 600 | { 601 | "matcher": { 602 | "id": "byRegexp", 603 | "options": ".*Package.*" 604 | }, 605 | "properties": [ 606 | { 607 | "id": "color", 608 | "value": { 609 | "fixedColor": "red", 610 | "mode": "fixed" 611 | } 612 | } 613 | ] 614 | }, 615 | { 616 | "matcher": { 617 | "id": "byRegexp", 618 | "options": ".*DRAM.*" 619 | }, 620 | "properties": [ 621 | { 622 | "id": "color", 623 | "value": { 624 | "fixedColor": "orange", 625 | "mode": "fixed" 626 | } 627 | } 628 | ] 629 | }, 630 | { 631 | "matcher": { 632 | "id": "byRegexp", 633 | "options": ".*OtherComponents.*" 634 | }, 635 | "properties": [ 636 | { 637 | "id": "color", 638 | "value": { 639 | "fixedColor": "blue", 640 | "mode": "fixed" 641 | } 642 | } 643 | ] 644 | }, 645 | { 646 | "matcher": { 647 | "id": "byRegexp", 648 | "options": ".*GPU.*" 649 | }, 650 | "properties": [ 651 | { 652 | "id": "color", 653 | "value": { 654 | "fixedColor": "semi-dark-green", 655 | "mode": "fixed" 656 | } 657 | } 658 | ] 659 | } 660 | ] 661 | }, 662 | "gridPos": { 663 | "h": 8, 664 | "w": 12, 665 | "x": 12, 666 | "y": 18 667 | }, 668 | "id": 17, 669 | "options": { 670 | "legend": { 671 | "calcs": [ 672 | "mean", 673 | "max" 674 | ], 675 | "displayMode": "table", 676 | "placement": "bottom", 677 | "showLegend": true, 678 | "sortBy": "Max", 679 | "sortDesc": true 680 | }, 681 | "tooltip": { 682 | "mode": "single", 683 | "sort": "none" 684 | } 685 | }, 686 | "targets": [ 687 | { 688 | "datasource": { 689 | "type": "prometheus", 690 | "uid": "${datasource}" 691 | }, 692 | "editorMode": "code", 693 | "expr": "sum (\n increase(\n (kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 694 | "hide": false, 695 | "interval": "", 696 | "legendFormat": "PKG (CORE+UNCORE)", 697 | "range": true, 698 | "refId": "A" 699 | }, 700 | { 701 | "datasource": { 702 | "type": "prometheus", 703 | "uid": "${datasource}" 704 | }, 705 | "editorMode": "code", 706 | "expr": "sum (\n increase(\n (kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 707 | "hide": false, 708 | "interval": "", 709 | "legendFormat": "DRAM", 710 | "range": true, 711 | "refId": "B" 712 | }, 713 | { 714 | "datasource": { 715 | "type": "prometheus", 716 | "uid": "${datasource}" 717 | }, 718 | "editorMode": "code", 719 | "expr": "sum (\n increase(\n (kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 720 | "hide": false, 721 | "legendFormat": "OTHER", 722 | "range": true, 723 | "refId": "C" 724 | }, 725 | { 726 | "datasource": { 727 | "type": "prometheus", 728 | "uid": "${datasource}" 729 | }, 730 | "editorMode": "code", 731 | "expr": "sum (\n increase(\n (kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 732 | "hide": false, 733 | "legendFormat": " GPU", 734 | "range": true, 735 | "refId": "D" 736 | } 737 | ], 738 | "title": "Total Power Consumption (kWh per day) in Namespace: $namespace", 739 | "type": "timeseries" 740 | }, 741 | { 742 | "datasource": { 743 | "type": "prometheus", 744 | "uid": "${datasource}" 745 | }, 746 | "fieldConfig": { 747 | "defaults": { 748 | "color": { 749 | "mode": "thresholds" 750 | }, 751 | "mappings": [], 752 | "thresholds": { 753 | "mode": "absolute", 754 | "steps": [ 755 | { 756 | "color": "green", 757 | "value": null 758 | }, 759 | { 760 | "color": "red", 761 | "value": 80 762 | } 763 | ] 764 | } 765 | }, 766 | "overrides": [] 767 | }, 768 | "gridPos": { 769 | "h": 7, 770 | "w": 24, 771 | "x": 0, 772 | "y": 26 773 | }, 774 | "id": 15, 775 | "options": { 776 | "displayMode": "gradient", 777 | "minVizHeight": 10, 778 | "minVizWidth": 0, 779 | "orientation": "auto", 780 | "reduceOptions": { 781 | "calcs": [ 782 | "lastNotNull" 783 | ], 784 | "fields": "", 785 | "values": false 786 | }, 787 | "showUnfilled": true 788 | }, 789 | "pluginVersion": "9.1.0", 790 | "targets": [ 791 | { 792 | "datasource": { 793 | "type": "prometheus", 794 | "uid": "${datasource}" 795 | }, 796 | "editorMode": "code", 797 | "expr": "sum by (container_namespace)(\n (\n increase(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m]) +\n increase(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\"}[24h:1m])\n ) * $watt_per_second_to_kWh\n)", 798 | "interval": "", 799 | "legendFormat": "{{container_namespace}}", 800 | "range": true, 801 | "refId": "A" 802 | } 803 | ], 804 | "title": "Total Power Consumption (PKG+DRAM+OTHER+GPU) by Namespace (kWh per day)", 805 | "type": "bargauge" 806 | } 807 | ], 808 | "refresh": "", 809 | "schemaVersion": 37, 810 | "style": "dark", 811 | "tags": [], 812 | "templating": { 813 | "list": [ 814 | { 815 | "current": { 816 | "selected": true, 817 | "text": "Prometheus-Kepler", 818 | "value": "Prometheus-Kepler" 819 | }, 820 | "hide": 0, 821 | "includeAll": false, 822 | "multi": false, 823 | "name": "datasource", 824 | "options": [], 825 | "query": "prometheus", 826 | "queryValue": "", 827 | "refresh": 1, 828 | "regex": "", 829 | "skipUrlSync": false, 830 | "type": "datasource" 831 | }, 832 | { 833 | "allValue": ".*", 834 | "current": { 835 | "selected": false, 836 | "text": "All", 837 | "value": "$__all" 838 | }, 839 | "datasource": { 840 | "type": "prometheus", 841 | "uid": "${datasource}" 842 | }, 843 | "definition": "label_values(kepler_container_package_joules_total, container_namespace)", 844 | "description": "Namespace for pods to choose", 845 | "hide": 0, 846 | "includeAll": true, 847 | "label": "Namespace", 848 | "multi": false, 849 | "name": "namespace", 850 | "options": [], 851 | "query": { 852 | "query": "label_values(kepler_container_package_joules_total, container_namespace)", 853 | "refId": "StandardVariableQuery" 854 | }, 855 | "refresh": 1, 856 | "regex": "", 857 | "skipUrlSync": false, 858 | "sort": 0, 859 | "tagValuesQuery": "", 860 | "tagsQuery": "", 861 | "type": "query", 862 | "useTags": false 863 | }, 864 | { 865 | "allValue": ".*", 866 | "current": { 867 | "selected": false, 868 | "text": "All", 869 | "value": "$__all" 870 | }, 871 | "datasource": { 872 | "type": "prometheus", 873 | "uid": "${datasource}" 874 | }, 875 | "definition": "label_values(kepler_container_package_joules_total{container_namespace=~\"$namespace\"}, pod_name)", 876 | "hide": 0, 877 | "includeAll": true, 878 | "label": "Pod", 879 | "multi": false, 880 | "name": "pod", 881 | "options": [], 882 | "query": { 883 | "query": "label_values(kepler_container_package_joules_total{container_namespace=~\"$namespace\"}, pod_name)", 884 | "refId": "StandardVariableQuery" 885 | }, 886 | "refresh": 1, 887 | "regex": "", 888 | "skipUrlSync": false, 889 | "sort": 0, 890 | "tagValuesQuery": "", 891 | "tagsQuery": "", 892 | "type": "query", 893 | "useTags": false 894 | }, 895 | { 896 | "current": { 897 | "selected": false, 898 | "text": "2.23", 899 | "value": "2.23" 900 | }, 901 | "hide": 0, 902 | "label": "Coal Coeff", 903 | "name": "coal", 904 | "options": [ 905 | { 906 | "selected": true, 907 | "text": "2.23", 908 | "value": "2.23" 909 | } 910 | ], 911 | "query": "2.23", 912 | "skipUrlSync": false, 913 | "type": "textbox" 914 | }, 915 | { 916 | "current": { 917 | "selected": false, 918 | "text": "0.91", 919 | "value": "0.91" 920 | }, 921 | "hide": 0, 922 | "label": "Natural Gas Coeff", 923 | "name": "natural_gas", 924 | "options": [ 925 | { 926 | "selected": true, 927 | "text": "0.91", 928 | "value": "0.91" 929 | } 930 | ], 931 | "query": "0.91", 932 | "skipUrlSync": false, 933 | "type": "textbox" 934 | }, 935 | { 936 | "current": { 937 | "selected": false, 938 | "text": "2.13", 939 | "value": "2.13" 940 | }, 941 | "hide": 0, 942 | "label": "Petroleum Coeff", 943 | "name": "petroleum", 944 | "options": [ 945 | { 946 | "selected": true, 947 | "text": "2.13", 948 | "value": "2.13" 949 | } 950 | ], 951 | "query": "2.13", 952 | "skipUrlSync": false, 953 | "type": "textbox" 954 | }, 955 | { 956 | "description": "1W*s = 1J and 1J = (1/3600000)kWh", 957 | "hide": 2, 958 | "label": "", 959 | "name": "watt_per_second_to_kWh", 960 | "query": "0.000000277777777777778", 961 | "skipUrlSync": false, 962 | "type": "constant" 963 | } 964 | ] 965 | }, 966 | "time": { 967 | "from": "now-15m", 968 | "to": "now" 969 | }, 970 | "timepicker": {}, 971 | "timezone": "browser", 972 | "title": "Kepler Exporter Dashboard", 973 | "uid": "NhnADUW4zIBM", 974 | "version": 1, 975 | "weekStart": "" 976 | } -------------------------------------------------------------------------------- /chart/files/caas-carbon-dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "target": { 12 | "limit": 100, 13 | "matchAny": false, 14 | "tags": [ 15 | "sustainable-computing" 16 | ], 17 | "type": "dashboard" 18 | }, 19 | "type": "dashboard" 20 | } 21 | ] 22 | }, 23 | "description": "Dashboard for CaaS Carbon Footprint", 24 | "editable": true, 25 | "fiscalYearStartMonth": 0, 26 | "graphTooltip": 0, 27 | "links": [], 28 | "liveNow": false, 29 | "panels": [ 30 | { 31 | "collapsed": false, 32 | "datasource": "prometheus", 33 | "gridPos": { 34 | "h": 1, 35 | "w": 24, 36 | "x": 0, 37 | "y": 0 38 | }, 39 | "id": 11, 40 | "panels": [], 41 | "title": "Carbon Emissions", 42 | "type": "row" 43 | }, 44 | { 45 | "datasource": { 46 | "type": "prometheus", 47 | "uid": "${datasource}" 48 | }, 49 | "fieldConfig": { 50 | "defaults": { 51 | "color": { 52 | "mode": "palette-classic" 53 | }, 54 | "custom": { 55 | "hideFrom": { 56 | "legend": false, 57 | "tooltip": false, 58 | "viz": false 59 | } 60 | }, 61 | "mappings": [] 62 | }, 63 | "overrides": [ 64 | { 65 | "matcher": { 66 | "id": "byName", 67 | "options": "Gas" 68 | }, 69 | "properties": [ 70 | { 71 | "id": "color", 72 | "value": { 73 | "fixedColor": "orange", 74 | "mode": "fixed" 75 | } 76 | } 77 | ] 78 | }, 79 | { 80 | "matcher": { 81 | "id": "byName", 82 | "options": "Hard Coal" 83 | }, 84 | "properties": [ 85 | { 86 | "id": "color", 87 | "value": { 88 | "fixedColor": "#010101", 89 | "mode": "fixed" 90 | } 91 | } 92 | ] 93 | }, 94 | { 95 | "matcher": { 96 | "id": "byName", 97 | "options": "Wind Onshore" 98 | }, 99 | "properties": [ 100 | { 101 | "id": "color", 102 | "value": { 103 | "fixedColor": "dark-green", 104 | "mode": "fixed" 105 | } 106 | } 107 | ] 108 | }, 109 | { 110 | "matcher": { 111 | "id": "byName", 112 | "options": "Wind Offshore" 113 | }, 114 | "properties": [ 115 | { 116 | "id": "color", 117 | "value": { 118 | "fixedColor": "light-green", 119 | "mode": "fixed" 120 | } 121 | } 122 | ] 123 | }, 124 | { 125 | "matcher": { 126 | "id": "byName", 127 | "options": "Brown Coal" 128 | }, 129 | "properties": [ 130 | { 131 | "id": "color", 132 | "value": { 133 | "fixedColor": "#5c291b", 134 | "mode": "fixed" 135 | } 136 | } 137 | ] 138 | }, 139 | { 140 | "matcher": { 141 | "id": "byName", 142 | "options": "Waste" 143 | }, 144 | "properties": [ 145 | { 146 | "id": "color", 147 | "value": { 148 | "fixedColor": "#ef3524", 149 | "mode": "fixed" 150 | } 151 | } 152 | ] 153 | }, 154 | { 155 | "matcher": { 156 | "id": "byName", 157 | "options": "Geothermal" 158 | }, 159 | "properties": [ 160 | { 161 | "id": "color", 162 | "value": { 163 | "fixedColor": "#f4001d", 164 | "mode": "fixed" 165 | } 166 | } 167 | ] 168 | }, 169 | { 170 | "matcher": { 171 | "id": "byName", 172 | "options": "Biomass" 173 | }, 174 | "properties": [ 175 | { 176 | "id": "color", 177 | "value": { 178 | "fixedColor": "#b9d0b6", 179 | "mode": "fixed" 180 | } 181 | } 182 | ] 183 | }, 184 | { 185 | "matcher": { 186 | "id": "byName", 187 | "options": "Hydro Water Res." 188 | }, 189 | "properties": [ 190 | { 191 | "id": "color", 192 | "value": { 193 | "fixedColor": "dark-blue", 194 | "mode": "fixed" 195 | } 196 | } 197 | ] 198 | }, 199 | { 200 | "matcher": { 201 | "id": "byName", 202 | "options": "Hydro Run-of-river" 203 | }, 204 | "properties": [ 205 | { 206 | "id": "color", 207 | "value": { 208 | "fixedColor": "light-blue", 209 | "mode": "fixed" 210 | } 211 | } 212 | ] 213 | }, 214 | { 215 | "matcher": { 216 | "id": "byName", 217 | "options": "Nuclear" 218 | }, 219 | "properties": [ 220 | { 221 | "id": "color", 222 | "value": { 223 | "fixedColor": "#f8f17b", 224 | "mode": "fixed" 225 | } 226 | } 227 | ] 228 | } 229 | ] 230 | }, 231 | "gridPos": { 232 | "h": 12, 233 | "w": 12, 234 | "x": 0, 235 | "y": 1 236 | }, 237 | "id": 1, 238 | "options": { 239 | "displayLabels": [ 240 | "value" 241 | ], 242 | "legend": { 243 | "displayMode": "list", 244 | "placement": "bottom", 245 | "showLegend": true, 246 | "values": [] 247 | }, 248 | "pieType": "pie", 249 | "reduceOptions": { 250 | "calcs": [ 251 | "mean" 252 | ], 253 | "fields": "", 254 | "values": false 255 | }, 256 | "tooltip": { 257 | "mode": "single", 258 | "sort": "none" 259 | } 260 | }, 261 | "targets": [ 262 | { 263 | "datasource": { 264 | "type": "prometheus", 265 | "uid": "${datasource}" 266 | }, 267 | "disableTextWrap": false, 268 | "editorMode": "builder", 269 | "exemplar": false, 270 | "expr": "avg(entsoe_generation_b01)", 271 | "format": "time_series", 272 | "fullMetaSearch": false, 273 | "includeNullMetadata": true, 274 | "instant": false, 275 | "legendFormat": "Biomass", 276 | "range": true, 277 | "refId": "A", 278 | "useBackend": false 279 | }, 280 | { 281 | "datasource": { 282 | "type": "prometheus", 283 | "uid": "${datasource}" 284 | }, 285 | "disableTextWrap": false, 286 | "editorMode": "builder", 287 | "exemplar": false, 288 | "expr": "avg(entsoe_generation_b02)", 289 | "format": "time_series", 290 | "fullMetaSearch": false, 291 | "includeNullMetadata": true, 292 | "instant": false, 293 | "legendFormat": "Brown Coal", 294 | "range": true, 295 | "refId": "B", 296 | "useBackend": false 297 | }, 298 | { 299 | "datasource": { 300 | "type": "prometheus", 301 | "uid": "${datasource}" 302 | }, 303 | "disableTextWrap": false, 304 | "editorMode": "builder", 305 | "exemplar": false, 306 | "expr": "avg(entsoe_generation_b04)", 307 | "format": "time_series", 308 | "fullMetaSearch": false, 309 | "includeNullMetadata": true, 310 | "instant": false, 311 | "legendFormat": "Gas", 312 | "range": true, 313 | "refId": "C", 314 | "useBackend": false 315 | }, 316 | { 317 | "datasource": { 318 | "type": "prometheus", 319 | "uid": "${datasource}" 320 | }, 321 | "disableTextWrap": false, 322 | "editorMode": "builder", 323 | "exemplar": false, 324 | "expr": "avg(entsoe_generation_b05)", 325 | "format": "time_series", 326 | "fullMetaSearch": false, 327 | "includeNullMetadata": true, 328 | "instant": false, 329 | "legendFormat": "Hard Coal", 330 | "range": true, 331 | "refId": "D", 332 | "useBackend": false 333 | }, 334 | { 335 | "datasource": { 336 | "type": "prometheus", 337 | "uid": "${datasource}" 338 | }, 339 | "disableTextWrap": false, 340 | "editorMode": "builder", 341 | "exemplar": false, 342 | "expr": "avg(entsoe_generation_b09)", 343 | "format": "time_series", 344 | "fullMetaSearch": false, 345 | "includeNullMetadata": true, 346 | "instant": false, 347 | "legendFormat": "Geothermal", 348 | "range": true, 349 | "refId": "E", 350 | "useBackend": false 351 | }, 352 | { 353 | "datasource": { 354 | "type": "prometheus", 355 | "uid": "${datasource}" 356 | }, 357 | "disableTextWrap": false, 358 | "editorMode": "builder", 359 | "exemplar": false, 360 | "expr": "avg(entsoe_generation_b10)", 361 | "format": "time_series", 362 | "fullMetaSearch": false, 363 | "includeNullMetadata": true, 364 | "instant": false, 365 | "legendFormat": "Hydro Pumped Storage", 366 | "range": true, 367 | "refId": "F", 368 | "useBackend": false 369 | }, 370 | { 371 | "datasource": { 372 | "type": "prometheus", 373 | "uid": "${datasource}" 374 | }, 375 | "disableTextWrap": false, 376 | "editorMode": "builder", 377 | "exemplar": false, 378 | "expr": "avg(entsoe_generation_b11)", 379 | "format": "time_series", 380 | "fullMetaSearch": false, 381 | "includeNullMetadata": true, 382 | "instant": false, 383 | "legendFormat": "Hydro Run-of-river", 384 | "range": true, 385 | "refId": "G", 386 | "useBackend": false 387 | }, 388 | { 389 | "datasource": { 390 | "type": "prometheus", 391 | "uid": "${datasource}" 392 | }, 393 | "disableTextWrap": false, 394 | "editorMode": "builder", 395 | "exemplar": false, 396 | "expr": "avg(entsoe_generation_b12)", 397 | "format": "time_series", 398 | "fullMetaSearch": false, 399 | "includeNullMetadata": true, 400 | "instant": false, 401 | "legendFormat": "Hydro Water Res.", 402 | "range": true, 403 | "refId": "H", 404 | "useBackend": false 405 | }, 406 | { 407 | "datasource": { 408 | "type": "prometheus", 409 | "uid": "${datasource}" 410 | }, 411 | "disableTextWrap": false, 412 | "editorMode": "builder", 413 | "exemplar": false, 414 | "expr": "avg(entsoe_generation_b14)", 415 | "format": "time_series", 416 | "fullMetaSearch": false, 417 | "includeNullMetadata": true, 418 | "instant": false, 419 | "legendFormat": "Nuclear", 420 | "range": true, 421 | "refId": "I", 422 | "useBackend": false 423 | }, 424 | { 425 | "datasource": { 426 | "type": "prometheus", 427 | "uid": "${datasource}" 428 | }, 429 | "disableTextWrap": false, 430 | "editorMode": "builder", 431 | "exemplar": false, 432 | "expr": "avg(entsoe_generation_b16)", 433 | "format": "time_series", 434 | "fullMetaSearch": false, 435 | "includeNullMetadata": true, 436 | "instant": false, 437 | "legendFormat": "Solar", 438 | "range": true, 439 | "refId": "J", 440 | "useBackend": false 441 | }, 442 | { 443 | "datasource": { 444 | "type": "prometheus", 445 | "uid": "${datasource}" 446 | }, 447 | "disableTextWrap": false, 448 | "editorMode": "builder", 449 | "exemplar": false, 450 | "expr": "avg(entsoe_generation_b17)", 451 | "format": "time_series", 452 | "fullMetaSearch": false, 453 | "includeNullMetadata": true, 454 | "instant": false, 455 | "legendFormat": "Waste", 456 | "range": true, 457 | "refId": "K", 458 | "useBackend": false 459 | }, 460 | { 461 | "datasource": { 462 | "type": "prometheus", 463 | "uid": "${datasource}" 464 | }, 465 | "disableTextWrap": false, 466 | "editorMode": "builder", 467 | "exemplar": false, 468 | "expr": "avg(entsoe_generation_b18)", 469 | "format": "time_series", 470 | "fullMetaSearch": false, 471 | "includeNullMetadata": true, 472 | "instant": false, 473 | "legendFormat": "Wind Offshore", 474 | "range": true, 475 | "refId": "L", 476 | "useBackend": false 477 | }, 478 | { 479 | "datasource": { 480 | "type": "prometheus", 481 | "uid": "${datasource}" 482 | }, 483 | "disableTextWrap": false, 484 | "editorMode": "builder", 485 | "exemplar": false, 486 | "expr": "avg(entsoe_generation_b19)", 487 | "format": "time_series", 488 | "fullMetaSearch": false, 489 | "includeNullMetadata": true, 490 | "instant": false, 491 | "legendFormat": "Wind Onshore", 492 | "range": true, 493 | "refId": "M", 494 | "useBackend": false 495 | } 496 | ], 497 | "title": "Energy Generation Germany", 498 | "type": "piechart" 499 | }, 500 | { 501 | "datasource": { 502 | "type": "prometheus", 503 | "uid": "${datasource}" 504 | }, 505 | "description": "Using data from https://transparency.entsoe.eu/", 506 | "fieldConfig": { 507 | "defaults": { 508 | "color": { 509 | "mode": "thresholds" 510 | }, 511 | "mappings": [], 512 | "thresholds": { 513 | "mode": "absolute", 514 | "steps": [ 515 | { 516 | "color": "blue", 517 | "value": null 518 | }, 519 | { 520 | "color": "green", 521 | "value": 80 522 | } 523 | ] 524 | } 525 | }, 526 | "overrides": [] 527 | }, 528 | "gridPos": { 529 | "h": 6, 530 | "w": 7, 531 | "x": 12, 532 | "y": 1 533 | }, 534 | "id": 20, 535 | "options": { 536 | "colorMode": "value", 537 | "graphMode": "area", 538 | "justifyMode": "auto", 539 | "orientation": "auto", 540 | "reduceOptions": { 541 | "calcs": [ 542 | "mean" 543 | ], 544 | "fields": "", 545 | "values": false 546 | }, 547 | "textMode": "auto" 548 | }, 549 | "pluginVersion": "10.1.4", 550 | "targets": [ 551 | { 552 | "datasource": { 553 | "type": "prometheus", 554 | "uid": "${datasource}" 555 | }, 556 | "editorMode": "code", 557 | "expr": "avg(entsoe_generation_eco)*100", 558 | "hide": false, 559 | "legendFormat": "Engergy Index ECO %", 560 | "range": true, 561 | "refId": "B" 562 | } 563 | ], 564 | "title": "Energy ECO %", 565 | "type": "stat" 566 | }, 567 | { 568 | "datasource": { 569 | "type": "prometheus", 570 | "uid": "${datasource}" 571 | }, 572 | "description": "Using data from https://transparency.entsoe.eu/", 573 | "fieldConfig": { 574 | "defaults": { 575 | "color": { 576 | "mode": "thresholds" 577 | }, 578 | "mappings": [], 579 | "thresholds": { 580 | "mode": "absolute", 581 | "steps": [ 582 | { 583 | "color": "#5e5c5e", 584 | "value": null 585 | }, 586 | { 587 | "color": "light-red", 588 | "value": 0.1 589 | }, 590 | { 591 | "color": "dark-orange", 592 | "value": 0.2 593 | }, 594 | { 595 | "color": "orange", 596 | "value": 0.3 597 | }, 598 | { 599 | "color": "super-light-orange", 600 | "value": 0.4 601 | }, 602 | { 603 | "color": "#EAB839", 604 | "value": 0.5 605 | }, 606 | { 607 | "color": "light-yellow", 608 | "value": 0.6 609 | }, 610 | { 611 | "color": "super-light-green", 612 | "value": 0.7 613 | }, 614 | { 615 | "color": "green", 616 | "value": 0.8 617 | }, 618 | { 619 | "color": "dark-green", 620 | "value": 0.9 621 | } 622 | ] 623 | } 624 | }, 625 | "overrides": [] 626 | }, 627 | "gridPos": { 628 | "h": 12, 629 | "w": 4, 630 | "x": 19, 631 | "y": 1 632 | }, 633 | "id": 25, 634 | "options": { 635 | "displayMode": "lcd", 636 | "minVizHeight": 10, 637 | "minVizWidth": 0, 638 | "orientation": "auto", 639 | "reduceOptions": { 640 | "calcs": [ 641 | "last" 642 | ], 643 | "fields": "", 644 | "values": false 645 | }, 646 | "showUnfilled": true, 647 | "valueMode": "color" 648 | }, 649 | "pluginVersion": "10.1.4", 650 | "targets": [ 651 | { 652 | "datasource": { 653 | "type": "prometheus", 654 | "uid": "${datasource}" 655 | }, 656 | "editorMode": "code", 657 | "expr": "avg(entsoe_generation_eco)", 658 | "hide": false, 659 | "legendFormat": "Engergy Index ECO %", 660 | "range": true, 661 | "refId": "B" 662 | } 663 | ], 664 | "title": "Energy Ampel", 665 | "type": "bargauge" 666 | }, 667 | { 668 | "datasource": { 669 | "type": "prometheus", 670 | "uid": "${datasource}" 671 | }, 672 | "description": "Using data from https://transparency.entsoe.eu/", 673 | "fieldConfig": { 674 | "defaults": { 675 | "color": { 676 | "mode": "thresholds" 677 | }, 678 | "mappings": [], 679 | "thresholds": { 680 | "mode": "absolute", 681 | "steps": [ 682 | { 683 | "color": "blue", 684 | "value": null 685 | }, 686 | { 687 | "color": "red", 688 | "value": 80 689 | } 690 | ] 691 | } 692 | }, 693 | "overrides": [] 694 | }, 695 | "gridPos": { 696 | "h": 6, 697 | "w": 7, 698 | "x": 12, 699 | "y": 7 700 | }, 701 | "id": 27, 702 | "options": { 703 | "colorMode": "value", 704 | "graphMode": "area", 705 | "justifyMode": "auto", 706 | "orientation": "auto", 707 | "reduceOptions": { 708 | "calcs": [ 709 | "mean" 710 | ], 711 | "fields": "", 712 | "values": false 713 | }, 714 | "textMode": "auto" 715 | }, 716 | "pluginVersion": "10.1.4", 717 | "targets": [ 718 | { 719 | "datasource": { 720 | "type": "prometheus", 721 | "uid": "${datasource}" 722 | }, 723 | "editorMode": "code", 724 | "expr": "avg(entsoe_generation_fos)*100", 725 | "hide": false, 726 | "legendFormat": "Engergy Index ECO %", 727 | "range": true, 728 | "refId": "B" 729 | } 730 | ], 731 | "title": "Energy FOS %", 732 | "type": "stat" 733 | }, 734 | { 735 | "datasource": { 736 | "type": "prometheus", 737 | "uid": "${datasource}" 738 | }, 739 | "description": "Using data from https://transparency.entsoe.eu/", 740 | "fieldConfig": { 741 | "defaults": { 742 | "color": { 743 | "mode": "palette-classic" 744 | }, 745 | "custom": { 746 | "axisCenteredZero": false, 747 | "axisColorMode": "text", 748 | "axisLabel": "", 749 | "axisPlacement": "auto", 750 | "barAlignment": 0, 751 | "drawStyle": "line", 752 | "fillOpacity": 0, 753 | "gradientMode": "none", 754 | "hideFrom": { 755 | "legend": false, 756 | "tooltip": false, 757 | "viz": false 758 | }, 759 | "insertNulls": false, 760 | "lineInterpolation": "linear", 761 | "lineWidth": 1, 762 | "pointSize": 5, 763 | "scaleDistribution": { 764 | "type": "linear" 765 | }, 766 | "showPoints": "auto", 767 | "spanNulls": false, 768 | "stacking": { 769 | "group": "A", 770 | "mode": "none" 771 | }, 772 | "thresholdsStyle": { 773 | "mode": "off" 774 | } 775 | }, 776 | "mappings": [], 777 | "thresholds": { 778 | "mode": "absolute", 779 | "steps": [ 780 | { 781 | "color": "blue", 782 | "value": null 783 | }, 784 | { 785 | "color": "red", 786 | "value": 8 787 | } 788 | ] 789 | } 790 | }, 791 | "overrides": [ 792 | { 793 | "matcher": { 794 | "id": "byName", 795 | "options": "CO2 emmission" 796 | }, 797 | "properties": [ 798 | { 799 | "id": "color", 800 | "value": { 801 | "fixedColor": "blue", 802 | "mode": "fixed" 803 | } 804 | } 805 | ] 806 | } 807 | ] 808 | }, 809 | "gridPos": { 810 | "h": 8, 811 | "w": 23, 812 | "x": 0, 813 | "y": 13 814 | }, 815 | "id": 26, 816 | "options": { 817 | "legend": { 818 | "calcs": [], 819 | "displayMode": "list", 820 | "placement": "bottom", 821 | "showLegend": true 822 | }, 823 | "tooltip": { 824 | "mode": "single", 825 | "sort": "none" 826 | } 827 | }, 828 | "pluginVersion": "10.1.4", 829 | "targets": [ 830 | { 831 | "datasource": { 832 | "type": "prometheus", 833 | "uid": "${datasource}" 834 | }, 835 | "editorMode": "code", 836 | "expr": "avg(entsoe_generation_co2)", 837 | "hide": false, 838 | "legendFormat": "CO2 emmission", 839 | "range": true, 840 | "refId": "B" 841 | } 842 | ], 843 | "title": "CO2g/w", 844 | "transformations": [], 845 | "type": "timeseries" 846 | }, 847 | { 848 | "collapsed": false, 849 | "datasource": "prometheus", 850 | "gridPos": { 851 | "h": 1, 852 | "w": 24, 853 | "x": 0, 854 | "y": 21 855 | }, 856 | "id": 8, 857 | "panels": [], 858 | "title": "Power Consumption", 859 | "type": "row" 860 | }, 861 | { 862 | "datasource": { 863 | "type": "prometheus", 864 | "uid": "${datasource}" 865 | }, 866 | "description": "", 867 | "fieldConfig": { 868 | "defaults": { 869 | "color": { 870 | "mode": "palette-classic" 871 | }, 872 | "custom": { 873 | "axisCenteredZero": false, 874 | "axisColorMode": "text", 875 | "axisLabel": "watt", 876 | "axisPlacement": "left", 877 | "barAlignment": 0, 878 | "drawStyle": "bars", 879 | "fillOpacity": 44, 880 | "gradientMode": "opacity", 881 | "hideFrom": { 882 | "graph": false, 883 | "legend": false, 884 | "tooltip": false, 885 | "viz": false 886 | }, 887 | "insertNulls": false, 888 | "lineInterpolation": "linear", 889 | "lineWidth": 0, 890 | "pointSize": 5, 891 | "scaleDistribution": { 892 | "type": "linear" 893 | }, 894 | "showPoints": "always", 895 | "spanNulls": false, 896 | "stacking": { 897 | "group": "A", 898 | "mode": "normal" 899 | }, 900 | "thresholdsStyle": { 901 | "mode": "off" 902 | } 903 | }, 904 | "mappings": [], 905 | "thresholds": { 906 | "mode": "absolute", 907 | "steps": [ 908 | { 909 | "color": "green" 910 | }, 911 | { 912 | "color": "red", 913 | "value": 80 914 | } 915 | ] 916 | } 917 | }, 918 | "overrides": [ 919 | { 920 | "matcher": { 921 | "id": "byRegexp", 922 | "options": ".*DRAM.*" 923 | }, 924 | "properties": [ 925 | { 926 | "id": "color", 927 | "value": { 928 | "fixedColor": "orange", 929 | "mode": "fixed" 930 | } 931 | } 932 | ] 933 | }, 934 | { 935 | "matcher": { 936 | "id": "byRegexp", 937 | "options": ".*OTHER.*" 938 | }, 939 | "properties": [ 940 | { 941 | "id": "color", 942 | "value": { 943 | "fixedColor": "blue", 944 | "mode": "fixed" 945 | } 946 | } 947 | ] 948 | }, 949 | { 950 | "matcher": { 951 | "id": "byRegexp", 952 | "options": ".*GPU.*" 953 | }, 954 | "properties": [ 955 | { 956 | "id": "color", 957 | "value": { 958 | "fixedColor": "semi-dark-green", 959 | "mode": "fixed" 960 | } 961 | } 962 | ] 963 | }, 964 | { 965 | "matcher": { 966 | "id": "byRegexp", 967 | "options": ".*PKG.*" 968 | }, 969 | "properties": [ 970 | { 971 | "id": "color", 972 | "value": { 973 | "fixedColor": "red", 974 | "mode": "fixed" 975 | } 976 | } 977 | ] 978 | } 979 | ] 980 | }, 981 | "gridPos": { 982 | "h": 10, 983 | "w": 24, 984 | "x": 0, 985 | "y": 22 986 | }, 987 | "id": 16, 988 | "options": { 989 | "legend": { 990 | "calcs": [ 991 | "mean" 992 | ], 993 | "displayMode": "table", 994 | "placement": "right", 995 | "showLegend": true, 996 | "sortBy": "Mean", 997 | "sortDesc": true 998 | }, 999 | "tooltip": { 1000 | "mode": "single", 1001 | "sort": "none" 1002 | } 1003 | }, 1004 | "targets": [ 1005 | { 1006 | "datasource": "prometheus", 1007 | "editorMode": "code", 1008 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1009 | "hide": false, 1010 | "interval": "", 1011 | "legendFormat": "{{pod_name}} / {{container_namespace}} / PKG", 1012 | "range": true, 1013 | "refId": "A" 1014 | }, 1015 | { 1016 | "datasource": "prometheus", 1017 | "editorMode": "code", 1018 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1019 | "hide": false, 1020 | "interval": "", 1021 | "legendFormat": "{{pod_name}} / {{container_namespace}} / DRAM", 1022 | "range": true, 1023 | "refId": "B" 1024 | }, 1025 | { 1026 | "datasource": { 1027 | "type": "prometheus", 1028 | "uid": "${datasource}" 1029 | }, 1030 | "editorMode": "code", 1031 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1032 | "hide": false, 1033 | "interval": "", 1034 | "legendFormat": "{{pod_name}} / {{container_namespace}} / OTHER", 1035 | "range": true, 1036 | "refId": "C" 1037 | }, 1038 | { 1039 | "datasource": { 1040 | "type": "prometheus", 1041 | "uid": "${datasource}" 1042 | }, 1043 | "editorMode": "code", 1044 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1045 | "hide": false, 1046 | "legendFormat": "{{pod_name}} / {{container_namespace}} / GPU", 1047 | "range": true, 1048 | "refId": "D" 1049 | } 1050 | ], 1051 | "title": "Pod/Process Power Consumption (W) in Namespace: $namespace", 1052 | "type": "timeseries" 1053 | }, 1054 | { 1055 | "datasource": { 1056 | "type": "prometheus", 1057 | "uid": "${datasource}" 1058 | }, 1059 | "description": "", 1060 | "fieldConfig": { 1061 | "defaults": { 1062 | "color": { 1063 | "mode": "palette-classic" 1064 | }, 1065 | "custom": { 1066 | "axisCenteredZero": false, 1067 | "axisColorMode": "text", 1068 | "axisLabel": "CO2g/h", 1069 | "axisPlacement": "left", 1070 | "barAlignment": 0, 1071 | "drawStyle": "bars", 1072 | "fillOpacity": 44, 1073 | "gradientMode": "opacity", 1074 | "hideFrom": { 1075 | "graph": false, 1076 | "legend": false, 1077 | "tooltip": false, 1078 | "viz": false 1079 | }, 1080 | "insertNulls": false, 1081 | "lineInterpolation": "linear", 1082 | "lineWidth": 0, 1083 | "pointSize": 5, 1084 | "scaleDistribution": { 1085 | "type": "linear" 1086 | }, 1087 | "showPoints": "always", 1088 | "spanNulls": false, 1089 | "stacking": { 1090 | "group": "A", 1091 | "mode": "normal" 1092 | }, 1093 | "thresholdsStyle": { 1094 | "mode": "off" 1095 | } 1096 | }, 1097 | "mappings": [], 1098 | "thresholds": { 1099 | "mode": "absolute", 1100 | "steps": [ 1101 | { 1102 | "color": "green" 1103 | }, 1104 | { 1105 | "color": "red", 1106 | "value": 80 1107 | } 1108 | ] 1109 | } 1110 | }, 1111 | "overrides": [ 1112 | { 1113 | "matcher": { 1114 | "id": "byRegexp", 1115 | "options": ".*DRAM.*" 1116 | }, 1117 | "properties": [ 1118 | { 1119 | "id": "color", 1120 | "value": { 1121 | "fixedColor": "orange", 1122 | "mode": "fixed" 1123 | } 1124 | } 1125 | ] 1126 | }, 1127 | { 1128 | "matcher": { 1129 | "id": "byRegexp", 1130 | "options": ".*OTHER.*" 1131 | }, 1132 | "properties": [ 1133 | { 1134 | "id": "color", 1135 | "value": { 1136 | "fixedColor": "blue", 1137 | "mode": "fixed" 1138 | } 1139 | } 1140 | ] 1141 | }, 1142 | { 1143 | "matcher": { 1144 | "id": "byRegexp", 1145 | "options": ".*GPU.*" 1146 | }, 1147 | "properties": [ 1148 | { 1149 | "id": "color", 1150 | "value": { 1151 | "fixedColor": "semi-dark-green", 1152 | "mode": "fixed" 1153 | } 1154 | } 1155 | ] 1156 | }, 1157 | { 1158 | "matcher": { 1159 | "id": "byRegexp", 1160 | "options": ".*PKG.*" 1161 | }, 1162 | "properties": [ 1163 | { 1164 | "id": "color", 1165 | "value": { 1166 | "fixedColor": "red", 1167 | "mode": "fixed" 1168 | } 1169 | } 1170 | ] 1171 | } 1172 | ] 1173 | }, 1174 | "gridPos": { 1175 | "h": 10, 1176 | "w": 24, 1177 | "x": 0, 1178 | "y": 32 1179 | }, 1180 | "id": 22, 1181 | "options": { 1182 | "legend": { 1183 | "calcs": [ 1184 | "last" 1185 | ], 1186 | "displayMode": "table", 1187 | "placement": "right", 1188 | "showLegend": true, 1189 | "sortBy": "Mean", 1190 | "sortDesc": false 1191 | }, 1192 | "tooltip": { 1193 | "mode": "single", 1194 | "sort": "none" 1195 | } 1196 | }, 1197 | "targets": [ 1198 | { 1199 | "datasource": "prometheus", 1200 | "editorMode": "code", 1201 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m])*(entsoe_generation_co2*3600))", 1202 | "hide": false, 1203 | "interval": "", 1204 | "legendFormat": "{{pod_name}} / {{container_namespace}} / PKG", 1205 | "range": true, 1206 | "refId": "A" 1207 | }, 1208 | { 1209 | "datasource": "prometheus", 1210 | "editorMode": "code", 1211 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m])*($fosfactor/1000)*($ecofactor/1000))", 1212 | "hide": false, 1213 | "interval": "", 1214 | "legendFormat": "{{pod_name}} / {{container_namespace}} / DRAM", 1215 | "range": true, 1216 | "refId": "B" 1217 | }, 1218 | { 1219 | "datasource": { 1220 | "type": "prometheus", 1221 | "uid": "${datasource}" 1222 | }, 1223 | "editorMode": "code", 1224 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m])*($fosfactor/1000)*($ecofactor/1000))", 1225 | "hide": false, 1226 | "interval": "", 1227 | "legendFormat": "{{pod_name}} / {{container_namespace}} / OTHER", 1228 | "range": true, 1229 | "refId": "C" 1230 | }, 1231 | { 1232 | "datasource": { 1233 | "type": "prometheus", 1234 | "uid": "${datasource}" 1235 | }, 1236 | "editorMode": "code", 1237 | "expr": "sum by (pod_name, container_namespace) (irate(kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m])*($fosfactor/1000)*($ecofactor/1000))", 1238 | "hide": false, 1239 | "legendFormat": "{{pod_name}} / {{container_namespace}} / GPU", 1240 | "range": true, 1241 | "refId": "D" 1242 | } 1243 | ], 1244 | "title": "Pod/Process CO2 FOS Emission (C02g/h) in Namespace: $namespace", 1245 | "type": "timeseries" 1246 | }, 1247 | { 1248 | "datasource": { 1249 | "type": "prometheus", 1250 | "uid": "${datasource}" 1251 | }, 1252 | "description": "", 1253 | "fieldConfig": { 1254 | "defaults": { 1255 | "color": { 1256 | "mode": "palette-classic" 1257 | }, 1258 | "custom": { 1259 | "axisCenteredZero": false, 1260 | "axisColorMode": "text", 1261 | "axisLabel": "watt", 1262 | "axisPlacement": "left", 1263 | "barAlignment": 0, 1264 | "drawStyle": "bars", 1265 | "fillOpacity": 44, 1266 | "gradientMode": "opacity", 1267 | "hideFrom": { 1268 | "graph": false, 1269 | "legend": false, 1270 | "tooltip": false, 1271 | "viz": false 1272 | }, 1273 | "insertNulls": false, 1274 | "lineInterpolation": "linear", 1275 | "lineWidth": 0, 1276 | "pointSize": 5, 1277 | "scaleDistribution": { 1278 | "type": "linear" 1279 | }, 1280 | "showPoints": "always", 1281 | "spanNulls": false, 1282 | "stacking": { 1283 | "group": "A", 1284 | "mode": "normal" 1285 | }, 1286 | "thresholdsStyle": { 1287 | "mode": "off" 1288 | } 1289 | }, 1290 | "mappings": [], 1291 | "thresholds": { 1292 | "mode": "absolute", 1293 | "steps": [ 1294 | { 1295 | "color": "green" 1296 | }, 1297 | { 1298 | "color": "red", 1299 | "value": 80 1300 | } 1301 | ] 1302 | } 1303 | }, 1304 | "overrides": [ 1305 | { 1306 | "matcher": { 1307 | "id": "byRegexp", 1308 | "options": ".*Package.*" 1309 | }, 1310 | "properties": [ 1311 | { 1312 | "id": "color", 1313 | "value": { 1314 | "fixedColor": "red", 1315 | "mode": "fixed" 1316 | } 1317 | } 1318 | ] 1319 | }, 1320 | { 1321 | "matcher": { 1322 | "id": "byRegexp", 1323 | "options": ".*DRAM.*" 1324 | }, 1325 | "properties": [ 1326 | { 1327 | "id": "color", 1328 | "value": { 1329 | "fixedColor": "orange", 1330 | "mode": "fixed" 1331 | } 1332 | } 1333 | ] 1334 | }, 1335 | { 1336 | "matcher": { 1337 | "id": "byRegexp", 1338 | "options": ".*OtherComponents.*" 1339 | }, 1340 | "properties": [ 1341 | { 1342 | "id": "color", 1343 | "value": { 1344 | "fixedColor": "blue", 1345 | "mode": "fixed" 1346 | } 1347 | } 1348 | ] 1349 | }, 1350 | { 1351 | "matcher": { 1352 | "id": "byRegexp", 1353 | "options": ".*GPU.*" 1354 | }, 1355 | "properties": [ 1356 | { 1357 | "id": "color", 1358 | "value": { 1359 | "fixedColor": "semi-dark-green", 1360 | "mode": "fixed" 1361 | } 1362 | } 1363 | ] 1364 | } 1365 | ] 1366 | }, 1367 | "gridPos": { 1368 | "h": 8, 1369 | "w": 12, 1370 | "x": 0, 1371 | "y": 42 1372 | }, 1373 | "id": 2, 1374 | "options": { 1375 | "legend": { 1376 | "calcs": [ 1377 | "mean", 1378 | "max" 1379 | ], 1380 | "displayMode": "table", 1381 | "placement": "bottom", 1382 | "showLegend": true 1383 | }, 1384 | "tooltip": { 1385 | "mode": "single", 1386 | "sort": "none" 1387 | } 1388 | }, 1389 | "targets": [ 1390 | { 1391 | "datasource": { 1392 | "type": "prometheus", 1393 | "uid": "${datasource}" 1394 | }, 1395 | "editorMode": "code", 1396 | "expr": "sum(irate(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1397 | "hide": false, 1398 | "interval": "", 1399 | "legendFormat": "PKG", 1400 | "range": true, 1401 | "refId": "A" 1402 | }, 1403 | { 1404 | "datasource": { 1405 | "type": "prometheus", 1406 | "uid": "${datasource}" 1407 | }, 1408 | "editorMode": "code", 1409 | "expr": "sum(irate(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1410 | "hide": false, 1411 | "interval": "", 1412 | "legendFormat": "DRAM", 1413 | "range": true, 1414 | "refId": "B" 1415 | }, 1416 | { 1417 | "datasource": { 1418 | "type": "prometheus", 1419 | "uid": "${datasource}" 1420 | }, 1421 | "editorMode": "code", 1422 | "expr": "sum(irate(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1423 | "hide": false, 1424 | "legendFormat": "OTHER", 1425 | "range": true, 1426 | "refId": "C" 1427 | }, 1428 | { 1429 | "datasource": { 1430 | "type": "prometheus", 1431 | "uid": "${datasource}" 1432 | }, 1433 | "editorMode": "code", 1434 | "expr": "sum(irate(kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[5m]))", 1435 | "hide": false, 1436 | "legendFormat": " GPU", 1437 | "range": true, 1438 | "refId": "D" 1439 | } 1440 | ], 1441 | "title": "Total Power Consumption (W) in Namespace: $namespace", 1442 | "type": "timeseries" 1443 | }, 1444 | { 1445 | "datasource": { 1446 | "type": "prometheus", 1447 | "uid": "${datasource}" 1448 | }, 1449 | "description": "", 1450 | "fieldConfig": { 1451 | "defaults": { 1452 | "color": { 1453 | "mode": "palette-classic" 1454 | }, 1455 | "custom": { 1456 | "axisCenteredZero": false, 1457 | "axisColorMode": "text", 1458 | "axisLabel": "kWh", 1459 | "axisPlacement": "left", 1460 | "barAlignment": 0, 1461 | "drawStyle": "bars", 1462 | "fillOpacity": 44, 1463 | "gradientMode": "opacity", 1464 | "hideFrom": { 1465 | "graph": false, 1466 | "legend": false, 1467 | "tooltip": false, 1468 | "viz": false 1469 | }, 1470 | "insertNulls": false, 1471 | "lineInterpolation": "linear", 1472 | "lineWidth": 0, 1473 | "pointSize": 5, 1474 | "scaleDistribution": { 1475 | "type": "linear" 1476 | }, 1477 | "showPoints": "always", 1478 | "spanNulls": false, 1479 | "stacking": { 1480 | "group": "A", 1481 | "mode": "normal" 1482 | }, 1483 | "thresholdsStyle": { 1484 | "mode": "off" 1485 | } 1486 | }, 1487 | "mappings": [], 1488 | "thresholds": { 1489 | "mode": "absolute", 1490 | "steps": [ 1491 | { 1492 | "color": "green" 1493 | }, 1494 | { 1495 | "color": "red", 1496 | "value": 80 1497 | } 1498 | ] 1499 | } 1500 | }, 1501 | "overrides": [ 1502 | { 1503 | "matcher": { 1504 | "id": "byRegexp", 1505 | "options": ".*Package.*" 1506 | }, 1507 | "properties": [ 1508 | { 1509 | "id": "color", 1510 | "value": { 1511 | "fixedColor": "red", 1512 | "mode": "fixed" 1513 | } 1514 | } 1515 | ] 1516 | }, 1517 | { 1518 | "matcher": { 1519 | "id": "byRegexp", 1520 | "options": ".*DRAM.*" 1521 | }, 1522 | "properties": [ 1523 | { 1524 | "id": "color", 1525 | "value": { 1526 | "fixedColor": "orange", 1527 | "mode": "fixed" 1528 | } 1529 | } 1530 | ] 1531 | }, 1532 | { 1533 | "matcher": { 1534 | "id": "byRegexp", 1535 | "options": ".*OtherComponents.*" 1536 | }, 1537 | "properties": [ 1538 | { 1539 | "id": "color", 1540 | "value": { 1541 | "fixedColor": "blue", 1542 | "mode": "fixed" 1543 | } 1544 | } 1545 | ] 1546 | }, 1547 | { 1548 | "matcher": { 1549 | "id": "byRegexp", 1550 | "options": ".*GPU.*" 1551 | }, 1552 | "properties": [ 1553 | { 1554 | "id": "color", 1555 | "value": { 1556 | "fixedColor": "semi-dark-green", 1557 | "mode": "fixed" 1558 | } 1559 | } 1560 | ] 1561 | } 1562 | ] 1563 | }, 1564 | "gridPos": { 1565 | "h": 8, 1566 | "w": 12, 1567 | "x": 12, 1568 | "y": 42 1569 | }, 1570 | "id": 17, 1571 | "options": { 1572 | "legend": { 1573 | "calcs": [ 1574 | "mean", 1575 | "max" 1576 | ], 1577 | "displayMode": "table", 1578 | "placement": "bottom", 1579 | "showLegend": true, 1580 | "sortBy": "Max", 1581 | "sortDesc": true 1582 | }, 1583 | "tooltip": { 1584 | "mode": "single", 1585 | "sort": "none" 1586 | } 1587 | }, 1588 | "targets": [ 1589 | { 1590 | "datasource": { 1591 | "type": "prometheus", 1592 | "uid": "${datasource}" 1593 | }, 1594 | "editorMode": "code", 1595 | "expr": "sum (\n increase(\n (kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 1596 | "hide": false, 1597 | "interval": "", 1598 | "legendFormat": "PKG (CORE+UNCORE)", 1599 | "range": true, 1600 | "refId": "A" 1601 | }, 1602 | { 1603 | "datasource": { 1604 | "type": "prometheus", 1605 | "uid": "${datasource}" 1606 | }, 1607 | "editorMode": "code", 1608 | "expr": "sum (\n increase(\n (kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 1609 | "hide": false, 1610 | "interval": "", 1611 | "legendFormat": "DRAM", 1612 | "range": true, 1613 | "refId": "B" 1614 | }, 1615 | { 1616 | "datasource": { 1617 | "type": "prometheus", 1618 | "uid": "${datasource}" 1619 | }, 1620 | "editorMode": "code", 1621 | "expr": "sum (\n increase(\n (kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 1622 | "hide": false, 1623 | "legendFormat": "OTHER", 1624 | "range": true, 1625 | "refId": "C" 1626 | }, 1627 | { 1628 | "datasource": { 1629 | "type": "prometheus", 1630 | "uid": "${datasource}" 1631 | }, 1632 | "editorMode": "code", 1633 | "expr": "sum (\n increase(\n (kepler_container_gpu_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m])\n )\n) * $watt_per_second_to_kWh", 1634 | "hide": false, 1635 | "legendFormat": " GPU", 1636 | "range": true, 1637 | "refId": "D" 1638 | } 1639 | ], 1640 | "title": "Total Power Consumption (kWh per day) in Namespace: $namespace", 1641 | "type": "timeseries" 1642 | }, 1643 | { 1644 | "datasource": { 1645 | "type": "prometheus", 1646 | "uid": "${datasource}" 1647 | }, 1648 | "fieldConfig": { 1649 | "defaults": { 1650 | "color": { 1651 | "mode": "thresholds" 1652 | }, 1653 | "mappings": [], 1654 | "thresholds": { 1655 | "mode": "absolute", 1656 | "steps": [ 1657 | { 1658 | "color": "green" 1659 | }, 1660 | { 1661 | "color": "red", 1662 | "value": 80 1663 | } 1664 | ] 1665 | } 1666 | }, 1667 | "overrides": [] 1668 | }, 1669 | "gridPos": { 1670 | "h": 7, 1671 | "w": 24, 1672 | "x": 0, 1673 | "y": 50 1674 | }, 1675 | "id": 15, 1676 | "options": { 1677 | "displayMode": "gradient", 1678 | "minVizHeight": 10, 1679 | "minVizWidth": 0, 1680 | "orientation": "auto", 1681 | "reduceOptions": { 1682 | "calcs": [ 1683 | "lastNotNull" 1684 | ], 1685 | "fields": "", 1686 | "values": false 1687 | }, 1688 | "showUnfilled": true, 1689 | "valueMode": "color" 1690 | }, 1691 | "pluginVersion": "10.1.4", 1692 | "targets": [ 1693 | { 1694 | "datasource": { 1695 | "type": "prometheus", 1696 | "uid": "${datasource}" 1697 | }, 1698 | "editorMode": "code", 1699 | "expr": "sum by (container_namespace)(\n (\n increase(kepler_container_dram_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m]) +\n increase(kepler_container_other_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m]) +\n increase(kepler_container_package_joules_total{container_namespace=~\"$namespace\", pod_name=~\"$pod\", cluster=~\"$meta_cluster\"}[24h:1m])\n ) * $watt_per_second_to_kWh\n)", 1700 | "interval": "", 1701 | "legendFormat": "{{container_namespace}}", 1702 | "range": true, 1703 | "refId": "A" 1704 | } 1705 | ], 1706 | "title": "Total Power Consumption (PKG+DRAM+OTHER+GPU) by Namespace (kWh per day)", 1707 | "type": "bargauge" 1708 | } 1709 | ], 1710 | "refresh": "", 1711 | "schemaVersion": 38, 1712 | "style": "dark", 1713 | "tags": [ 1714 | "sustainable-computing" 1715 | ], 1716 | "templating": { 1717 | "list": [ 1718 | { 1719 | "current": { 1720 | "selected": true, 1721 | "text": "default", 1722 | "value": "default" 1723 | }, 1724 | "hide": 0, 1725 | "includeAll": false, 1726 | "multi": false, 1727 | "name": "datasource", 1728 | "options": [], 1729 | "query": "prometheus", 1730 | "queryValue": "", 1731 | "refresh": 1, 1732 | "regex": "", 1733 | "skipUrlSync": false, 1734 | "type": "datasource" 1735 | }, 1736 | { 1737 | "allValue": ".*", 1738 | "current": { 1739 | "selected": false, 1740 | "text": "All", 1741 | "value": "$__all" 1742 | }, 1743 | "datasource": { 1744 | "type": "prometheus", 1745 | "uid": "${datasource}" 1746 | }, 1747 | "definition": "label_values(kepler_container_package_joules_total{cluster=~\"$meta_cluster\"}, container_namespace)", 1748 | "description": "Namespace for pods to choose", 1749 | "hide": 0, 1750 | "includeAll": true, 1751 | "label": "Namespace", 1752 | "multi": false, 1753 | "name": "namespace", 1754 | "options": [], 1755 | "query": { 1756 | "query": "label_values(kepler_container_package_joules_total{cluster=~\"$meta_cluster\"}, container_namespace)", 1757 | "refId": "StandardVariableQuery" 1758 | }, 1759 | "refresh": 1, 1760 | "regex": "", 1761 | "skipUrlSync": false, 1762 | "sort": 0, 1763 | "tagValuesQuery": "", 1764 | "tagsQuery": "", 1765 | "type": "query", 1766 | "useTags": false 1767 | }, 1768 | { 1769 | "allValue": ".*", 1770 | "current": { 1771 | "selected": false, 1772 | "text": "All", 1773 | "value": "$__all" 1774 | }, 1775 | "datasource": { 1776 | "type": "prometheus", 1777 | "uid": "${datasource}" 1778 | }, 1779 | "definition": "label_values(kepler_container_package_joules_total{container_namespace=~\"$namespace\",cluster=~\"$meta_cluster\"}, pod_name)", 1780 | "hide": 0, 1781 | "includeAll": true, 1782 | "label": "Pod", 1783 | "multi": false, 1784 | "name": "pod", 1785 | "options": [], 1786 | "query": { 1787 | "query": "label_values(kepler_container_package_joules_total{container_namespace=~\"$namespace\",cluster=~\"$meta_cluster\"}, pod_name)", 1788 | "refId": "StandardVariableQuery" 1789 | }, 1790 | "refresh": 1, 1791 | "regex": "", 1792 | "skipUrlSync": false, 1793 | "sort": 0, 1794 | "tagValuesQuery": "", 1795 | "tagsQuery": "", 1796 | "type": "query", 1797 | "useTags": false 1798 | }, 1799 | { 1800 | "allValue": ".*", 1801 | "current": { 1802 | "selected": false, 1803 | "text": "All", 1804 | "value": "$__all" 1805 | }, 1806 | "datasource": { 1807 | "type": "prometheus", 1808 | "uid": "${datasource}" 1809 | }, 1810 | "definition": "label_values(prometheus_build_info, cluster)", 1811 | "hide": 0, 1812 | "includeAll": true, 1813 | "label": "Cluster", 1814 | "multi": false, 1815 | "name": "meta_cluster", 1816 | "options": [], 1817 | "query": "label_values(prometheus_build_info, cluster)", 1818 | "refresh": 2, 1819 | "regex": "", 1820 | "skipUrlSync": false, 1821 | "sort": 1, 1822 | "tagValuesQuery": "", 1823 | "tagsQuery": "", 1824 | "type": "query", 1825 | "useTags": false 1826 | }, 1827 | { 1828 | "description": "1W*s = 1J and 1J = (1/3600000)kWh", 1829 | "hide": 2, 1830 | "label": "", 1831 | "name": "watt_per_second_to_kWh", 1832 | "query": "0.000000277777777777778", 1833 | "skipUrlSync": false, 1834 | "type": "constant" 1835 | }, 1836 | { 1837 | "description": "FOS CO2g/kWh", 1838 | "hide": 2, 1839 | "name": "fosfactor", 1840 | "query": "751", 1841 | "skipUrlSync": false, 1842 | "type": "constant" 1843 | }, 1844 | { 1845 | "description": "ECO CO2g/kWh", 1846 | "hide": 2, 1847 | "name": "ecofactor", 1848 | "query": "117", 1849 | "skipUrlSync": false, 1850 | "type": "constant" 1851 | }, 1852 | { 1853 | "description": "B01 Biomass CO2g/kWh", 1854 | "hide": 2, 1855 | "name": "biomass", 1856 | "query": "230", 1857 | "skipUrlSync": false, 1858 | "type": "constant" 1859 | }, 1860 | { 1861 | "description": "B02 Brown Coal CO2g/kWh", 1862 | "hide": 2, 1863 | "name": "browncoal", 1864 | "query": "996", 1865 | "skipUrlSync": false, 1866 | "type": "constant" 1867 | }, 1868 | { 1869 | "description": "B05 Hard Coal CO2g/kWh", 1870 | "hide": 2, 1871 | "name": "hardcoal", 1872 | "query": "880", 1873 | "skipUrlSync": false, 1874 | "type": "constant" 1875 | }, 1876 | { 1877 | "description": "B04 Gas CO2g/kWh", 1878 | "hide": 2, 1879 | "name": "gas", 1880 | "query": "378", 1881 | "skipUrlSync": false, 1882 | "type": "constant" 1883 | }, 1884 | { 1885 | "description": "B14 Nuclear CO2g/kWh", 1886 | "hide": 2, 1887 | "name": "nuclear", 1888 | "query": "39", 1889 | "skipUrlSync": false, 1890 | "type": "constant" 1891 | }, 1892 | { 1893 | "description": "B19 Wind Onshore CO2g/kWh", 1894 | "hide": 2, 1895 | "name": "windonshore", 1896 | "query": "9", 1897 | "skipUrlSync": false, 1898 | "type": "constant" 1899 | }, 1900 | { 1901 | "description": "B18 Wind Offhore CO2g/kWh", 1902 | "hide": 2, 1903 | "name": "windoffshore", 1904 | "query": "4", 1905 | "skipUrlSync": false, 1906 | "type": "constant" 1907 | }, 1908 | { 1909 | "description": "B16 Solar CO2g/kWh", 1910 | "hide": 2, 1911 | "name": "solar", 1912 | "query": "26", 1913 | "skipUrlSync": false, 1914 | "type": "constant" 1915 | }, 1916 | { 1917 | "description": "B17 Waste CO2g/kWh", 1918 | "hide": 2, 1919 | "name": "waste", 1920 | "query": "494", 1921 | "skipUrlSync": false, 1922 | "type": "constant" 1923 | }, 1924 | { 1925 | "description": "B10 Hydro Pumped Storage CO2g/kWh", 1926 | "hide": 2, 1927 | "name": "hydropump", 1928 | "query": "23", 1929 | "skipUrlSync": false, 1930 | "type": "constant" 1931 | }, 1932 | { 1933 | "description": "B11 Hydro Run River CO2g/kWh", 1934 | "hide": 2, 1935 | "name": "hydroriver", 1936 | "query": "23", 1937 | "skipUrlSync": false, 1938 | "type": "constant" 1939 | }, 1940 | { 1941 | "description": "B12 Hydro Water Reservoir CO2g/kWh", 1942 | "hide": 2, 1943 | "name": "hydrores", 1944 | "query": "23", 1945 | "skipUrlSync": false, 1946 | "type": "constant" 1947 | } 1948 | ] 1949 | }, 1950 | "time": { 1951 | "from": "now-5m", 1952 | "to": "now" 1953 | }, 1954 | "timepicker": {}, 1955 | "timezone": "browser", 1956 | "title": "CaaS Carbon Dashboard", 1957 | "uid": "NhnWODJ4zIBM", 1958 | "version": 30, 1959 | "weekStart": "" 1960 | } 1961 | --------------------------------------------------------------------------------