Skip to content

feat: add forum telemetry for comment create update and delete#244

Merged
santhosh-apphelix-2u merged 1 commit intorelease-ulmofrom
COSMO2-853-comment-write-instrumentation
Apr 21, 2026
Merged

feat: add forum telemetry for comment create update and delete#244
santhosh-apphelix-2u merged 1 commit intorelease-ulmofrom
COSMO2-853-comment-write-instrumentation

Conversation

@santhosh-apphelix-2u
Copy link
Copy Markdown

Implements COSMO2-853 for the comment create, comment update, and comment delete flows in edx-platform.

Adds Datadog forum telemetry for parent and child comment creation, comment updates, and comment deletes, including operation, entity context, actor, course, result, HTTP status, and relevant comment metadata.

Copilot AI review requested due to automatic review settings April 21, 2026 10:40
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Datadog “forum.*” telemetry attributes to the Discussion REST API comment create/update/delete flows to support COSMO2-853 observability needs.

Changes:

  • Instrument CommentViewSet.create, partial_update, and destroy with operation/entity/actor/course/result/error attributes.
  • Add _get_comment_trace_context helper to fetch comment context for request-level telemetry on update/delete.
  • Emit forum.entity_id from create_comment after the comment is persisted.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
lms/djangoapps/discussion/rest_api/views.py Adds telemetry attributes around comment create/update/delete and introduces a helper to fetch comment context.
lms/djangoapps/discussion/rest_api/api.py Records forum.entity_id for newly created comments after serializer save.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1357 to +1376
try:
cc_comment, course_id = _get_comment_trace_context(comment_id)
set_custom_attribute("forum.course_id", str(course_id))
if cc_comment.get("parent_id"):
set_custom_attribute(
"forum.parent_comment_id", str(cc_comment.get("parent_id"))
)

update_fields = [
field
for field, value in request.data.items()
if value is not None and field != "voted"
]
if update_fields:
set_custom_attribute("forum.update_fields", ",".join(update_fields))

if request.content_type != MergePatchParser.media_type:
raise UnsupportedMediaType(request.content_type)

response = Response(update_comment(request, comment_id, request.data))
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

partial_update() pre-fetches the comment/thread via _get_comment_trace_context for telemetry, but update_comment() already retrieves the same entities (via _get_comment_and_context) and builds context. This adds redundant forum service calls for every update. Consider reusing the data from update_comment (e.g., have update_comment return cc_comment/context/course_id, or move telemetry attribute setting into api.update_comment where cc_comment is already available).

Copilot uses AI. Check for mistakes.
def _get_comment_trace_context(comment_id):
"""Retrieve comment context needed for request-level telemetry."""
cc_comment = Comment(id=comment_id).retrieve()
course_id = get_course_id_from_thread_id(cc_comment["thread_id"])
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_get_comment_trace_context makes an extra forum service call by deriving course_id via get_course_id_from_thread_id(thread_id), which retrieves the thread. The comment retrieve response already includes course_id (see Comment.accessible_fields), so this can use cc_comment["course_id"] (with a fallback if needed) to avoid the additional network hop and latency per request.

Suggested change
course_id = get_course_id_from_thread_id(cc_comment["thread_id"])
course_id = cc_comment.get("course_id")
if not course_id:
course_id = get_course_id_from_thread_id(cc_comment["thread_id"])

Copilot uses AI. Check for mistakes.
Comment on lines +1329 to +1334
cc_comment, course_id = _get_comment_trace_context(comment_id)
set_custom_attribute("forum.course_id", str(course_id))
if cc_comment.get("parent_id"):
set_custom_attribute(
"forum.parent_comment_id", str(cc_comment.get("parent_id"))
)
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

destroy() now pre-fetches the comment (and its thread/course) for telemetry via _get_comment_trace_context, but delete_comment() already calls _get_comment_and_context() internally (Comment.retrieve + Thread.retrieve). This duplicates forum service calls (and course access checks) on every delete. Consider restructuring so the telemetry uses the data already fetched in delete_comment (e.g., have delete_comment return the cc_comment/context/course_id, or move the telemetry attribute setting into api.delete_comment where cc_comment is already available).

Suggested change
cc_comment, course_id = _get_comment_trace_context(comment_id)
set_custom_attribute("forum.course_id", str(course_id))
if cc_comment.get("parent_id"):
set_custom_attribute(
"forum.parent_comment_id", str(cc_comment.get("parent_id"))
)

Copilot uses AI. Check for mistakes.
Comment on lines +1312 to +1316
except Exception as exc:
set_custom_attribute("forum.result", "error")
set_custom_attribute("forum.http_status", str(status.HTTP_400_BAD_REQUEST))
set_custom_attribute("forum.error_type", _discussion_error_type(exc))
raise
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the exception handler, forum.http_status is always recorded as 400, but this endpoint can raise exceptions that DRF will render with different status codes (e.g., PermissionDenied=403, UnsupportedMediaType=415, DiscussionBlackOutException=403). For more accurate telemetry, set forum.http_status based on the exception when available (e.g., getattr(exc, "status_code", 500) or mapping ObjectDoesNotExist->404) rather than hard-coding 400.

Copilot uses AI. Check for mistakes.
@santhosh-apphelix-2u santhosh-apphelix-2u merged commit 0c96ca2 into release-ulmo Apr 21, 2026
68 checks passed
@santhosh-apphelix-2u santhosh-apphelix-2u deleted the COSMO2-853-comment-write-instrumentation branch April 21, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants