Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement custom trigger for webhooks #9879

Merged
merged 21 commits into from
Sep 9, 2024
Merged

Conversation

gt2345
Copy link
Contributor

@gt2345 gt2345 commented Aug 29, 2024

Ticket

MD-480

Description

Part of workload alerting project.
ERD link: https://hpe-aiatscale.atlassian.net/wiki/spaces/ENGINEERIN/pages/1666809868/Workload+Alerting+ERD

Implement trigger type CUSTOM for webhook.

Test Plan

Create a webhook with custom trigger, note that for custom trigger, the mode of webhook can only be Specific.
Within the same workspace as the webhook, create an experiment with config including

integrations:
  webhooks:
    webhook_name:
      - the_name_of_custom_webhook

In the experiment code, trigger the webhook as

with det.core.init() as core_context:
    core_context.alert(title="some content", level="debug")

Verify that the webhook is triggered.

Checklist

  • Changes have been manually QA'd
  • New features have been approved by the corresponding PM
  • User-facing API changes have the "User-facing API Change" label
  • Release notes have been added as a separate file under docs/release-notes/
    See Release Note for details.
  • Licenses have been included for new code which was copied and/or modified from any external code

@cla-bot cla-bot bot added the cla-signed label Aug 29, 2024
Copy link

codecov bot commented Aug 29, 2024

Codecov Report

Attention: Patch coverage is 3.34928% with 202 lines in your changes missing coverage. Please review.

Project coverage is 54.61%. Comparing base (036477b) to head (f72241e).
Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
master/internal/webhooks/postgres_webhook.go 4.23% 113 Missing ⚠️
webui/react/src/components/WebhookCreateModal.tsx 0.00% 43 Missing ⚠️
master/internal/webhooks/api_webhook.go 0.00% 21 Missing ⚠️
harness/determined/core/_context.py 12.50% 14 Missing ⚠️
webui/react/src/pages/WebhookList.tsx 0.00% 7 Missing ⚠️
master/internal/webhooks/webhook.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9879      +/-   ##
==========================================
- Coverage   54.67%   54.61%   -0.07%     
==========================================
  Files        1263     1263              
  Lines      156862   157047     +185     
  Branches     3597     3598       +1     
==========================================
+ Hits        85768    85769       +1     
- Misses      70963    71147     +184     
  Partials      131      131              
Flag Coverage Δ
backend 45.08% <3.49%> (-0.12%) ⬇️
harness 72.58% <12.50%> (-0.04%) ⬇️
web 54.40% <0.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
master/internal/webhooks/webhook.go 12.00% <0.00%> (-0.50%) ⬇️
webui/react/src/pages/WebhookList.tsx 0.00% <0.00%> (ø)
harness/determined/core/_context.py 53.04% <12.50%> (-4.67%) ⬇️
master/internal/webhooks/api_webhook.go 0.00% <0.00%> (ø)
webui/react/src/components/WebhookCreateModal.tsx 0.00% <0.00%> (ø)
master/internal/webhooks/postgres_webhook.go 48.70% <4.23%> (-11.94%) ⬇️

... and 4 files with indirect coverage changes

Copy link

netlify bot commented Aug 29, 2024

Deploy Preview for determined-ui canceled.

Name Link
🔨 Latest commit f72241e
🔍 Latest deploy log https://app.netlify.com/sites/determined-ui/deploys/66db3c5625106600081cb6a8

@gt2345 gt2345 marked this pull request as ready for review September 3, 2024 15:53
@gt2345 gt2345 requested review from a team as code owners September 3, 2024 15:53
Copy link
Contributor

@johnkim-det johnkim-det left a comment

Choose a reason for hiding this comment

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

some suggestions but otherwise web LGTM. would be nice to have unit testing but won't block on it.

Comment on lines 166 to 171
useEffect(() => {
if ((triggers || []).includes(V1TriggerType.CUSTOM)) {
form.setFieldValue('mode', V1WebhookMode.SPECIFIC);
}
}, [triggers, form]);

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: consolidate with existing useEffect and/or move to onChange?

name="mode"
rules={[{ message: 'Webhook mode is required', required: true }]}>
<Select
disabled={(triggers || []).includes(V1TriggerType.CUSTOM)}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: don't think || [] throughout the file is necessary?

