きゅぶろぐ

きゅぶんずの ぶろぐができて べんりだな

Unity 実機でエラーを検知したときに自動的にコンソールログをslackに送信する

実機上でエラーが発生した時、どうやってデバッグしていますか?
AbcConsoleを使っていると、たったこれだけで、
エラーを検知した時(Debug.LogError/LogExceptionが呼ばれた時)に、slackにログを送信できます!

slackのtoken取得はこちらのブログなどを参考に。

AbcConsole.Instance.ErrorCallback += DevelopmentErrorReport.Execute; // どこかでCallbackを登録しておく
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AbcConsole;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

public static class DevelopmentErrorReport
{
    private const string SlackChannel = "(チャンネル名)";
    private const string SlackToken = "(トークン)";
    private const int MaxLogLine = 100; // Logを過去何件まで送るか
    private static readonly TimeSpan Interval = TimeSpan.FromMinutes(1); // 連続で送信するのを防止するためにインターバルを設ける

    private static DateTime _lastSend = DateTime.MinValue;

    public static void Execute(IReadOnlyList<Log> logs)
    {
        var now = DateTime.Now;
        if (_lastSend > now - Interval)
        {
            Debug.Log("Skip");
            return;
        }
        _lastSend = now;

        var lastLog = logs.Last();

        var info = new StringBuilder();
        info.AppendLine($"Version: {Application.version})");
        info.AppendLine($"Device: {SystemInfo.deviceName} ({SystemInfo.operatingSystem}/{SystemInfo.deviceModel})");
        info.AppendLine();
        info.AppendLine($"[{lastLog.Type}] ({lastLog.DateTime:yyyy/MM/dd HH:mm:ss}) {lastLog.Condition.Split('\n').First()}");

        var logText = new StringBuilder();
        var skip = logs.Count - MaxLogLine;
        if (skip > 0)
        {
            logText.AppendLine($"Skip {skip} lines...");
            logText.AppendLine();
        }
        foreach (var log in logs.Skip(skip))
        {
            logText.AppendLine($"[{log.Type}] ({log.DateTime:yyyy/MM/dd HH:mm:ss}) {log.Condition}");
            logText.AppendLine(log.StackTrace);
            logText.AppendLine();
        }

        // https://api.slack.com/methods/files.upload
        var formData = new WWWForm();
        formData.AddField("token", SlackToken);
        formData.AddField("channels", SlackChannel);
        formData.AddBinaryData("file", Encoding.UTF8.GetBytes(logText.ToString()), "log");
        formData.AddField("filetype", "text");
        formData.AddField("initial_comment", info.ToString());

        UniTask.Void(async () =>
        {
            try
            {
                var result = await UnityWebRequest.Post("https://slack.com/api/files.upload", formData).SendWebRequest();
                Debug.Log($"Send Finish {result.responseCode}");
            }
            catch (UnityWebRequestException e)
            {
                Debug.Log($"Send Error {e}");
            }
        });
    }
}