void generateFile(std::string const& filename, const unsigned wordsCount, Dict const& dict, Prng& prng, Queries& queries)
{
  cout << "generating file " << filename << "..." << endl;
  std::ofstream os(filename);
  if( not os.is_open() )
    throw std::runtime_error{"unable to open file for writing: " + filename};

  for(unsigned i=0; i<wordsCount; ++i)
  {
    const auto addNumber = (i % numberedWordEveryIteration) == 0;
    auto       word      = dict[prng()] + ( addNumber ? std::to_string(prng()) : "" );
    os << word << "\n";
    if( (i % queryEveryIteration) == 0 )
      queries.insert(std::move(word));
  }
}
Exemple #2
0
int main(int argc, char **argv) {
    QTextStream qout(stdout, QIODevice::WriteOnly);
    QTextStream qerr(stderr, QIODevice::WriteOnly);
    QTextStream qin(stdin, QIODevice::ReadOnly);

    Args args;
    args.add(new Arg("h", "help", Arg::setTrue, QVariant(false)));
    args.add(new Arg("v", "verbose", Arg::setTrue, QVariant(false)));
    //args.add(new Arg("i", "input-file", Arg::readableFile, QVariant("/var/log/postgresql.log")));
    args.add(new Arg("i", "input-file", Arg::readableFile,
                     QVariant("/var/log/postgresql/postgresql-9.1-main.log")));
    args.add(new Arg("o", "output-file", Arg::writableFile,
                     QVariant("report.html")));
    args.add(new Arg("u", "users", Arg::toString, QVariant()));
    args.add(new Arg("d", "databases", Arg::toString, QVariant()));
    args.add(new Arg("top", Arg::toInt, QVariant(20)));
    args.add(new Arg("t", "query-types", Arg::toString,
                     QVariant("SELECT,UPDATE,INSERT,DELETE")));

    if(!args.parse(argc, argv)) {
        args.help();
        return -1;
    }

    QStringList users = args.getStringList("users");
    QStringList databases = args.getStringList("databases");
    QStringList query_types = args.getStringList("query-types");

    int ret;

    QString line;
    int start_index;
    int stop_index;

    int old_query_id;
    int new_query_id;
    int old_line_id;
    int new_line_id;
    QString database;
    QString user;
    QString statement;
    uint duration;

    QFile input_file;
    ret = args.getFile(&input_file, "input-file", QIODevice::ReadOnly | QIODevice::Text);
    if(ret)return ret;

    QFile output_file;
    ret = args.getFile(&output_file, "output-file", QIODevice::WriteOnly | QIODevice::Text);
    if(ret)return ret;
    QTextStream output(&output_file);

    /* display the top N queries */
    int top = args.getInt("top");

    Queries queries;
    old_query_id = -1;
    old_line_id = -0;
    statement = "";
    duration = 0;

    QTime timer;
    timer.start();

    uint lines = 0;

    if(input_file.atEnd()) {
        qerr << "The input file (" << input_file.fileName();
        qerr << ") seems to be empty" << endl;
    }

    while (!input_file.atEnd()) {
        line = input_file.readLine(4096);
        lines++;
        if(lines % 1000 == 0) {
            qout << "Read " << lines << " lines." << endl;
            qout.flush();
        }

        if(line[0] == '\t') {
            statement.append(line);
            continue;
        }

        start_index = line.indexOf("[", 15);
        start_index = line.indexOf("[", start_index + 3) + 1;
        stop_index = line.indexOf("-", start_index);

        new_query_id = line.mid(start_index, stop_index - start_index).toInt();

        start_index = stop_index + 1;
        stop_index = line.indexOf("]", start_index);

        new_line_id = line.mid(start_index, stop_index - start_index).toInt();

        if(new_query_id != old_query_id || old_line_id < new_line_id) {
            old_query_id = new_query_id;
            QString hashStatement = Query::normalize(statement);
            statement = Query::format(statement);
            if((
                        hashStatement.startsWith("INSERT") ||
                        hashStatement.startsWith("DELETE") ||
                        hashStatement.startsWith("UPDATE") ||
                        hashStatement.startsWith("SELECT")
                    )
                    && (!users.length() || users.contains(user))
                    && (!databases.length() || databases.contains(database))) {
                uint hash = qHash(hashStatement);
                if(queries.contains(hash)) {
                    queries[hash]->addStatement(duration, statement);
                } else {
                    queries.insert(hash, new Query(hashStatement, statement, user, database, duration));
                }
            }

            user = "";
            database = "";
            duration = 0;
            statement = "";

            start_index = line.indexOf("user="******",", start_index);
            user = line.mid(start_index, stop_index - start_index);

            start_index = line.indexOf("db=", stop_index) + 3;
            stop_index = line.indexOf(" ", start_index);
            if(start_index == -1 || stop_index == -1)continue;
            database = line.mid(start_index, stop_index - start_index);

            start_index = line.indexOf("duration: ", stop_index) + 10;
            stop_index = line.indexOf(" ", start_index);
            duration = line.mid(start_index, stop_index - start_index).toDouble() * 1000;

            start_index = line.indexOf("statement: ", stop_index) + 11;
            if(start_index < stop_index)continue;
            stop_index = line.length();
            statement = line.mid(start_index, stop_index - start_index);
        } else {
            start_index = line.indexOf("] ", stop_index);
            if(start_index != -1) {
                start_index += 2;

                stop_index = line.length() - start_index;
                statement.append(line.mid(start_index, line.length() - start_index));
            }
        }
    }

    QFile header(":templates/header.html");
    if (!header.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qout << "Unable to open templates/header.html" << endl;
        return -4;
    } else {
        output << header.readAll();
        header.close();
    }
    QList<Query*> queries_sorted;

    output << QString("<div class=\"information\">"
                      "<ul>"
                      "<li>Generated on %1</li>"
                      "<li>Parsed %2 (%3 lines) in %4 ms</li>"
                      "</ul>"
                      "</div>") \
           .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) \
           .arg(args.getString("input_file")) \
           .arg(lines) \
           .arg(timer.elapsed());

    output << "<div class=\"reports\">";

    output << "<h2 id=\"NormalizedQueriesMostTimeReport\">Queries that took up the most time (N) <a href=\"#top\" title=\"Back to top\">^</a></h2>";
    output << print_queries(queries.sortedQueries(Queries::mostTotalDuration), top);

    output << "<h2 id=\"NormalizedQueriesMostFrequentReport\">Most frequent queries (N) <a href=\"#top\" title=\"Back to top\">^</a></h2>";
    output << print_queries(queries.sortedQueries(Queries::mostExecutions), top);

    output << "<h2 id=\"NormalizedQueriesSlowestAverageReport\">Slowest queries (N) <a href=\"#top\" title=\"Back to top\">^</a></h2>";
    output << print_queries(queries.sortedQueries(Queries::mostAverageDuration), top);

    QFile footer(":templates/footer.html");
    if (!footer.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qout << "Unable to open templates/footer.html" << endl;
        return -5;
    } else {
        output << footer.readAll();
        footer.close();
    }
    qout << "Wrote to file " << args.getString("output-file") << endl;
}