Inferno

Add in-game bug reports to your game

Let players and testers send a bug report from inside your game. Each report lands on your Inferno board as a task, labeled with the build it came from, so it is triaged next to the rest of your work instead of in a chat thread. Setup takes about ten minutes.

What you need

Set it up

  1. Open Settings, then Bug reports. Log in to Inferno and open Settings from the sidebar. Only owners and editors of a board see this.
  2. Create a report token. Pick the project the reports should go to and give the token a build label such as build-0.3.1. The label is added to every report as a task label. Choose which column new reports land in. Make a new token for each build you hand out.
  3. Copy the token and the address. Inferno shows the token once. Copy it before you leave the screen. If you lose it, revoke it and make a new one.
  4. Test it with curl. Run this in a terminal, with your own token in place of the example. A task should appear on your board within a few seconds.
    curl -X POST https://qprtaihyjfgswggrekpm.supabase.co/functions/v1/create-report \
      -H "Authorization: Bearer inr_your_token" \
      -H "Content-Type: application/json" \
      -d '{"content":"Player falls through the floor\nLevel 3, after the lift","severity":"high","device":{"os":"Windows 11","gpu":"RTX 3060"}}'
  5. Add it to your game. Pick your engine below, paste in your token, and call it from a report button or an error handler.

What your game sends

One JSON object in a POST to https://qprtaihyjfgswggrekpm.supabase.co/functions/v1/create-report, with your token in an Authorization: Bearer header.

FieldRequiredWhat it does
contentYesThe report text, up to 4,000 characters. The first line becomes the task title.
severityNolow, medium, high, or crash. Sets the task's priority and, if you chose one, its column.
deviceNoAn object with os and gpu. Added to the end of the task description.

Anything else in the request is ignored. The whole request must be under 20 KB. HTML tags and control characters are removed.

What comes back

StatusMeaning
200The report was saved as a task.
400The request was not valid JSON, had no content, or had an unknown severity.
401The token is wrong, switched off, revoked, or its project was deleted. These all look the same on purpose.
413The request was too large.
429Too many reports. Wait a while and try again.

Examples for your engine

These are plain HTTP examples to adapt, not a plugin. Replace inr_your_token with your own token.

Unity

// Unity (C#). Call StartCoroutine(Send("what happened", "high")) from a button.
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

public class InfernoBugReporter : MonoBehaviour
{
    const string Endpoint = "https://qprtaihyjfgswggrekpm.supabase.co/functions/v1/create-report";
    const string Token = "inr_your_token";

    [System.Serializable] class Device { public string os; public string gpu; }
    [System.Serializable] class Report { public string content; public string severity; public Device device; }

    public IEnumerator Send(string text, string severity = "medium")
    {
        var report = new Report
        {
            content = text,
            severity = severity,
            device = new Device { os = SystemInfo.operatingSystem, gpu = SystemInfo.graphicsDeviceName },
        };
        using var request = new UnityWebRequest(Endpoint, "POST");
        request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonUtility.ToJson(report)));
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("Authorization", "Bearer " + Token);
        yield return request.SendWebRequest();
        if (request.result != UnityWebRequest.Result.Success)
            Debug.LogWarning("Bug report not sent: " + request.responseCode);
    }
}

Godot 4

# Godot 4 (GDScript). Add this script to an autoload, then call send_report("what happened", "high").
extends Node

const ENDPOINT := "https://qprtaihyjfgswggrekpm.supabase.co/functions/v1/create-report"
const TOKEN := "inr_your_token"

func send_report(text: String, severity := "medium") -> void:
	var http := HTTPRequest.new()
	add_child(http)
	var body := JSON.stringify({
		"content": text,
		"severity": severity,
		"device": {"os": OS.get_name(), "gpu": RenderingServer.get_video_adapter_name()},
	})
	var headers := ["Content-Type: application/json", "Authorization: Bearer " + TOKEN]
	http.request_completed.connect(func(_result, code, _headers, _body):
		if code != 200:
			push_warning("Bug report not sent: %d" % code)
		http.queue_free())
	http.request(ENDPOINT, headers, HTTPClient.METHOD_POST, body)

Unreal

// Unreal (C++). Add "HTTP" and "Json" to PublicDependencyModuleNames in your Build.cs.
#include "HttpModule.h"
#include "Interfaces/IHttpRequest.h"
#include "Dom/JsonObject.h"
#include "Serialization/JsonSerializer.h"
#include "Serialization/JsonWriter.h"

void SendBugReport(const FString& Text, const FString& Severity)
{
    TSharedRef<FJsonObject> Json = MakeShared<FJsonObject>();
    Json->SetStringField(TEXT("content"), Text);
    Json->SetStringField(TEXT("severity"), Severity);

    FString Body;
    TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&Body);
    FJsonSerializer::Serialize(Json, Writer);

    TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Request = FHttpModule::Get().CreateRequest();
    Request->SetURL(TEXT("https://qprtaihyjfgswggrekpm.supabase.co/functions/v1/create-report"));
    Request->SetVerb(TEXT("POST"));
    Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
    Request->SetHeader(TEXT("Authorization"), TEXT("Bearer inr_your_token"));
    Request->SetContentAsString(Body);
    Request->ProcessRequest();
}

What happens to a report

Keeping it safe

Not included yet

If something does not work

Still stuck? Email celeste@infernotaskboard.com.