target / goalert

Open source on-call scheduling, automated escalations, and notifications so you never miss a critical alert
https://goalert.me
Apache License 2.0
2.19k stars 230 forks source link

Add Metadata to Alerts for Traceability and Integration #3653

Open mastercactapus opened 5 months ago

mastercactapus commented 5 months ago

What problem would you like to solve? Please describe: Difficulties in tracing and integrating with other systems due to the lack of ability to associate arbitrary metadata with an alert upon its creation and retrieval.

Describe the solution you'd like:

Example of the Graphql input and struct formats:

input AlertMetadataInput {
  key: String!
  value: String!
}

input CreateAlertInput {
  // ...
  meta: [AlertMetadataInput!]
}

type AlertMetadata {
  key: String!
  value: String!
}

type Alert {
  // ...
  meta: [AlertMetadata!]
}
type AlertMetaValue struct {
    Key string `json:"key"`
    Value string `json:"value"`
}

const TypeAlertMetaV1 = "alert_meta_v1"

type AlertMeta struct {
    Type string `json:"type"`
    AlertMetaV1 []AlertMetaValue `alert_meta_v1`
}

Additional context: This feature can enhance the handling of alerts to make them compatible with query parameters as well as GraphQL.

Forfold commented 5 months ago

@mastercactapus What do you envision Type string being within the AlertMeta struct?

mastercactapus commented 5 months ago

@Forfold That struct is specifically what's going to Postgres -- the idea is to have type/version info embedded in it so we have something to key off of in any migrations/changes we need to make down the line.

It wouldn't be included in any of the API/external stuff, just internal

Forfold commented 5 months ago

@mastercactapus Gotcha, so the external integration wouldn't ever see this value, as it would be a hardcoded string set in the function at time of insert/update?

mastercactapus commented 5 months ago

@Forfold yep, exactly. Not only that, but the alert.Store method shouldn't even expose it, it's just to ensure integrity within the store method to the DB (since things change over time).

mastercactapus commented 5 months ago

Also, a nice addition would be adding a metaValue(key: string): string field to Alert in the GraphQL schema. It would play nice with GraphQL, allowing mapping (potentially multiple) metadata fields in the return structure, for example:

alert(id: 123) {
  id
  myData: metaValue(key: "my_data_v1")
}

would return:

{"data": {
  "alert": {
    "id": 123,
    "myData": "some value"
  }
}}

(thanks @Forfold for helping with this idea!)

mastercactapus commented 5 months ago

For data storage, it may be better to store as a map so that we leave open the possibility to index these (for search) in the future. Part of validation would need to ensure unique keys anyway:

const TypeAlertMetaV1 = "alert_meta_v1"

type AlertMeta struct {
    Type string `json:"type"`
    AlertMetaV1 map[string]string `alert_meta_v1`
}