diff --git a/CODEOWNERS b/CODEOWNERS index 69caaa040b16..79c4d1ffd786 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -6,3 +6,6 @@ /frontend/ @flagsmith/flagsmith-front-end /infrastructure/ @flagsmith/flagsmith-infrastructure /docs/ @flagsmith/flagsmith-docs + +# Specific rules based on file +/docs/docs/deployment-self-hosting/observability/_events-catalogue.md @flagsmith/flagsmith-product diff --git a/api/Makefile b/api/Makefile index d3748d0f1936..432e019d8b4e 100644 --- a/api/Makefile +++ b/api/Makefile @@ -164,7 +164,8 @@ integrate-private-tests: .PHONY: generate-docs generate-docs: generate-flagsmith-sdk-openapi - poetry run flagsmith docgen metrics > ../docs/docs/administration-and-security/platform-configuration/metrics.md + poetry run flagsmith docgen metrics > ../docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md + poetry run flagsmith docgen events > ../docs/docs/deployment-self-hosting/observability/_events-catalogue.md .PHONY: add-known-sdk-version add-known-sdk-version: diff --git a/api/README.md b/api/README.md index 0d710878ef7b..d418636a4dfe 100644 --- a/api/README.md +++ b/api/README.md @@ -35,7 +35,7 @@ We use the Given When Then structure in all our tests. ### Code guidelines: metrics -Flagsmith's backend exports Prometheus metrics. When planning a feature, consider which metrics should cover it — counters for domain events, histograms for latency or sizes, gauges for cardinalities. See [documentation for existing metrics](../docs/docs/administration-and-security/platform-configuration/metrics.md). Metrics code is hosted in `metrics.py` modules. +Flagsmith's backend exports Prometheus metrics. When planning a feature, consider which metrics should cover it — counters for domain events, histograms for latency or sizes, gauges for cardinalities. See [documentation for existing metrics](https://docs.flagsmith.com/deployment-self-hosting/observability/metrics). Metrics code is hosted in `metrics.py` modules. Name metrics `flagsmith_{domain}_{entity}_{unit}` and give them a comprehensive description. diff --git a/api/poetry.lock b/api/poetry.lock index caf301439f5b..a10b9de29e30 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -2055,14 +2055,14 @@ resolved_reference = "b7fa1f42c333b443763548ea1fe0054f07cdf641" [[package]] name = "flagsmith-common" -version = "3.7.0" +version = "3.8.2" description = "Flagsmith's common library" optional = false python-versions = "<4.0,>=3.11" groups = ["main", "dev", "licensing", "workflows"] files = [ - {file = "flagsmith_common-3.7.0-py3-none-any.whl", hash = "sha256:96013812c926df779f9f960759d15607cb724656a1ccd921b923887774aa8f1b"}, - {file = "flagsmith_common-3.7.0.tar.gz", hash = "sha256:b0a87ba4d4039970b4aedb8baa207f970cf48514386be6b3874961803980b56d"}, + {file = "flagsmith_common-3.8.2-py3-none-any.whl", hash = "sha256:4b1921ec874da52ce7dfa8a248677153a57bda5e607be892f5b5c9dddcbf5c73"}, + {file = "flagsmith_common-3.8.2.tar.gz", hash = "sha256:0612a14858c0e56f5d51dba6be9e4b1f82741b17aced24367a7ad6bccba3d7a8"}, ] [package.dependencies] @@ -6022,4 +6022,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">3.11,<3.14" -content-hash = "ae5e279244c9c4b4e8eeff86d7c62cf7559501c3c2317969eb5e28ead8a14153" +content-hash = "3887d5db2a2c09afcc53b6bdda606a15226230b49c0e1712346099b7a3a71d52" diff --git a/api/pyproject.toml b/api/pyproject.toml index 7e3d676f2dfe..91a41d6d1a2e 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -178,7 +178,7 @@ pygithub = "~2.8" hubspot-api-client = "^12.0.0" djangorestframework-dataclasses = "^1.3.1" pyotp = "^2.9.0" -flagsmith-common = { version = ">=3.5.0,<4", extras = [ +flagsmith-common = { version = ">=3.8.2,<4", extras = [ "common-core", "flagsmith-schemas", "task-processor", diff --git a/docs/docs/administration-and-security/index.mdx b/docs/docs/administration-and-security/index.mdx index 1a2243e49035..65beff5d9296 100644 --- a/docs/docs/administration-and-security/index.mdx +++ b/docs/docs/administration-and-security/index.mdx @@ -149,7 +149,7 @@ Configure environment-specific settings and platform-wide options for your Flags
System monitoring and performance metrics
diff --git a/docs/docs/deployment-self-hosting/core-configuration/environment-variables.md b/docs/docs/deployment-self-hosting/core-configuration/environment-variables.md index d8f0ba0ebef5..c6e56f008b45 100644 --- a/docs/docs/deployment-self-hosting/core-configuration/environment-variables.md +++ b/docs/docs/deployment-self-hosting/core-configuration/environment-variables.md @@ -53,7 +53,7 @@ relevant section below for more details. - `PREVENT_SIGNUP`: Determines whether to prevent new signups. - `ENABLE_EMAIL_ACTIVATION`: New user registration will go via email activation flow, default False. - `OTEL_EXPORTER_OTLP_ENDPOINT`: Base OTLP/HTTP endpoint (e.g. `http://collector:4318`). If unset, OTel is disabled. See - [OpenTelemetry](/deployment-self-hosting/scaling-and-performance/opentelemetry). + [OpenTelemetry](/deployment-self-hosting/observability/opentelemetry). - `OTEL_SERVICE_NAME`: The `service.name` resource attribute attached to all OTel telemetry. Defaults to `flagsmith-api`. - `OTEL_TRACING_EXCLUDED_URL_PATHS`: Comma-separated URL paths to exclude from OTel tracing (e.g. diff --git a/docs/docs/deployment-self-hosting/index.md b/docs/docs/deployment-self-hosting/index.md index 952db1dd7eea..9eb217187e51 100644 --- a/docs/docs/deployment-self-hosting/index.md +++ b/docs/docs/deployment-self-hosting/index.md @@ -50,11 +50,19 @@ Once deployed, you'll need to configure your Flagsmith instance: As your usage grows, you'll need to consider scaling and performance: - **[Sizing and Scaling](/deployment-self-hosting/scaling-and-performance/sizing-and-scaling)**: Understand resource requirements and scaling strategies -- **[Monitoring](/deployment-self-hosting/scaling-and-performance/monitoring)**: Set up monitoring and alerting for your deployment - **[Asynchronous Task Processor](/deployment-self-hosting/scaling-and-performance/asynchronous-task-processor)**: Configure background task processing - **[Using InfluxDB for Analytics](/deployment-self-hosting/scaling-and-performance/using-influxdb-for-analytics)**: Set up analytics storage - **[Load Testing](/deployment-self-hosting/scaling-and-performance/load-testing)**: Test your deployment under load +## Observability + +Monitor the health and behaviour of your deployment: + +- **[Monitoring](/deployment-self-hosting/observability/monitoring)**: Set up monitoring and alerting +- **[Metrics](/deployment-self-hosting/observability/metrics)**: Prometheus metrics exported by the backend +- **[Events](/deployment-self-hosting/observability/events)**: Structured events emitted by the backend +- **[OpenTelemetry](/deployment-self-hosting/observability/opentelemetry)**: Export traces and logs via OTLP + ## Administration and Maintenance Ongoing administration tasks to keep your deployment running smoothly: diff --git a/docs/docs/deployment-self-hosting/observability/_category_.json b/docs/docs/deployment-self-hosting/observability/_category_.json new file mode 100644 index 000000000000..28bba6dc0db8 --- /dev/null +++ b/docs/docs/deployment-self-hosting/observability/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Observability", + "position": 6, + "collapsed": true +} diff --git a/docs/docs/deployment-self-hosting/observability/_events-catalogue.md b/docs/docs/deployment-self-hosting/observability/_events-catalogue.md new file mode 100644 index 000000000000..6b10112bd465 --- /dev/null +++ b/docs/docs/deployment-self-hosting/observability/_events-catalogue.md @@ -0,0 +1,232 @@ + +### `app_analytics.no_analytics_database_configured` + +Logged at `warning` from: + - `api/app_analytics/analytics_db_service.py:74` + - `api/app_analytics/analytics_db_service.py:210` + +Attributes: + - `details` + +### `code_references.cleanup_issues.created` + +Logged at `info` from: + - `api/integrations/github/views.py:388` + +Attributes: + - `issues_created.count` + - `organisation.id` + +### `code_references.scan.created` + +Logged at `info` from: + - `api/projects/code_references/views.py:41` + +Attributes: + - `code_references.count` + - `feature.count` + - `organisation.id` + +### `dynamodb.environment_document_compressed` + +Logged at `info` from: + - `api/environments/dynamodb/wrappers/environment_wrapper.py:92` + +Attributes: + - `environment_api_key` + - `environment_id` + +### `feature_health.feature_health_event_dismissal_not_supported` + +Logged at `warning` from: + - `api/features/feature_health/services.py:127` + +Attributes: + - `feature_health_event_external_id` + - `feature_health_event_id` + - `feature_health_event_type` + - `provider_name` + +### `feature_health.feature_health_provider_error` + +Logged at `error` from: + - `api/features/feature_health/services.py:50` + +Attributes: + - `exc_info` + - `provider_id` + - `provider_name` + +### `feature_health.invalid_feature_health_webhook_path_requested` + +Logged at `warning` from: + - `api/features/feature_health/providers/services.py:30` + +Attributes: + - `path` + +### `gitlab.api_call_failed` + +Logged at `error` from: + - `api/integrations/gitlab/views/browse_gitlab.py:58` + +Attributes: + - `exc_info` + +### `gitlab.configuration_created` + +Logged at `info` from: + - `api/integrations/gitlab/views/configuration.py:26` + +Attributes: + - `gitlab_instance_url` + - `organisation.id` + - `project.id` + +### `gitlab.configuration_updated` + +Logged at `info` from: + - `api/integrations/gitlab/views/configuration.py:34` + +Attributes: + - `gitlab_instance_url` + - `organisation.id` + - `project.id` + +### `gitlab.issues_fetched` + +Logged at `info` from: + - `api/integrations/gitlab/views/browse_gitlab.py:133` + +Attributes: + - `gitlab_project_id` + - `project.id` + +### `gitlab.merge_requests_fetched` + +Logged at `info` from: + - `api/integrations/gitlab/views/browse_gitlab.py:159` + +Attributes: + - `gitlab_project_id` + - `project.id` + +### `gitlab.projects_fetched` + +Logged at `info` from: + - `api/integrations/gitlab/views/browse_gitlab.py:108` + +Attributes: + - `project.id` + +### `launch_darkly.import_failed` + +Logged at `exception` from: + - `api/integrations/launch_darkly/tasks.py:36` + +Attributes: + - `import_request_id` + - `ld_project_key` + - `organisation_id` + - `project_id` + +### `launch_darkly.import_rate_limit_reached` + +Logged at `warning` from: + - `api/integrations/launch_darkly/tasks.py:26` + +Attributes: + - `error_message` + - `import_request_id` + - `ld_project_key` + - `organisation_id` + - `project_id` + - `retry_at` + +### `platform_hub.no_analytics_database_configured` + +Logged at `warning` from: + - `api/platform_hub/services.py:116` + - `api/platform_hub/services.py:206` + - `api/platform_hub/services.py:428` + +Attributes: + +### `segments.serializers.segment_revision_created` + +Logged at `info` from: + - `api/segments/serializers.py:141` + +Attributes: + - `revision_id` + - `segment_id` + +### `sentry_change_tracking.integration_error` + +Logged at `warning` from: + - `api/integrations/sentry/change_tracking.py:112` + +Attributes: + - `feature_name` + - `sentry_action` + - `sentry_response_body` + - `sentry_response_status` + +### `sentry_change_tracking.request_failure` + +Logged at `warning` from: + - `api/integrations/sentry/change_tracking.py:102` + +Attributes: + - `error` + - `feature_name` + - `sentry_action` + +### `sentry_change_tracking.sending` + +Logged at `debug` from: + - `api/integrations/sentry/change_tracking.py:87` + +Attributes: + - `feature_name` + - `headers` + - `payload` + - `sentry_action` + - `url` + +### `sentry_change_tracking.success` + +Logged at `info` from: + - `api/integrations/sentry/change_tracking.py:109` + +Attributes: + - `feature_name` + - `sentry_action` + +### `workflows.change_request.committed` + +Logged at `info` from: + - `api/core/workflows_services.py:39` + +Attributes: + - `environment.id` + - `feature_states.count` + - `organisation.id` + +### `workflows.missing_live_segment` + +Logged at `warning` from: + - `api/core/workflows_services.py:114` + +Attributes: + - `draft_segment` + +### `workflows.segment_revision_created` + +Logged at `info` from: + - `api/core/workflows_services.py:119` + +Attributes: + - `revision_id` + - `segment_id` + diff --git a/docs/docs/administration-and-security/platform-configuration/metrics.md b/docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md similarity index 84% rename from docs/docs/administration-and-security/platform-configuration/metrics.md rename to docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md index 2055304b7fe5..6cae297b29e4 100644 --- a/docs/docs/administration-and-security/platform-configuration/metrics.md +++ b/docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md @@ -1,17 +1,3 @@ ---- -title: Metrics -sidebar_label: Metrics -sidebar_position: 20 ---- - -## Prometheus - -To enable the Prometheus `/metrics` endpoint, set the `PROMETHEUS_ENABLED` environment variable to `true`. - -When enabled, Flagsmith serves the `/metrics` endpoint on port 9100. - -The metrics provided by Flagsmith are described below. - ### `flagsmith_build_info` diff --git a/docs/docs/deployment-self-hosting/observability/events.mdx b/docs/docs/deployment-self-hosting/observability/events.mdx new file mode 100644 index 000000000000..62ade0c12383 --- /dev/null +++ b/docs/docs/deployment-self-hosting/observability/events.mdx @@ -0,0 +1,15 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 40 +--- + +import EventCatalogue from './_events-catalogue.md'; + +Flagsmith backend emits [OpenTelemetry events](https://opentelemetry.io/docs/specs/otel/logs/data-model/#events) +that can be ingested to downstream observability systems and/or a data warehouse of your choice via OTLP. +To learn how to configure this, see [OpenTelemetry](/deployment-self-hosting/observability/opentelemetry). + +## Event catalogue + +