「corner width %f too big {o:{%f,%f}, s:{%f,%f}}」のSIGABRTエラー解消法

<!-- 以下本文 -->

# はじめに

menuでは、フロント側のエラートラッキングに Sentry を使用しています。

今回は、その中でも発生回数が多かったエラーの対応方法をご紹介します。


# エラー内容

以下がSentryにあがっていることを報告いただいたので、調査を行いました。

```
SIGABRT
corner width %f too big {o:{%f,%f}, s:{%f,%f}} > corner width 3.500000 too big {o:{0.000000,0.000000}, s:{nan,7.000000}} > corner_width >= 0 && 2 * corner_width <= CGRectGetWidth(rect)
```


# 原因

内容に `nan` とあるように、計算式が間違っていることが原因でした。

アニメーションさせる部分で割合を出している部分があったのですが、分母が0になるパターンが存在したことで、割り切ることができずに発生していた模様です。

```typescript
Animated.timing(animatedValue, {
  toValue: currentCount / baseCount,
  duration: 1000,
  useNativeDriver: false,
}).start();
```


# 修正方法

単純ですが、早期returnで0の場合は計算を行わないようにしました。

```typescript
if (requiredDeliveryCount == 0) {
  return;
}

Animated.timing(animatedValue, {
  toValue: currentCount / baseCount,
  duration: 1000,
  useNativeDriver: false,
}).start();
```

これで問題なく動作することを確認し、リリース後に報告が鳴り止むことを確認できました🎉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962815/b6d49bcb-a4e1-46fa-80e1-5ce9f581e093.png)


# Sentryの監視を自動化する

今回は別のエンジニアにSlackで報告いただいて気がついたのですが、できれば発生回数が多いものは自動で通知してくれると便利ですよね。（Sentryを確認すること自体、習慣化しないといけないですが。。）

SentryはAPIを提供しており、これを利用することでIssueを取得できるようです。

https://docs.sentry.io/api/events/list-a-projects-issues/

認証トークンはこちらで作成しました。

https://sentry.io/settings/account/api/auth-tokens/new-token/

上記のAPIとSlackのAPIと組み合わせて、毎月2回自動でSlackに通知するActionsを作りました！！

#### `notify-sentry-summary-slack.yml`

```yaml
name: Sentry Slack Notify

on:
  workflow_dispatch:
  schedule:
    - cron: '0 1 10 * *'
    - cron: '0 1 25 * *'

jobs:
  notify:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4 

      - name: Install jq tool
        run: |
          sudo apt-get update
          sudo apt-get install jq

      - name: Set script permissions
        run: chmod +x ./.github/script/notify-sentry-summary-slack.sh

      - name: Run script
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN_FOR_API }}
          SLACK_WEBHOOK_URL: ${{ secrets.SENTRY_SUMMARY_SLACK_WEBHOOK_URL }}
        run: ./.github/script/notify-sentry-summary-slack.sh
```

#### `notify-sentry-summary-slack.sh`

```shell
#!/bin/bash

# Sentry APIをcurlで実行し、JSONデータを取得
SENTRY_ISSUES=$(curl -s -H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
    -G "https://sentry.io/api/0/projects/{organization_id_or_slug}/{project_id_or_slug}/issues/" \
    --data-urlencode "statsPeriod=14d" \
    --data-urlencode "environment=production")

# curlコマンドが失敗した場合、処理を中断
if [ $? -ne 0 ]; then
    echo "Error: Failed to fetch Sentry issues."
    exit 1
fi

# jqでJSONデータを解析し、必要な情報を抽出
TOP_5_ISSUES=$(echo "$SENTRY_ISSUES" | jq -c '[.[] | {title: .title, culprit: .culprit, permalink: .permalink, count: (.count | tonumber), userCount: .userCount, firstSeen: .firstSeen, lastSeen: .lastSeen, metadata: .metadata}] | sort_by(-.count)[:5]')

# jqコマンドが失敗した場合、処理を中断
if [ $? -ne 0 ]; then
    echo "Error: Failed to parse Sentry issues."
    exit 1
fi

# Slackのメッセージ形式にデータを整形
SLACK_MESSAGE=":menu2: *ユーザーアプリで発生しているSentryエラー TOP5 (過去2週間)*\n"
SLACK_MESSAGE+="$(date '+%Y-%m-%d') 時点\n"

while IFS= read -r ISSUE; do
    TITLE=$(echo "$ISSUE" | jq -r .title)
    CULPRIT=$(echo "$ISSUE" | jq -r .culprit)
    PERMALINK=$(echo "$ISSUE" | jq -r .permalink)
    COUNT=$(echo "$ISSUE" | jq -r .count)
    USER_COUNT=$(echo "$ISSUE" | jq -r .userCount)
    FIRST_SEEN=$(echo "$ISSUE" | jq -r .firstSeen | cut -d'T' -f1)
    LAST_SEEN=$(echo "$ISSUE" | jq -r .lastSeen | cut -d'T' -f1)

    SLACK_MESSAGE+="<$PERMALINK|$TITLE>\n"
    SLACK_MESSAGE+="発生箇所: \`$CULPRIT\`\n"
    SLACK_MESSAGE+="統計情報:\n"
    SLACK_MESSAGE+="• 発生件数: *$COUNT* \n" 
    SLACK_MESSAGE+="• 影響ユーザー数: *$USER_COUNT* \n"
    SLACK_MESSAGE+="期間:\n"
    SLACK_MESSAGE+="• 初回発生: $FIRST_SEEN\n"
    SLACK_MESSAGE+="• 最新発生: $LAST_SEEN\n"
    SLACK_MESSAGE+="━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
done < <(echo "$TOP_5_ISSUES" | jq -c '.[]')

# SlackのWebhook URLにcurlでメッセージを送信
curl -X POST -H 'Content-type: application/json' --data "{\"text\":\"$SLACK_MESSAGE\"}" "$SLACK_WEBHOOK_URL"

# curlコマンドが失敗した場合、エラーを出力
if [ $? -ne 0 ]; then
    echo "Error: Failed to send Slack notification."
    exit 1
fi

echo "Slack notification sent."
```

動くとこんな感じで通知してくれます🎉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962815/4966f104-305b-46bc-98b8-bf6963bed538.png)

これで漏れなく改善していけますね。

引き続き、クラッシュ調査はチーム一丸となって行っていきます。

<!-- フッター -->

<hr>

### **▼採用情報**<br>
レアゾン・ホールディングスは、「世界一の企業へ」というビジョンを掲げ、「新しい"当たり前"を作り続ける」というミッションを推進しています。

現在、エンジニア採用を積極的に行っておりますので、ご興味をお持ちいただけましたら、ぜひ下記リンクからご応募ください。

https://recruit.reazon.jp/