LogKeeper (Flutter & Firebase)

This is a log snapshot management solution used to save and share log snapshots within the development team.
Supports iOS/Android/Web and utilizes Dart backend API (with client-server shared code).
Logs stored in Firestore and Firebase Auth used to access some parts of the data.

By default, mock repositories are used. So just run the project to try it with mock data.

Usage scenario

  • QA engineer or someone from the team finds an error in the app
  • Whether it is an error popup or just a suspicious behaviour there should always be a button to upload logs to the LogKeeper
  • This button reads log file and makes POST request which saves the log on the server, analyzes it and returns a link to it
  • Now a person has the link to the uploaded log which they can share to the Bug report or just post it to the chat.
    The link looks something like: https://[your_hosting_url]/#/details?id=[log_id]
    Link redirects to this log like this:\
Log Contents Log Contents in Web view
image image

All logs later can be found on the home screen which is accessible only for authorized users\

Auth Screen Home Screen Log Deletion Popup
image image image
Settings Screen Upload Log Screen Home Screen Drawer
image image image


This tool uses:

Consists of the following parts:

  • log_keep_back (an API to upload logs and to retrieve links to share them)
  • log_keep (client part to view logs or upload them manually)
  • log_keep_shared (code shared between other two projects)
  • code to send logs to an API from your apps (an example for Unity C# is given below)

Folders structure is based on https://hub.docker.com/r/google/dart-runtime-base
in order to use shared code in log_keep_shared both on the client and server sides.

How to set it up

Firebase Account

  • Create one at https://firebase.google.com/
  • Add apps that you need (iOS/Android/Web)
  • Enable Firestore and create empty collections ("projects" and "logs")

Attach Firebase to your local copy

in log_keep:

  • add google-services.json for Android
  • add GoogleService-Info.plist for iOS
  • add firebaseConfig.js near index.html which should contain code like this:
var firebaseConfig = {
    apiKey: "..",
    authDomain: "..",
    projectId: "..",
    storageBucket: ".",
    messagingSenderId: "..",
    appId: "..",
    measurementId: ".."


Moving from mock to Firebase data

Mock repositories used by default. When your Firebase account is ready please go to app.dart and uncomment Firebase repositories

firebaseApp = await Firebase.initializeApp();

    signalsReady: true);

    signalsReady: true);

To build and host Web client use

  • cd log_keep
  • flutter build web
  • init and login using Firebase CLI
  • firebase deploy --only hosting

Google Service Account

For a backend to run you need a Google Service Account https://cloud.google.com/iam/docs/service-accounts.

Service account credentials could be passed to log_keep_back via .env file:

  • private_key_id
  • client_email
  • client_id
  • private_key
  • databaseParentPath="projects/[PROJECT_ID]/databases/(default)/documents"
  • serverLogUrlFormat="https://[PROJECT_ID].web.app/#/details?id={0}"

Instructions on how to build & deploy server can also be found here https://hub.docker.com/r/google/dart-runtime-base



Known issues and limitations

  • The Web browser forces all widgets above it to ignore all clicks on them.
    As a temporary solution in such cases, the browser becomes hidden.
  • Firestore limits its entities to 2mb so this is the limitation for log files uploaded.
    The plan is to use Firebase Storage to keep logs there.
  • Flutter Web text rendering performance seems to have some issues. This is a target for some R&D. For now Web browser has been added as a fallback log viewer.

Example code of sending request to the LogKeeper

Unity, C#:

var form = new WWWForm();

// Prepare log data
form.AddField("title", title);
form.AddField("author", author);
form.AddField("project", project);
form.AddField("contents", contents); // the log contents

// Send
var uwr = UnityWebRequest.Post("your_url" + "/save", form);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
    // error

// Read result
var raw = Encoding.UTF8.GetString(uwr.downloadHandler.data);
var id = JSON.Parse(raw)["body"]["id"].Value;
var urlFormat = JSON.Parse(raw)["body"]["url_format"].Value;

// Get the link to the log
var link = string.Format(urlFormat, id);
ShowNotifications("Report link copied to clipboard");


Feel free to report bugs, request new features
or to contribute to this project!