if (t.triggerType === V1TriggerType.CUSTOM) {
return (
<li className={css.listBadge} key={t.id}>
<Badge>CUSTOM</Badge>
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: could use labels from triggerOptions in WebhookCreateModal?


// Event data for custom trigger.
message CustomWebhookEventData {
// The level for the event data.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// The level for the event data.
// The level at which the event data is logged.

if t.TriggerType == webhookv1.TriggerType_TRIGGER_TYPE_CUSTOM {
if req.Webhook.Mode != webhookv1.WebhookMode_WEBHOOK_MODE_SPECIFIC {
return nil, status.Errorf(codes.InvalidArgument,
"custom trigger only works on webhook with mode 'SPECIFIC' got %v",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"custom trigger only works on webhook with mode 'SPECIFIC' got %v",
"custom trigger only works on webhook with mode 'SPECIFIC'. Got %v",

type CustomTriggerData struct {
Title string `json:"title"`
Description string `json:"description"`
Level string `json:"level"`
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Should we keep the CustomWebhookEventData fields in the same order as this CustomTriggerData?
Just so it's clear what the most important field(s) are (which is presumably the Title field)

// Event data for custom trigger.
message CustomWebhookEventData {
// The level for the event data.
determined.log.v1.LogLevel level = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we make this log_level?

Suggested change
determined.log.v1.LogLevel level = 1;
determined.log.v1.LogLevel log_level = 1;


activeConfig, err := expconf.ParseAnyExperimentConfigYAML(m.ConfigBytes)
if err != nil {
return fmt.Errorf("error parsing experiment config : %w", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return fmt.Errorf("error parsing experiment config : %w", err)
return fmt.Errorf("error parsing experiment config: %w", err)

@@ -223,3 +230,29 @@ func (a *WebhooksAPIServer) TestWebhook(
}
return &apiv1.TestWebhookResponse{}, nil
}

// PostWebhookEventData handles data for custom trigger.
func (a *WebhooksAPIServer) PostWebhookEventData(
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we maybe add a couple of integration tests for this function?

Copy link
Contributor Author

@gt2345 gt2345 Sep 4, 2024

Choose a reason for hiding this comment

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

e2e tests for this function were accidentally dropped during a merge, now they should be restored

@@ -359,6 +390,7 @@ def init(
_metrics=metrics,
_tensorboard_manager=tensorboard_manager,
_session=session,
info=info,
Copy link
Contributor

@jgongd jgongd Sep 5, 2024

Choose a reason for hiding this comment

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

Just for my understanding, why do we need info now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because we want to access the experiment id and trial id in alert function

err = generateEventForCustomTrigger(
ctx, &es, webhook.Triggers, webhook.WebhookType, webhook.URL, m.Experiment, activeConfig, data, trialID)
if err != nil {
return fmt.Errorf("error genrating event %d %+v: %w", webhookID, webhook, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return fmt.Errorf("error genrating event %d %+v: %w", webhookID, webhook, err)
return fmt.Errorf("error genrating event for webhook with ID %d %+v: %w", webhookID, webhook, err)

}

var es []Event
if webhookConfig.WebhookID != nil {
Copy link
Contributor

@jgongd jgongd Sep 5, 2024

Choose a reason for hiding this comment

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

(not a blocker)From the user perspective, since they can provide a list of webhook ids, where can a user find out the id of a webhook?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since webhook is not part of the CLI, user can only access the webhook ids from REST api. This is alright to me because we want to encourage user to use webhook name for readability, and using id is more like an add-on.

}

if _, err := db.Bun().NewInsert().Model(&es).Exec(ctx); err != nil {
return fmt.Errorf("report experiment state changed inserting event trigger: %w", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

would the error message be something like handle custom trigger data inserting events?

Comment on lines +386 to +387
Where("name = ?", webhookName).
Where("workspace_id = ?", workspaceID).
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice, this makes sure only one webhook is selected if there are multiple webhooks with the same names but different url.

mStatus = string(e.State)
}

endTime := time.Now()
Copy link
Contributor

Choose a reason for hiding this comment

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

Why we need to set endTime to time.Now()?

Copy link
Contributor

Choose a reason for hiding this comment

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

I could be wrong but it seems like endTime is only used here to set the experiment duration in expBlockFields, so if it hasn't completed yet (endTime == nil), then we can get the duration from start time up until the present!

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah thanks! That calculates the experiment duration for a Slack message.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exactly, thanks @amandavialva01

Copy link
Contributor

@jgongd jgongd left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@amandavialva01 amandavialva01 left a comment

Choose a reason for hiding this comment

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

LGTM! Awesome work with this 😆

@gt2345 gt2345 merged commit bfeb418 into main Sep 9, 2024
83 of 97 checks passed
@gt2345 gt2345 deleted the gt/480-custom-trigger branch September 9, 2024 01:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants