// Pengolah cepat log akses (Apache/Nginx "combined") -> batch JSON untuk mesin deteksi.
// Membaca stdin, menulis JSON ke stdout. Tidak membuka jaringan/berkas lain.
// Kompilasi: g++ -std=c++17 -O2 -Wall -Wextra -o access_log_parser access_log_parser.cpp
// Pakai:     ./access_log_parser SENSOR_CODE < /var/log/nginx/access.log > batch.json
//            curl -X POST $ENGINE_URL/api/v1/ingest -H "X-Sensor-Key: $KEY" -H "Content-Type: application/json" -d @batch.json
#include <iostream>
#include <regex>
#include <string>

static std::string esc(const std::string& s, size_t max = 2000) {
    std::string o; o.reserve(s.size() + 8);
    for (size_t i = 0; i < s.size() && o.size() < max; ++i) {
        unsigned char c = static_cast<unsigned char>(s[i]);
        switch (c) {
            case '"': o += "\\\""; break; case '\\': o += "\\\\"; break;
            case '\n': case '\r': case '\t': o += ' '; break;
            default: if (c < 0x20 || c == 0x7f) o += ' '; else o += static_cast<char>(c);
        }
    }
    return o;
}

int main(int argc, char** argv) {
    const std::string code = argc > 1 ? argv[1] : "";
    if (code.empty()) { std::cerr << "Pemakaian: " << argv[0] << " SENSOR_CODE < access.log\n"; return 2; }
    static const std::regex re(R"re(^(\S+) \S+ \S+ \[[^\]]+\] "([A-Z]+) (\S+) [^"]*" (\d{3}) \S+(?: "[^"]*" "([^"]*)")?)re");
    const size_t kMaxEvents = 500;  // batas per batch sesuai API
    std::cout << "{\"sensor_code\":\"" << esc(code, 50) << "\",\"os\":\"linux\",\"events\":[";
    std::string line; size_t n = 0, skipped = 0; bool first = true;
    while (std::getline(std::cin, line)) {
        std::smatch m;
        if (!std::regex_search(line, m, re)) { ++skipped; continue; }
        if (n >= kMaxEvents) break;
        const std::string url = m[3];
        const auto q = url.find('?');
        if (!first) std::cout << ',';
        first = false;
        std::cout << "{\"type\":\"http_request\",\"ip\":\"" << esc(m[1], 45) << "\",\"method\":\"" << esc(m[2], 10)
                  << "\",\"path\":\"" << esc(url.substr(0, q), 2000) << "\"";
        if (q != std::string::npos) std::cout << ",\"query\":\"" << esc(url.substr(q + 1), 4000) << "\"";
        if (m[5].matched) std::cout << ",\"user_agent\":\"" << esc(m[5], 255) << "\"";
        std::cout << "}";
        ++n;
    }
    std::cout << "]}\n";
    std::cerr << n << " baris diproses, " << skipped << " dilewati\n";
    return 0;
}
