In v2 versioning environments, every flag change is published via an EnvironmentFeatureVersion, and the resulting audit row uses a fixed template (api/audit/constants.py:64):
ENVIRONMENT_FEATURE_VERSION_PUBLISHED_MESSAGE = "New version published for feature: %s"
That string is the entire log field. Nothing indicates which feature states changed, the enabled/disabled flip, segment overrides touched, or value diffs.
Five integrations consume this row via the AuditLog post_save filter (api/audit/signals.py:118-125, accepting FEATURE, FEATURE_STATE, SEGMENT, EF_VERSION) and render the log text:
- Datadog, New Relic, Slack, Grafana — render
audit_log.log directly
- Dynatrace — same, plus
audited_instance.feature.name for deployment name
v1 produces per-FS rows like Flag state updated: my_flag: Enabled. v2 collapses these into one row per version with no per-FS content.
Proposal:
- Render the EFV message via
get_updated_feature_states_for_version(efv), enumerating each FS's action.
- Optionally expose the change list as structured audit-log metadata so future receivers don't re-parse prose.
In v2 versioning environments, every flag change is published via an
EnvironmentFeatureVersion, and the resulting audit row uses a fixed template (api/audit/constants.py:64):That string is the entire
logfield. Nothing indicates which feature states changed, the enabled/disabled flip, segment overrides touched, or value diffs.Five integrations consume this row via the AuditLog post_save filter (
api/audit/signals.py:118-125, acceptingFEATURE,FEATURE_STATE,SEGMENT,EF_VERSION) and render thelogtext:audit_log.logdirectlyaudited_instance.feature.namefor deployment namev1 produces per-FS rows like
Flag state updated: my_flag: Enabled. v2 collapses these into one row per version with no per-FS content.Proposal:
get_updated_feature_states_for_version(efv), enumerating each FS's action.