From 9021bbd5dee1dc3fe69ee9d8c2ca98bc388445a6 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jul 2020 17:43:10 +0200 Subject: [PATCH 1/6] root: implement APM support --- Pipfile | 2 ++ Pipfile.lock | 51 +++++++++++++++++++++++++++- passbook/flows/planner.py | 3 ++ passbook/lib/expression/evaluator.py | 2 ++ passbook/policies/engine.py | 2 ++ passbook/policies/process.py | 2 ++ 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index cad4fd1b6..12a44fddc 100644 --- a/Pipfile +++ b/Pipfile @@ -41,6 +41,8 @@ structlog = "*" swagger-spec-validator = "*" urllib3 = {extras = ["secure"],version = "*"} facebook-sdk = "*" +elastic-apm = "*" +psutil = "*" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index 340513777..35448f896 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "fd0192b73c01aaffb90716ce7b6d4e5be9adb8788d3ebd58e54ccd6f85d9b71b" + "sha256": "f90d79a67bbd689ca4e7ccbfd528e4ed45078e848c36d84e53ff9c6b2a1e92ed" }, "pipfile-spec": 6, "requires": { @@ -306,6 +306,38 @@ ], "version": "==1.0.0" }, + "elastic-apm": { + "hashes": [ + "sha256:0ffd86d8449d7b63c6053c5032e09abf398c753214a55de8a4e15cb9b56108d1", + "sha256:18006ade25a91a8030b5fcfa825d5c364b13bc5e902b818725341f8c9a00895a", + "sha256:1d8335f94660c246d5475ec3b15452cd0f5b51affb2e1d16eb2fbc36380308a8", + "sha256:25fea9cb6c99efc229b1449d7fbdda76260404cc74abefcc0cc86b3a5102d99d", + "sha256:2841bee5650b736d5ebb199d728a18b415dfed22cb367cd913619a691dfe39e8", + "sha256:301d159933f19115b21f92bc1ff7f0073bfea13ca24c6ff34023c23077a08e44", + "sha256:4eaaebd088315d7ba2726b21fea06279598cad128be073b28c0462049f093d5a", + "sha256:515d027d380df818ec304d4d28121c39069a0d919cb2eb7f8e29019a14d62c2a", + "sha256:5ad2b431298567f642d44826be2c557d9aca5761c0240be23f9a52b66833cc93", + "sha256:5dbf19570bdf97e169b5901913e9a3e271ff5e10d298a608e214802dca8c9065", + "sha256:724ded78cc24d2c7d8bc81642a938d9bfc2dcb8b5bdad1b1da242300f9f4ec73", + "sha256:7e859162f4c187defe26fb00c974a128eee2bd8988cd30ccffdcaaeb56cb2248", + "sha256:9180ed12b9c12cc794f3b57069d1e7b2a04352af02f8d0bc89c9251231f8660e", + "sha256:92f885cc67a9d78e72b174feaa979ddb5188d7cef2b5a7739be740955e07c5ed", + "sha256:976eaaf3825df760946f31b5426544fecc4c32fd66e124565ede7151f8152689", + "sha256:abafeff08ff285cc03c33e822633c6e25a9434174413f72a5032393e9f95a1e0", + "sha256:ad21169ebee7ae35d6c42cd6ac9e7658d6e07bc6a3f34dcc4f0a32e03d736fdc", + "sha256:b2b4ff079a20d620d7f87a345d37cf9b7f2bc1c8cc8c9317fb0c3979371f0d41", + "sha256:b3b72d26104de89124cca965b234b6b67be4604518e168aedcd52c7229c923e9", + "sha256:c4a144ecb0b1570c1f6a285cd6f28f2eda89c0696ed494892e3250bb6fed7909", + "sha256:dc368bbac6401fa0c9d7a35429257190759f4f33099783d9e0557ce12d64ca6c", + "sha256:e28a81802784ea80d21c294a4ab4e47f658a4031caa5c320147925ab62c6a0d4", + "sha256:e7832a5ad503d6cd4a7eaa4cee782ccdf113afa99708e3d005fe9aef539a8222", + "sha256:f2674a3aee0c38df82dedade353c944a2f55b215c7d5b0776e1bb89ce87de57c", + "sha256:f7b37f65c0ca971038f6b69c7581ea762fbc89d9631107babc04c646898686d2", + "sha256:fbd1a68b4cf32298e09652958ec3cf13462a5269408522211cfd3e02b451c3b2" + ], + "index": "pypi", + "version": "==5.8.0" + }, "facebook-sdk": { "hashes": [ "sha256:2e987b3e0f466a6f4ee77b935eb023dba1384134f004a2af21f1cfff7fe0806e", @@ -461,6 +493,23 @@ ], "version": "==0.8.0" }, + "psutil": { + "hashes": [ + "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058", + "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953", + "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4", + "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e", + "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f", + "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38", + "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e", + "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8", + "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26", + "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5", + "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310" + ], + "index": "pypi", + "version": "==5.7.0" + }, "psycopg2-binary": { "hashes": [ "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac", diff --git a/passbook/flows/planner.py b/passbook/flows/planner.py index 64d0f89f4..9e92e889a 100644 --- a/passbook/flows/planner.py +++ b/passbook/flows/planner.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional from django.core.cache import cache from django.http import HttpRequest +from elasticapm import capture_span from structlog import get_logger from passbook.core.models import User @@ -88,6 +89,7 @@ class FlowPlanner: self.allow_empty_flows = False self.flow = flow + @capture_span(name="FlowPlanner", span_type="flow.planner.plan") def plan( self, request: HttpRequest, default_context: Optional[Dict[str, Any]] = None ) -> FlowPlan: @@ -127,6 +129,7 @@ class FlowPlanner: raise EmptyFlowException() return plan + @capture_span(name="FlowPlanner", span_type="flow.planner.build_plan") def _build_plan( self, user: User, diff --git a/passbook/lib/expression/evaluator.py b/passbook/lib/expression/evaluator.py index 3a252f08b..cae4aed90 100644 --- a/passbook/lib/expression/evaluator.py +++ b/passbook/lib/expression/evaluator.py @@ -2,6 +2,7 @@ import re from textwrap import indent from typing import Any, Dict, Iterable, Optional +from elasticapm import capture_span from django.core.exceptions import ValidationError from requests import Session @@ -68,6 +69,7 @@ class BaseEvaluator: full_expression += f"\nresult = handler({handler_signature})" return full_expression + @capture_span(name="BaseEvaluator", span_type="lib.evaluator.evaluate") def evaluate(self, expression_source: str) -> Any: """Parse and evaluate expression. If the syntax is incorrect, a SyntaxError is raised. If any exception is raised during execution, it is raised. diff --git a/passbook/policies/engine.py b/passbook/policies/engine.py index 5db4f8cfc..3671e239f 100644 --- a/passbook/policies/engine.py +++ b/passbook/policies/engine.py @@ -5,6 +5,7 @@ from typing import List, Optional from django.core.cache import cache from django.http import HttpRequest +from elasticapm import capture_span from structlog import get_logger from passbook.core.models import User @@ -69,6 +70,7 @@ class PolicyEngine: if policy.__class__ == Policy: raise TypeError(f"Policy '{policy}' is root type") + @capture_span(name="PolicyEngine", span_type="policy.engine.build") def build(self) -> "PolicyEngine": """Build task group""" for binding in self._iter_bindings(): diff --git a/passbook/policies/process.py b/passbook/policies/process.py index f4af4819e..0c8dbf87b 100644 --- a/passbook/policies/process.py +++ b/passbook/policies/process.py @@ -4,6 +4,7 @@ from multiprocessing.connection import Connection from typing import Optional from django.core.cache import cache +from elasticapm import capture_span from structlog import get_logger from passbook.policies.exceptions import PolicyException @@ -44,6 +45,7 @@ class PolicyProcess(Process): if connection: self.connection = connection + @capture_span(name="PolicyEngine", span_type="policy.process.execute") def execute(self) -> PolicyResult: """Run actual policy, returns result""" LOGGER.debug( From b3b8cd807d560574f653b42e040c786fce318b64 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jul 2020 17:53:35 +0200 Subject: [PATCH 2/6] root: expose APM settings in helm chart --- docs/installation/kubernetes.md | 5 +++++ helm/templates/configmap.yaml | 4 ++++ helm/values.yaml | 5 +++++ passbook/root/settings.py | 13 +++++++++++++ 4 files changed, 27 insertions(+) diff --git a/docs/installation/kubernetes.md b/docs/installation/kubernetes.md index 35882adab..7e47718b2 100644 --- a/docs/installation/kubernetes.md +++ b/docs/installation/kubernetes.md @@ -22,6 +22,11 @@ config: # Log level used by web and worker # Can be either debug, info, warning, error log_level: warning + # Optionally enable Elastic APM Support + apm: + enabled: false + server_url: "" + secret_token: "" # This Helm chart ships with built-in Prometheus ServiceMonitors and Rules. # This requires the CoreOS Prometheus Operator. diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml index c4bd4d71d..313a6c8c5 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmap.yaml @@ -21,3 +21,7 @@ data: message_queue_db: 1 error_reporting: {{ .Values.config.error_reporting }} log_level: "{{ .Values.config.log_level }}" + apm: + enabled: {{ .Values.config.apm.enabled }} + server_url: "{{ .Values.config.apm.server_url }}" + secret_token: "{{ .Values.config.apm.server_token }}" diff --git a/helm/values.yaml b/helm/values.yaml index 937a7fce8..4fb14448d 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -14,6 +14,11 @@ config: # Log level used by web and worker # Can be either debug, info, warning, error log_level: warning + # Optionally enable Elastic APM Support + apm: + enabled: false + server_url: "" + secret_token: "" # This Helm chart ships with built-in Prometheus ServiceMonitors and Rules. # This requires the CoreOS Prometheus Operator. diff --git a/passbook/root/settings.py b/passbook/root/settings.py index 4e7c2b381..149a6ee2c 100644 --- a/passbook/root/settings.py +++ b/passbook/root/settings.py @@ -281,6 +281,19 @@ if not DEBUG and _ERROR_REPORTING: release="passbook@%s" % __version__, ) +_APM_ENABLED = CONFIG.y("apm.enabled", True) +if _APM_ENABLED: + INSTALLED_APPS.append("elasticapm.contrib.django") + ELASTIC_APM = { + "CLOUD_PROVIDER": False, + "DEBUG": DEBUG, + "SERVICE_NAME": "passbook", + "SERVICE_VERSION": __version__, + "SECRET_TOKEN": CONFIG.y("apm.secret_token", ""), + "SERVER_URL": CONFIG.y("apm.secret_token", "http://localhost:8200"), + } + + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.1/howto/static-files/ From 231e448b1a91a677ecd9b7e970bd421f066c47b1 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jul 2020 17:53:35 +0200 Subject: [PATCH 3/6] lib/eval: fix import order --- passbook/lib/expression/evaluator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passbook/lib/expression/evaluator.py b/passbook/lib/expression/evaluator.py index cae4aed90..c8595c9c8 100644 --- a/passbook/lib/expression/evaluator.py +++ b/passbook/lib/expression/evaluator.py @@ -2,9 +2,9 @@ import re from textwrap import indent from typing import Any, Dict, Iterable, Optional -from elasticapm import capture_span from django.core.exceptions import ValidationError +from elasticapm import capture_span from requests import Session from structlog import get_logger From 41117d873deb1813fc5257a19cce4fea1fe98948 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jul 2020 18:23:15 +0200 Subject: [PATCH 4/6] ci: fix gatekeeper building the wrong image --- azure-pipelines.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b0107ddbe..983ae3043 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -194,15 +194,13 @@ stages: pool: vmImage: 'ubuntu-latest' steps: - - task: CmdLine@2 - inputs: - script: cd gatekeeper - task: Docker@2 inputs: containerRegistry: 'dockerhub' repository: 'beryju/passbook-gatekeeper' command: 'buildAndPush' Dockerfile: 'Dockerfile' + buildContext: 'gatekeeper/' tags: 'gh-$(Build.SourceBranchName)' - job: build_static pool: From 0715cac39b242f45565032099086d8d00564a844 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jul 2020 18:24:24 +0200 Subject: [PATCH 5/6] root: remove psutil as we have external monitoring for CPU --- Pipfile | 1 - Pipfile.lock | 17 ----------------- 2 files changed, 18 deletions(-) diff --git a/Pipfile b/Pipfile index 12a44fddc..3243d403a 100644 --- a/Pipfile +++ b/Pipfile @@ -42,7 +42,6 @@ swagger-spec-validator = "*" urllib3 = {extras = ["secure"],version = "*"} facebook-sdk = "*" elastic-apm = "*" -psutil = "*" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index 35448f896..01c830dc4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -493,23 +493,6 @@ ], "version": "==0.8.0" }, - "psutil": { - "hashes": [ - "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058", - "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953", - "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4", - "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e", - "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f", - "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38", - "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e", - "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8", - "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26", - "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5", - "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310" - ], - "index": "pypi", - "version": "==5.7.0" - }, "psycopg2-binary": { "hashes": [ "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac", From beb5ffcbddea59f27ee86d27c8710e7b9094e969 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jul 2020 18:48:24 +0200 Subject: [PATCH 6/6] ci: fix gatekeeper dockerfile path --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 983ae3043..ffa9303f9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -199,7 +199,7 @@ stages: containerRegistry: 'dockerhub' repository: 'beryju/passbook-gatekeeper' command: 'buildAndPush' - Dockerfile: 'Dockerfile' + Dockerfile: 'gatekeeper/Dockerfile' buildContext: 'gatekeeper/' tags: 'gh-$(Build.SourceBranchName)' - job: build_static