Capture Unity logs while not printing them to the console

Hi, I disable logs on live build and enable for staging build. I see a lot of issues in live build, so to debug that i have created a script to collect all the logs and store it in a json file.

I dont want people see the logs as it contains valuable data. so how can i achieve it : capture all the logs while not printing any logs in build or unity editor. The only way to see the logs is through this json file that i created.

I have successfully created and saved the unity logs to a json file when i do : Debug.unityLogger.logEnabled = true .

if i write : Debug.unityLogger.logEnabled = false; and capture the logs, it didnt work.

So any idea what can i do here ?

I used below event to capture logs.

Application.logMessageReceivedThreaded += HandleLog;

void HandleLog()
{
// logic
}

the parameters are for log message, stack trace and the log type. It doesnt help in my case

You could create your own LogHandler, and set it by Debug.unityLogger.logHandler = customLogHandler. Here’s an example:

public class CustomLoggerTestScript : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI text;

    ILogHandler defaultLogHandler;

    private void Awake()
    {
        defaultLogHandler = Debug.unityLogger.logHandler;
    }

    public void SetToDefaultLogHandler()
    {
        Debug.unityLogger.logHandler = defaultLogHandler;
    }

    public void SetToMyLogHandler()
    {
        Debug.unityLogger.logHandler = new MyLogHandler(text);
    }
}

public class MyLogHandler : ILogHandler
{
    private readonly TextMeshProUGUI text;
    public MyLogHandler(TextMeshProUGUI text)
    {
        this.text = text;
    }

    public void LogFormat(LogType logType, Object context, string format, params object[] args)
    {
        text.text += string.Format(format, args) + "\n";
    }

    public void LogException(Exception exception, Object context)
    {
        text.text += exception + "\n";
    }
}

In the above case, if you switch to MyLogHandler, every Debug.Log() will flow to the UI text, instead of the console.

3 Likes

You would have to send the logs over the internet to your private server via encrypted traffic. How else can you get something from the user’s machine to you without them reading it? You would have to state those terms, like what kind of data you’re sending clearly to the user for them to agree or disagree to. It would need to comply with all relevant laws. Also, even with encrypted network traffic, a knowledgeable user could be able to hack the app itself and just snoop on the private log data that way. It’s my opinion that you just shouldn’t try to hide data from a user on their own computer in a log file. I hope I understood your goal correctly. I’m sorry if it’s not the answer you were hoping to hear.

But, if you want to try to go down that route, tsukimi is right. You can override Debug.unityLogger.logHandler with your own ILogHandler. That’s how I do it.

5 Likes

Thank you very much, I will try it now

Hi @tsukimi and @CodeRonnie , Thanks for your help. I was able to achieve it.
This is how i store logs and format it in a json:

{
“message”: “Hello World”,
“stackTrace”: “at LogCapture.GetStackTrace () <0x00000 + 0xffffffff> 0 in <00000000000000000000000000000000>:0\n at Ludo.LudoPlayer.SetPlayerRingAnimation (System.Boolean val) <0x00000 + 0xffffffff> 0 in <00000000000000000000000000000000>:0\nat System.Action`1[T].Invoke (T obj) <0x00000 + 0xffffffff> 0 in <00000000000000000000000000000000>:0”,
“type”: “Log”
},

The issue is the size of the file is getting large as logs are getting printed :

To manage it, I have added filter to not add duplicate logs, using hashset to store logs.
The stack trace has <0000x> the memory address : which i dont want. I only need human readable text in stack trace,
Is there a way in unity to handle it. OR should i manually remove it by doing string operation.

cc @JoshPeterson

Just gzip the Json file, since there’s a lot of repeated characters, the compression ratio will be extreme (probably 90-95%)

https://stackoverflow.com/a/11155693

I second what @CodeRonnie said, there’s no point in hiding something on a user device, they own the device and everything inside it, plus it’s just log files, they shouldn’t contain any secrets or personal informations (at least I hope so, or else you may get into big troubles…)

Hi @Nad_B , We have multiple multiplayer games on android build, we send game config, packets and important information from server to unity which will control the game play.
one option is to hide the logs, if i do it, i cant get crash logs, errors logs at run time. If i enable it then i need to hide it from users and send it to server.

I have done it.
The only thing is i am manually trimming the stack trace everytime. It could be performance heavy. SO i thought maybe unity has some pre built solution to it.

    private string CleanStackTraceRemoveExtraThings(string fullStackTrace)
    {
        // Remove Unity internal calls with placeholder addresses from the stack trace
        string[] stackTraceLines = fullStackTrace.Split('\n');
        List<string> cleanedStackTrace = new List<string>();

        foreach (string line in stackTraceLines)
        {
            if (!line.Contains("UnityEngine.") && !line.Contains("UnityEditor."))
            {
                // Extract class.method information and add to the cleaned stack trace
                if (line.Contains("at "))
                {
                    int startIndex = line.IndexOf("at ") + 3;
                    int endIndex = line.IndexOf("(", startIndex);
                    if (endIndex != -1)
                    {
                        string classMethod = line.Substring(startIndex, endIndex - startIndex);
                        cleanedStackTrace.Add(classMethod);
                    }
                }
            }
        }

        return string.Join("\n", cleanedStackTrace.ToArray());

    }

I don’t think Unity has anything to offer regarding formatting stack traces, it’s a crucial C#/.NET feature. Since you’re on Android, it means you’re under IL2CPP, that’s why you’re getting those hexadecimal identifiers instead of the actual class/method names. You could improve the stripping performance by using a StreamReader, Regex and/or Spans.

But as I said, just try gzipping the file, it’ll take care of reducing the log file sizes drastically, then you can process/strip them on your server after you upload them to avoid doing the work on your users devices.

2 Likes

Thanks @Nad_B , I will try gzipping.