Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion api/core/workflows_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from features.workflows.core.models import ChangeRequest
from users.models import FFAdminUser

logger = structlog.get_logger()
logger = structlog.get_logger("workflows")


class ChangeRequestCommitService:
Expand All @@ -34,6 +34,15 @@ def commit(self, committed_by: "FFAdminUser") -> None:

self.change_request.committed_at = timezone.now()
self.change_request.committed_by = committed_by

if environment := self.change_request.environment:
logger.info(
"change_request.committed",
organisation__id=environment.project.organisation_id,
environment__id=environment.id,
feature_states__count=self.change_request.feature_states.count(),
)

self.change_request.save()

def _publish_feature_states(self) -> None:
Expand Down
8 changes: 8 additions & 0 deletions api/integrations/github/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from urllib.parse import urlparse

import requests
import structlog
from django.conf import settings
from django.db.utils import IntegrityError
from rest_framework import status, viewsets
Expand Down Expand Up @@ -54,6 +55,7 @@
from projects.code_references.services import get_code_references_for_feature_flag

logger = logging.getLogger(__name__)
code_references_logger = structlog.get_logger("code_references")


def github_auth_required(func): # type: ignore[no-untyped-def]
Expand Down Expand Up @@ -383,6 +385,12 @@ def create_cleanup_issue(request, organisation_pk: int) -> Response: # type: ig
except IntegrityError:
pass

code_references_logger.info(
"cleanup_issues.created",
organisation__id=organisation_pk,
issues_created__count=len(summaries),
)

return Response(status=status.HTTP_204_NO_CONTENT)


Expand Down
12 changes: 11 additions & 1 deletion api/projects/code_references/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Any

import structlog
from django.shortcuts import get_object_or_404
from drf_spectacular.utils import extend_schema
from rest_framework import generics, response
Expand All @@ -19,6 +20,8 @@
FeatureFlagCodeReferencesRepositorySummary,
)

logger = structlog.get_logger("code_references")


class FeatureFlagCodeReferencesScanCreateAPIView(
generics.CreateAPIView[FeatureFlagCodeReferencesScan]
Expand All @@ -33,7 +36,14 @@ class FeatureFlagCodeReferencesScanCreateAPIView(
def perform_create( # type: ignore[override]
self, serializer: FeatureFlagCodeReferencesScanSerializer
) -> None:
serializer.save(project_id=self.kwargs["project_pk"])
instance = serializer.save(project_id=self.kwargs["project_pk"])
feature_names = {ref["feature_name"] for ref in instance.code_references}
logger.info(
"scan.created",
organisation__id=instance.project.organisation_id,
code_references__count=len(instance.code_references),
feature__count=len(feature_names),
)


@extend_schema(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from flag_engine.segments.constants import EQUAL, PERCENTAGE_SPLIT
from freezegun.api import FrozenDateTimeFactory
from pytest_mock import MockerFixture
from pytest_structlog import StructuredLogCapture

from audit.constants import (
CHANGE_REQUEST_APPROVED_MESSAGE,
Expand Down Expand Up @@ -172,6 +173,28 @@ def test_change_request_commit__not_scheduled__sets_committed_at_and_version( #
assert change_request_no_required_approvals.feature_states.first().live_from == now


def test_change_request_commit__valid_request__emits_structlog_event(
change_request_no_required_approvals: ChangeRequest,
log: StructuredLogCapture,
) -> None:
# Given
user = FFAdminUser.objects.create(email="committer@example.com")

# When
change_request_no_required_approvals.commit(committed_by=user)

# Then
environment = change_request_no_required_approvals.environment
assert environment is not None
assert {
"event": "change_request.committed",
"level": "info",
"organisation__id": environment.project.organisation_id,
"environment__id": environment.id,
"feature_states__count": change_request_no_required_approvals.feature_states.count(),
} in log.events


def test_change_request_create__valid_environment__creates_audit_log( # type: ignore[no-untyped-def]
environment, admin_user
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import responses
from pytest_django.fixtures import SettingsWrapper
from pytest_mock import MockerFixture
from pytest_structlog import StructuredLogCapture
from rest_framework import status
from rest_framework.test import APIClient

Expand Down Expand Up @@ -78,6 +79,7 @@ def test_create_cleanup_issue__valid_request__returns_204(
admin_client_new: APIClient,
organisation: Organisation,
feature: Feature,
log: StructuredLogCapture,
) -> None:
# Given
github_issue_response_1: dict[str, Any] = {
Expand Down Expand Up @@ -135,6 +137,15 @@ def test_create_cleanup_issue__valid_request__returns_204(
request_body_2 = json.loads(responses.calls[1].request.body)
assert "lib/flags.py#L7" in request_body_2["body"]

assert log.events == [
{
"event": "cleanup_issues.created",
"level": "info",
"organisation__id": organisation.id,
"issues_created__count": 2,
},
]


@responses.activate
@pytest.mark.usefixtures("set_github_pat", "mock_code_references")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import freezegun
from pytest_structlog import StructuredLogCapture
from rest_framework.test import APIClient

from features.models import Feature
Expand All @@ -10,6 +11,7 @@
def test_create_code_reference__valid_payload__returns_201_with_accepted_references(
admin_client_new: APIClient,
project: Project,
log: StructuredLogCapture,
) -> None:
# Given / When
response = admin_client_new.post(
Expand Down Expand Up @@ -63,6 +65,16 @@ def test_create_code_reference__valid_payload__returns_201_with_accepted_referen
},
]

assert log.events == [
{
"event": "scan.created",
"level": "info",
"organisation__id": project.organisation_id,
"code_references__count": 3,
"feature__count": 2,
},
]


def test_create_code_reference__not_authenticated__returns_401(
client: APIClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@
{
"name": "LOG_LEVEL",
"value": "INFO"
},
{
"name": "LOG_FORMAT",
"value": "json"
}
],
"secrets": [
Expand Down
Loading