Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7447d7c3 authored by Felipe Leme's avatar Felipe Leme
Browse files

Save dumpstate duration stats so it can be tuned over time.

Fixes: 26373682
Test: dumpstate_test passes and manual verification

Change-Id: I72a308bfb314e157b12746c1be2c33833bdf9d8a
parent 67e488b2
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -69,9 +69,10 @@ binder::Status DumpstateService::setListener(const std::string& name,
}

status_t DumpstateService::dump(int fd, const Vector<String16>&) {
    dprintf(fd, "id: %lu\n", ds_.id_);
    dprintf(fd, "id: %d\n", ds_.id_);
    dprintf(fd, "pid: %d\n", ds_.pid_);
    dprintf(fd, "progress: %d / %d\n", ds_.progress_, ds_.weight_total_);
    dprintf(fd, "progress:\n");
    ds_.progress_->Dump(fd, "  ");
    dprintf(fd, "args: %s\n", ds_.args_.c_str());
    dprintf(fd, "extra_options: %s\n", ds_.extra_options_.c_str());
    dprintf(fd, "version: %s\n", ds_.version_.c_str());
@@ -79,7 +80,8 @@ status_t DumpstateService::dump(int fd, const Vector<String16>&) {
    dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str());
    dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str());
    dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str());
    dprintf(fd, "path: %s\n", ds_.extra_options_.c_str());
    dprintf(fd, "path: %s\n", ds_.path_.c_str());
    dprintf(fd, "extra_options: %s\n", ds_.extra_options_.c_str());
    dprintf(fd, "base_name: %s\n", ds_.base_name_.c_str());
    dprintf(fd, "name: %s\n", ds_.name_.c_str());
    dprintf(fd, "now: %ld\n", ds_.now_);
+22 −14
Original line number Diff line number Diff line
@@ -683,7 +683,7 @@ void Dumpstate::PrintHeader() const {
    JustDumpFile("", "/proc/version");
    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
    printf("Bugreport format version: %s\n", version_.c_str());
    printf("Dumpstate info: id=%lu pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
    printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
           dry_run_, args_.c_str(), extra_options_.c_str());
    printf("\n");
}
@@ -1154,10 +1154,10 @@ static void dumpstate() {
    DumpModemLogs();

    printf("========================================================\n");
    printf("== Final progress (pid %d): %d/%d (originally %d)\n", ds.pid_, ds.progress_,
           ds.weight_total_, WEIGHT_TOTAL);
    printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
           ds.progress_->GetMax(), ds.progress_->GetInitialMax());
    printf("========================================================\n");
    printf("== dumpstate: done (id %lu)\n", ds.id_);
    printf("== dumpstate: done (id %d)\n", ds.id_);
    printf("========================================================\n");
}

@@ -1222,7 +1222,7 @@ bool Dumpstate::FinishZipFile() {
    char date[80];
    time_t the_real_now_please_stand_up = time(nullptr);
    strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
    MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
    MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
           the_real_now_please_stand_up - ds.now_);

    if (!ds.AddZipEntry(entry_name, tmp_path_)) {
@@ -1418,8 +1418,17 @@ int main(int argc, char *argv[]) {
        exit(0);
    }

    /* redirect output if needed */
    bool is_redirecting = !use_socket && use_outfile;

    // TODO: temporarily set progress until it's part of the Dumpstate constructor
    std::string stats_path =
        is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
                       : "";
    ds.progress_.reset(new Progress(stats_path));

    /* gets the sequential id */
    int last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
    uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
    ds.id_ = ++last_id;
    android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));

@@ -1445,7 +1454,7 @@ int main(int argc, char *argv[]) {
        MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
    }

    MYLOGI("dumpstate info: id=%lu, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
    MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
           ds.extra_options_.c_str());

    MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
