grokify / commonchat

CommonChat is an idealized message format with conversion to chat systems such as Glip and Slack.
MIT License
8 stars 2 forks source link

Grafana's Slack webhooks can't be parsed #3

Closed ylecuyer closed 1 year ago

ylecuyer commented 2 years ago

Hello John,

We faced an error when we tried to connect Grafana slack webhooks to Glip:

json: cannot unmarshal number into Go struct field Field.attachments.fields.value of type string

Here is an example Grafana payload:

{
    "attachments": [
        {
            "color": "#D63232",
            "fallback": "[Alerting] TEST",
            "fields": [
                {
                    "short": true,
                    "title": "server $tag_name replication_lag",
                    "value": 0
                },
                {
                    "short": true,
                    "title": "server $tag_name replication_lag",
                    "value": 0
                },
                {
                    "short": true,
                    "title": "server $tag_name replication_lag",
                    "value": 0
                },
                {
                    "short": true,
                    "title": "server $tag_name replication_lag",
                    "value": 0
                },
                {
                    "short": true,
                    "title": "server $tag_name replication_lag",
                    "value": 0
                },
                {
                    "short": true,
                    "title": "server $tag_name replication_lag",
                    "value": 0
                }
            ],
            "footer": "Grafana v8",
            "footer_icon": "https://grafana.com/assets/img/fav32.png",
            "text": "",
            "title": "[Alerting] TEST",
            "title_link": "https://grafana/",
            "ts": 1643390857
        }
    ],
    "channel": ""
}

As you can see value is an int and not a string as expected.

This probably could be fixed by being more flexible on the expected values:

type Flexval struct {
  Value string `json:value,omitempty`
}

func (flexval *Flexval) UnmarshalJSON(msg []byte) error {
  var f interface{}

  err := json.Unmarshal(msg, &f)
  if (err != nil) {
    panic(err)
  }

  str, ok := f.(string)

  if ok {
    flexval.Value = str
  }

  fl, ok := f.(float64)

  if ok {
    flexval.Value = fmt.Sprintf("%g", fl)
  }

  return nil;
}

type Field struct {
       Title string    `json:"title,omitempty"`
       FlexVal Flexval `json:"value,omitempty"`
       Short bool      `json:"short,omitempty"`
 }

WDYT?

grokify commented 1 year ago

Hi Yoann @ylecuyer Thanks for the issue, test case, and proposal! :+1:

This has been resolved in 0bdecd54c0154de54aa7a1b1a0854a2be10c265e with test cases including the one above.

The solution used is very similar to yours but implemented with a generic String tolerant reder type:

github.com/grokify/mogo/encoding/jsonutil.String.

This is inline with other existing tolerant reader types for jsonutil.Bool and jsonutil.Int64.

This has been released in v0.3.7 and in Chathooks v0.8.8.