// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "util/pprof_utils.h"

#include <stdio.h>
#include <unistd.h>

#include <cstdlib>
#include <fstream> // IWYU pragma: keep
#include <memory>

#include "absl/strings/substitute.h"
#include "agent/utils.h"
#include "io/fs/local_file_system.h"

namespace doris {
namespace config {
extern std::string pprof_profile_dir;
}

Status PprofUtils::get_pprof_cmd(std::string* cmd) {
    AgentUtils util;
    // check if pprof cmd exist
    const static std::string tools_path = std::string(std::getenv("DORIS_HOME")) + "/tools/bin/";
    std::string pprof_cmd = tools_path + "pprof";
    std::string msg;
    bool rc = util.exec_cmd(pprof_cmd + " --version", &msg);
    if (!rc) {
        // not found in BE tools dir, found in system
        pprof_cmd = "pprof";
        rc = util.exec_cmd(pprof_cmd + " --version", &msg);
        if (!rc) {
            return Status::NotSupported(
                    "pprof: command not found in systemp PATH or be/tools/bin/. Install gperftools "
                    "first.");
        }
    }
    *cmd = pprof_cmd;
    return Status::OK();
}

Status PprofUtils::get_perf_cmd(std::string* cmd) {
    AgentUtils util;
    // check if perf cmd exist
    std::string perf_cmd = "perf";
    std::string msg;
    bool rc = util.exec_cmd(perf_cmd + " --version", &msg);
    if (!rc) {
        return Status::NotSupported("perf: command not found in systemp PATH");
    }
    *cmd = perf_cmd;
    return Status::OK();
}

Status PprofUtils::get_self_cmdline(std::string* cmd) {
    // get cmdline
    FILE* fp = fopen("/proc/self/cmdline", "r");
    if (fp == nullptr) {
        return Status::InternalError("Unable to open file: /proc/self/cmdline");
    }
    char buf[1024];

    Status res = Status::OK();

    if (fscanf(fp, "%1023s ", buf) != 1) {
        res = Status::InternalError("get_self_cmdline read buffer failed");
    }
    fclose(fp);
    *cmd = buf;
    return res;
}

Status PprofUtils::get_readable_profile(const std::string& file_or_content, bool is_file,
                                        std::stringstream* output) {
    // get pprof cmd
    std::string pprof_cmd;
    RETURN_IF_ERROR(PprofUtils::get_pprof_cmd(&pprof_cmd));

    // get self cmdline
    std::string self_cmdline;
    RETURN_IF_ERROR(PprofUtils::get_self_cmdline(&self_cmdline));

    // save file if necessary
    std::string final_file;
    if (!is_file) {
        std::stringstream tmp_file;
        tmp_file << config::pprof_profile_dir << "/pprof_profile." << getpid() << "." << rand();
        std::ofstream outfile;
        outfile.open(tmp_file.str().c_str());
        outfile << file_or_content;
        outfile.close();
        final_file = tmp_file.str();
    } else {
        final_file = file_or_content;
    }

    // parse raw with "pprof --text cmdline raw_file"
    std::string cmd_output;
    std::string final_cmd = pprof_cmd + absl::Substitute(" --text $0 $1", self_cmdline, final_file);
    AgentUtils util;
    LOG(INFO) << "begin to run command: " << final_cmd;
    bool rc = util.exec_cmd(final_cmd, &cmd_output, false);

    // delete raw file
    static_cast<void>(io::global_local_filesystem()->delete_file(file_or_content));

    if (!rc) {
        return Status::InternalError("Failed to execute command: {}", cmd_output);
    }

    (*output) << "Profile(Sample 30 seconds)" << std::endl;
    (*output) << cmd_output << std::endl;
    return Status::OK();
}

Status PprofUtils::generate_flamegraph(int32_t sample_seconds,
                                       const std::string& flame_graph_tool_dir, bool return_file,
                                       std::string* svg_file_or_content) {
    // get perf cmd
    std::string perf_cmd;
    RETURN_IF_ERROR(PprofUtils::get_perf_cmd(&perf_cmd));

    // check if FlameGraph has been installed
    // check stackcollapse-perf.pl and flamegraph.pl exist
    std::string stackcollapse_perf_pl = flame_graph_tool_dir + "/stackcollapse-perf.pl";
    std::string flamegraph_pl = flame_graph_tool_dir + "/flamegraph.pl";
    bool exists = false;
    RETURN_IF_ERROR(io::global_local_filesystem()->exists(stackcollapse_perf_pl, &exists));
    RETURN_IF_ERROR(io::global_local_filesystem()->exists(flamegraph_pl, &exists));
    if (!exists) {
        return Status::InternalError(
                "Missing stackcollapse-perf.pl or flamegraph.pl in FlameGraph");
    }

    // tmp output profile file
    std::stringstream tmp_file;
    tmp_file << config::pprof_profile_dir << "/cpu_perf." << getpid() << "." << rand();

    // sample
    std::stringstream cmd;
    cmd << perf_cmd << " record -m 2 -g -p " << getpid() << " -o " << tmp_file.str() << " -- sleep "
        << sample_seconds;

    AgentUtils util;
    std::string cmd_output;
    LOG(INFO) << "begin to run command: " << cmd.str();
    bool rc = util.exec_cmd(cmd.str(), &cmd_output);
    if (!rc) {
        static_cast<void>(io::global_local_filesystem()->delete_file(tmp_file.str()));
        return Status::InternalError("Failed to execute perf command: {}", cmd_output);
    }

    // generate flamegraph

    std::string res_content;
    if (return_file) {
        std::stringstream graph_file;
        graph_file << config::pprof_profile_dir << "/flamegraph." << getpid() << "." << rand()
                   << ".svg";
        std::stringstream gen_cmd;
        gen_cmd << perf_cmd << " script -i " << tmp_file.str() << " | " << stackcollapse_perf_pl
                << " | " << flamegraph_pl << " > " << graph_file.str();
        LOG(INFO) << "begin to run command: " << gen_cmd.str();
        rc = util.exec_cmd(gen_cmd.str(), &res_content);
        if (!rc) {
            static_cast<void>(io::global_local_filesystem()->delete_file(tmp_file.str()));
            static_cast<void>(io::global_local_filesystem()->delete_file(graph_file.str()));
            return Status::InternalError("Failed to execute perf script command: {}", res_content);
        }
        *svg_file_or_content = graph_file.str();
    } else {
        std::stringstream gen_cmd;
        gen_cmd << perf_cmd << " script -i " << tmp_file.str() << " | " << stackcollapse_perf_pl
                << " | " << flamegraph_pl;
        LOG(INFO) << "begin to run command: " << gen_cmd.str();
        rc = util.exec_cmd(gen_cmd.str(), &res_content, false);
        if (!rc) {
            static_cast<void>(io::global_local_filesystem()->delete_file(tmp_file.str()));
            return Status::InternalError("Failed to execute perf script command: {}", res_content);
        }
        *svg_file_or_content = res_content;
    }
    return Status::OK();
}

} // namespace doris