@@ -1464,9 +1473,6 @@ int main(int argc, char *argv[]) {
        ds.update_progress_ = 1;
    }

    /* redirect output if needed */
    bool is_redirecting = !use_socket && use_outfile;

    if (is_redirecting) {
        ds.bugreport_dir_ = dirname(use_outfile);
        ds.base_name_ = basename(use_outfile);
@@ -1517,7 +1523,7 @@ int main(int argc, char *argv[]) {
                     "--es", "android.intent.extra.NAME", ds.name_,
                     "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
                     "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
                     "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
                     "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
                };
                // clang-format on
                send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
@@ -1720,7 +1726,7 @@ int main(int argc, char *argv[]) {
                 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
                 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
                 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
                 "--ei", "android.intent.extra.MAX", std::to_string(ds.weight_total_),
                 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
                 "--es", "android.intent.extra.BUGREPORT", ds.path_,
                 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
            };
@@ -1743,8 +1749,10 @@ int main(int argc, char *argv[]) {
        }
    }

    MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weight_total_, WEIGHT_TOTAL);
    MYLOGI("done (id %lu)\n", ds.id_);
    MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
           ds.progress_->GetInitialMax());
    ds.progress_->Save();
    MYLOGI("done (id %d)\n", ds.id_);

    if (is_redirecting) {
        fclose(stderr);
+64 −18
Original line number Diff line number Diff line
@@ -184,20 +184,65 @@ class CommandOptions {
};

/*
 * Estimated total weight of bugreport generation.
 * Keeps track of current progress and estimated max, saving stats on file to tune up future runs.
 *
 * Each section contributes to the total weight by an individual weight, so the overall progress
 * can be calculated by dividing the all completed weight by the total weight.
 * Each `dumpstate` section contributes to the total weight by an individual weight, so the overall
 * progress can be calculated by dividing the estimate max progress by the current progress.
 *
 * This value is defined empirically and it need to be adjusted as more sections are added.
 * The estimated max progress is initially set to a value (`kDefaultMax) defined empirically, but
 * it's adjusted after each dumpstate run by storing the average duration in a file.
 *
 * It does not need to match the exact sum of all sections, but ideally it should to be slight more
 * than such sum: a value too high will cause the bugreport to finish before the user expected (for
 * example, jumping from 70% to 100%), while a value too low will cause the progress to get stuck
 * at an almost-finished value (like 99%) for a while.
 */
// TODO: move to dumpstate.cpp / utils.cpp once it's used in just one file
static const int WEIGHT_TOTAL = 6500;
class Progress {
    friend class ProgressTest;
    friend class DumpstateTest;

  public:
    /*
     * Default estimation of the max duration of a bugreport generation.
     *
     * It does not need to match the exact sum of all sections, but ideally it should to be slight
     * more than such sum: a value too high will cause the bugreport to finish before the user
     * expected (for example, jumping from 70% to 100%), while a value too low will cause the
     * progress to get stuck at an almost-finished value (like 99%) for a while.
     *
     * This constant is only used when the average duration from previous runs cannot be used.
     */
    static const int kDefaultMax;

    Progress(const std::string& path = "");

    // Gets the current progress.
    int32_t Get() const;

    // Gets the current estimated max progress.
    int32_t GetMax() const;

    // Gets the initial estimated max progress.
    int32_t GetInitialMax() const;

    // Increments progress (ignored if not positive).
    // Returns `true` if the max progress increased as well.
    bool Inc(int32_t delta);

    // Persist the stats.
    void Save();

    void Dump(int fd, const std::string& prefix) const;

  private:
    Progress(int32_t initial_max, float growth_factor,
             const std::string& path = "");                                // Used by test cases.
    Progress(int32_t initial_max, int32_t progress, float growth_factor);  // Used by test cases.
    void Load();
    int32_t initial_max_;
    int32_t progress_;
    int32_t max_;
    float growth_factor_;
    int32_t n_runs_;
    int32_t average_max_;
    const std::string& path_;
};

/*
 * List of supported zip format versions.
@@ -310,12 +355,17 @@ class Dumpstate {
     */
    void TakeScreenshot(const std::string& path = "");

    // TODO: members below should be private once refactor is finished
    /////////////////////////////////////////////////////////////////////
    // TODO: members below should be private once refactor is finished //
    /////////////////////////////////////////////////////////////////////

    // TODO: temporary method until Dumpstate object is properly set
    void SetProgress(std::unique_ptr<Progress> progress);

    /*
     * Updates the overall progress of the bugreport generation by the given weight increment.
     */
    void UpdateProgress(int delta);
    void UpdateProgress(int32_t delta);

    /* Prints the dumpstate header on `stdout`. */
    void PrintHeader() const;
@@ -332,7 +382,7 @@ class Dumpstate {
    // TODO: initialize fields on constructor

    // dumpstate id - unique after each device reboot.
    unsigned long id_;
    uint32_t id_;

    // dumpstate pid
    pid_t pid_;
@@ -343,11 +393,7 @@ class Dumpstate {
    // Whether it should take an screenshot earlier in the process.
    bool do_early_screenshot_ = false;

    // Currrent progress.
    int progress_ = 0;

    // Total estimated progress.
    int weight_total_ = WEIGHT_TOTAL;
    std::unique_ptr<Progress> progress_;

    // When set, defines a socket file-descriptor use to report progress to bugreportz.
    int control_socket_fd_ = -1;
+0 −0

Empty file added.

+1 −0
Original line number Diff line number Diff line
SIX_SIX_SIX 42
Loading