1. Architecture
Traffic Tool
  • Traffic Tool Docs
    • Tổng quan
      • Tổng Quan
      • Setup Guide
      • System Architecture
      • Code Structure
      • Logs and Monitoring
      • Environment & Configuration
      • Deployment
        • Local
        • Staging
        • Product
    • Bussiness | Logic
      • 1. Thống kê hàng ngày (Daily Statistics)
      • 2. Thống kê hệ thống (System Statistics)
      • 3. Tìm kiếm tự động (Automated Discovery)
      • 4. Trung tâm Báo cáo (Report Center)
      • 5. Quản lý tài khoản (Account Management)
      • 6. Quản lý Hệ thống (System Management)
      • 7. Quản lý tài khoản Google (Google Account Management)
    • Project
      • ADMIN
        • Tổng quan
        • Hướng dẫn sử dung
          • Đăng Nhập & Xác Thực Hai Bước
          • Thống Kê Hệ Thống
          • Thống Kê Hàng Ngày
          • Tìm Kiếm Tự Động
          • Trung Tâm Báo Cáo
          • Quản Lý Tài Khoản
          • Quản Lý Server
          • Quản Lý Proxy
          • Quản Lý Gói Proxy
          • Quản Lý Nhà Cung Cấp Proxy
          • Quản Lý Backup Proxy
          • Quản Lý Tài Khoản Google
          • User Guide
        • Architecture
          • System Architecture
          • Code Structure
          • Environment & Configuration
          • Logs and Monitoring
        • Deployment
          • Local
          • Staging
          • Production
      • API
        • Tổng quan
        • Architecture
          • Database Schema
          • System Architecture
          • Code Structure
          • Environment & Configuration
          • Logs and Monitoring
        • Deployment
          • Local
          • Staging
          • Production
        • API Interface
          • 🔑 Identity & Session
            • Đăng nhập hệ thống (Login)
            • Đăng ký tài khoản mới (Public)
            • Lấy danh sách người dùng (Phân trang)
            • Admin tạo người dùng mới
            • Lấy thông tin cá nhân hiện tại
            • Khởi tạo bảo mật 2FA
            • Xác thực mã OTP
            • Chi tiết người dùng theo ID
            • Cập nhật thông tin người dùng
            • Xóa tài khoản người dùng
            • Đổi mật khẩu
            • Kiểm tra Cấu hình Thông báo Telegram Toàn hệ thống
            • Bật/Tắt Thông báo Telegram Toàn cục
          • 📁 Campaign Management
            • Danh sách Chiến dịch Toàn cầu
            • Khởi tạo Chiến dịch Mới
            • Chi tiết Chiến dịch
            • Cập nhật Chiến dịch
            • Xóa Chiến dịch
            • Tắt/Mở Chiến dịch (Hàng loạt)
            • Dữ liệu Hình mẫu SEO (Negative SEO)
          • ⚙️ Project Mechanics
            • Danh sách Dự án (Projects List)
            • Khởi tạo Kịch bản Mô phỏng
            • Lấy chi tiết cấu hình Dự án
            • Cập nhật Kịch bản chạy
            • Xóa Dự án
            • Chỉnh sửa Hàng loạt (Bulk)
            • Bật/Tắt Dự án
          • 👤 Profile Management
            • Danh sách Vân tay số (Profiles Data)
            • Tạo Hồ sơ Đơn lẻ (Tạo Vân tay mới)
            • Nhập kho Tài khoản Email (Bulk Import)
            • Chi tiết Session/Cookies
            • Chỉnh sửa Hồ sơ/Ghi chú
            • Xóa Vân tay số và Dữ liệu Local
            • Mở khóa Captcha/Trạng thái Blocked
            • Tra cứu Kho Profile Khả dụng
            • Báo cáo Sức khỏe Kho Tài Khoản
          • 🦾 Worker Interface
            • Đăng ký Khởi tạo Node (Handshake)
            • Nhịp Tim Khảo Sát Tình Trạng (Heartbeat)
            • Nhận Cấu hình Bypass & Hệ thống
            • Kéo (PULL) Nhiệm vụ Traffic SEO
            • Báo cáo Sự cố Node (Crash Report)
          • 📊 Report: Execution
            • Kéo Công việc Báo cáo (Worker Pull)
            • Quản lý Giám sát Nhiệm vụ (Task Dashboard)
            • Bắn Lại Báo Cáo Thất Bại (Manual Retry)
          • 📊 Report: Discovery
            • Danh sách Tên miền Chờ Xử Lý (Discovery Pool)
            • Nhập Mục Tiêu Thủ Công (Manual Insert)
            • Kích hoạt Heuristic Scanner (Cào tự động)
            • Chi tiết Bằng Chứng (Evidence Data)
            • Dán nhãn Vi Phạm / Cập nhật Screenshot
            • Loại Bỏ Mục Tiêu
            • Duyệt Yêu Cầu (Approve to Execution)
          • 📊 Report: Platforms Configuration
            • Truy vấn Danh sách Nền tảng Đối tác (Vendor)
            • Tạo Nền tảng Vendor Báo cáo Mới
            • Bật/Tắt Trang báo cáo theo Loại
            • Cập nhật Metadata Trang
            • Xóa Trang Báo Cáo
            • Lấy Cài đặt LLM cho Vendor cụ thể
            • Cập nhật Cài đặt Tạo mẫu LLM
            • Lấy Cấu hình Schema Biểu mẫu cho Vendor
            • Cập nhật Yêu cầu Trường Biểu mẫu
          • 📊 Report: Email Automation
            • Danh sách SMTP/Mailer Server
            • Thêm kết nối SMTP Mới
            • Nhật ký Nhiệm vụ Gửi Mail (Email Log)
            • Phân tích Tỉ lệ Chuyển đổi (Email Delivery Analytics)
          • 🌐 Global Proxies
            • Danh sách Kho Proxy Phân trang (Proxy Pool)
            • Thêm mới Tuyến IP (Bulk Import)
            • Cập nhật Thông tin máy chủ Proxy
            • Xóa Proxy (Thu hồi tài nguyên)
            • Kích hoạt Xoay vòng (Rotate IP) Cưỡng bức
          • 📈 System Intelligence
            • Báo cáo Luồng Bảo mật Hợp nhất (Colossal Report)
            • Bản Đồ Lưu Lượng GeoIP (Heatmap)
          • 🪝 Webhook Integrations
            • Callback Hoàn tất Gói Lưu lượng SEO (Traffic Node)
            • Callback Thông báo Hoàn tất Bắn Report AI
      • Tool
        • Tổng quan
        • Architecture
          • System Architecture
          • Code Structure
          • Environment & Configuration
          • Logs And Monitoring
          • Database Schema
        • Deployment
          • Local
          • Staging
          • Production
        • API interface
          • Tasks
            • Lấy tasks có phân trang và lọc
            • Xóa tất cả tasks
            • Get all tasks
            • Cập nhật một task
            • Xóa một task theo ID
            • Get all tasks
          • Group task
            • Tạo nhiều task groups
            • Lấy tất cả task groups
            • Xóa tất cả task groups
            • Xóa một task group theo ID
            • Endpoint /api/task-traffics/
            • Test parse proxy string
            • Endpoint /api/task-traffics/
          • Test
            • Mock proxy endpoint cho development
            • Mock profile endpoint cho development
            • Endpoint /api/test
            • Endpoint /api/test/account-stats
            • Endpoint /api/test/session-recommendation
            • Endpoint /api/test/check-browser
            • Endpoint /api/test/clear-browser-sessions
          • Proxies
            • Lấy tất cả proxy records
            • Tạo proxy record mới
            • Xóa tất cả proxies
            • Get all proxies
            • Xóa một proxy theo ID
            • Reset proxy process counter
            • Get all proxies
            • Get all proxies
          • Report Platforms
            • Submit report to multiple platforms
            • Submit report to specific platform
            • Get available platforms
            • Get platform statistics
            • Health check
          • Reports
            • Create a new report
            • Create a new report
            • Get report by ID
            • Get report by ID
            • Get report statistics
            • Get report groups
            • Get report groups
            • Get report group
            • Add report to group
            • Bulk add reports to group
            • Get report group statistics
            • Get analytics data
            • Get platform success rates
            • Get reports by platform
            • Get reports by group
            • Create test reports in bulk
            • Tạo PC report CSV
            • Lấy PC report JSON
            • Lấy report tasks
            • Giám sát report tasks
            • Report tasks đang hoạt động
            • Chi tiết report task
            • Thống kê reports
            • Dữ liệu biểu đồ reports
            • Lấy danh sách report sites
            • Tạo report site
            • Thống kê sites
            • Toggle site enabled/disabled
            • Toggle tất cả sites
            • Toggle sites theo type
            • Cập nhật hàng loạt AI prompts
            • Cập nhật site
            • Xóa site
            • Lấy cấu hình đầy đủ của site
            • Lấy AI prompt của site
            • Cập nhật AI prompt của site
            • Lấy GPT config của site
            • Cập nhật GPT config
            • Lấy response config của site
            • Cập nhật response config
            • Lấy security vendors đang bật
            • Phân tích keywords
            • Top keywords
            • Thống kê analytics
            • PC report dashboard
            • Lấy report domains
            • Thêm report domain
            • Chi tiết report domain
            • Thống kê hàng ngày
            • Cập nhật hàng loạt reports
          • Test Report
            • Test Microsoft report submission
            • Test AdGuard report submission
            • Test Google Ads report submission
            • Test Spamhaus report submission
            • Test ESET report submission
            • Test multi-platform report submission
            • Get available platforms
          • ESET Test
            • Simple test
            • Minimal POST test
            • Generate ESET report content
            • Get sample test data
            • Test form filling
            • Test full form submission
          • Spamhaus Test
            • Simple test
            • Minimal POST test
            • Generate Spamhaus report content
            • Get sample test data
            • Test Spamhaus form filling
            • Test full Spamhaus form submission
          • Report Scheduler
            • Get report scheduler statistics
            • Process ad detection result
            • Submit a scheduled report
            • Start report scheduler
            • Stop report scheduler
            • Get scheduler status
            • Process scheduled reports
            • Test browser session (non-headless)
            • Test report submission (non-headless)
          • Comprehensive Analytics
            • Get comprehensive dashboard analytics
            • Get overview statistics
            • Get brand-wise statistics
            • Get daily statistics
            • Get platform success rates
            • Get account performance
            • Get summary report
          • Search
            • Tạo nhiều search tasks
            • Lấy tổng số search tasks
          • Report Tasks
            • Tạo report tasks cho một domain
            • Tạo report tasks trực tiếp (hỗ trợ profileCountry và domainType rõ ràng)
            • Tạo report tasks cho nhiều domains cùng lúc
            • Tạo email-based report tasks
            • Lấy report task PENDING tiếp theo
            • Cập nhật status của report task
            • Lấy danh sách platforms có sẵn
            • Thống kê report tasks
            • Kích hoạt thực thi thủ công
          • Monitor
            • Thông tin tài nguyên hệ thống
          • System
            • Hello World
            • Health check
            • Đọc file log từ xa
            • Monitor worker status
          • Auth
            • Đăng nhập
            • Đăng ký tài khoản
          • User Management
            • Danh sách users có phân trang
            • Tạo user mới (Admin only)
            • Lấy tất cả users (không phân trang)
            • Lấy thông tin profile của user hiện tại
            • Tạo QR code TOTP cho 2FA
            • Xác thực TOTP để bật 2FA
            • Lấy user theo ID
            • Cập nhật thông tin user
            • Xóa user
            • Đổi mật khẩu user
          • Campaign Management
            • Danh sách campaigns có phân trang
            • Tạo campaign mới
            • Lấy tất cả campaigns
            • Thống kê tổng hợp campaigns
            • Xuất campaigns ra Excel
            • Lấy dữ liệu Negative SEO
            • Xuất dữ liệu Negative SEO ra Excel
            • Xuất Negative SEO theo IDs
            • Lấy dữ liệu Home Traffic
            • Xuất Home Traffic ra Excel
            • Xuất Home Traffic theo IDs
            • Lấy báo cáo campaigns (Public)
            • Lấy tất cả báo cáo campaigns (Public)
            • Lấy chi tiết campaign
            • Cập nhật campaign
            • Xóa campaign
            • Lấy campaigns đã fired theo type
          • Server Management
            • Danh sách servers có phân trang
            • Tạo server mới
            • Lấy tất cả servers
            • Lấy servers từ MongoDB
            • Báo cáo hiệu suất server
            • Thống kê health check
            • Thống kê task monitor
            • Lịch sử lỗi server
            • Thống kê lỗi server
            • Thay đổi trạng thái server
            • Xóa nhiều servers
            • Lấy server theo ID
            • Cập nhật server
            • Xóa server
            • Báo cáo servers (Public)
          • Project Management
            • Lấy tất cả projects
            • Tạo project mới
            • Lấy projects theo campaign
            • Cập nhật dữ liệu traffic
            • Cập nhật nhiều projects
            • Xóa nhiều projects
            • Lấy project theo ID
            • Cập nhật project
            • Cập nhật state của project
            • Cập nhật status của project
            • Tính lại chi tiết project
          • Task Management
            • Worker yêu cầu tasks
            • Reset task creation
          • Proxy Management
            • Danh sách proxies
            • Tạo proxy mới
            • Xóa tất cả proxies
            • Xuất proxies ra Excel
            • Tải template Excel mẫu
            • Tạo nhiều proxies
            • Import proxies từ Excel
            • Import từ tất cả providers
            • Xóa nhiều proxies
            • Lấy proxy theo ID
            • Cập nhật proxy
            • Xóa proxy
            • Toggle trạng thái proxy
          • Backup Proxy
            • Lấy danh sách backup proxies
            • Tạo backup proxy
            • Xóa nhiều backup proxies
            • Import từ Proxifly
            • Chạy health check
            • Lấy backup proxy theo ID
            • Cập nhật backup proxy
            • Xóa backup proxy
            • Test backup proxy
          • Proxy Providers
            • Lấy danh sách proxy providers
            • Tạo proxy provider
            • Xóa nhiều providers
            • Lấy provider theo ID
            • Cập nhật provider
            • Xóa provider
          • Proxy Packages
            • Lấy danh sách proxy packages
            • Tạo proxy package
            • Xóa nhiều packages
            • Lấy package theo ID
            • Cập nhật package
            • Xóa package
          • Profiles
            • Lấy profiles khả dụng (Public)
            • Lấy profile ngẫu nhiên (Public)
            • Danh sách profiles có phân trang
            • Phân tích profiles
            • Health check profiles
            • Tạo profile session
            • Lấy profile session
            • Cập nhật profile session
            • Xóa profile session
            • Đánh dấu profile đã dùng
            • Cập nhật nhiều profiles
            • Tạo nhiều profiles
            • Dọn dẹp sessions hết hạn
            • Dọn dẹp toàn diện
            • Tạo profile mới
            • Lấy profile theo ID
            • Cập nhật profile
            • Xóa profile
            • Thống kê profile
            • Sessions của profile (phân trang)
            • Report tasks của profile
            • Domains đã report bởi profile
            • Tasks theo domain của profile
            • Reset cooldown của profile
            • Test kết nối profile
            • Reset số lần đăng nhập thất bại
            • Ghi nhận đăng nhập thất bại
          • Keywords
            • Danh sách keywords
            • Tạo keyword mới
            • Xuất keywords ra Excel
            • Xác nhận fire keyword
            • Reset tất cả keywords
            • Lấy keyword theo ID
            • Cập nhật keyword
            • Xóa keyword
            • Reset keyword
            • Cập nhật status keyword
            • Kết quả SERP của keyword
          • Dashboard
            • Dữ liệu tổng hợp dashboard
            • Thống kê hệ thống
            • Thống kê traffic theo ID
            • Dữ liệu bảng biểu đồ traffic
            • Xuất báo cáo ra Excel
            • Lấy dữ liệu báo cáo
            • Cập nhật hàng loạt dashboard
            • Tính lại chi tiết projects (Admin only)
          • System Settings
            • Toggle Telegram notifications
            • Trạng thái Telegram notification
          • Activity Logs
            • Lấy activity logs
          • Locations
            • Lấy tất cả locations
            • Tạo location mới
            • Lấy location theo ID
            • Cập nhật location
            • Xóa location
          • Evidence
            • Kiểm tra evidence tồn tại
            • Kiểm tra evidence hàng loạt
            • Lấy evidence mới nhất
          • Files
            • Upload file
            • Download file
          • Server Hourly Reports
            • Lấy server hourly reports
          • Task Logs
            • Lấy task logs
          • Webhooks - Proxy
            • Lấy proxy cho task (Worker webhook)
            • Lấy proxies có thể rotate (Worker webhook)
            • Báo cáo kết quả proxy rotation (Worker webhook)
            • Lấy backup proxy (Worker webhook)
          • Webhooks - Profile
            • Lấy profiles (admin view, webhook)
            • Lấy profile ngẫu nhiên (Worker webhook)
            • Profiles khả dụng (webhook)
            • Lấy profile session (webhook)
            • Tạo profile session (webhook)
            • Đánh dấu profile đã dùng (webhook)
            • Lấy profile tags (webhook)
            • Lấy tất cả profile sessions (webhook)
          • Webhooks - Task
            • Cập nhật kết quả thực thi task (Worker webhook)
          • Webhooks - Search
            • Báo cáo domains đã click (webhook)
            • Lấy clicked domains (webhook)
            • Báo cáo domains (webhook)
            • Third party callback (webhook)
          • Webhooks - Logs
            • Lấy file logs (webhook)
            • Xóa nội dung log (webhook)
            • Kiểm tra IP address (webhook)
          • Webhooks - Keyword
            • Gửi kết quả SERP keyword (webhook)
          • Webhooks - Report
            • Cập nhật trạng thái report task (webhook)
          • Webhooks - CocCoc Token
            • Lấy CocCoc tokens (webhook)
            • Lock CocCoc token (webhook)
            • Unlock CocCoc token (webhook)
    • Schemas
      • LoginRequest
      • UpdateTask
      • WorkerStatus
      • StandardResponse
      • UserResponseDto
      • CreateTaskGroupRequest
      • HealthResponse
      • UserModel
      • CreateProxy
      • ErrorResponse
      • Pagination
      • CreateUserRequest
      • ReportTaskCreation
      • ErrorResponseFull
      • BulkDeleteRequest
      • UpdateUserRequest
      • CreateEmail
      • MessageResponse
      • UserResponse
      • PagingInfo
      • CreateMultipleSearchRequest
      • TrafficType
      • CampaignResponse
      • ProfileModel
      • CreateMultipleReportRequest
      • ServerResponse
      • CreateProfileRequest
      • UpdateReportStatusRequest
      • Task
      • BulkImportProfileReq
      • TestProxyRequest
      • TaskGroup
      • ProxyResponse
      • UpdateProfileRequest
      • CreateTask
      • UpdateTaskBody
      • KeywordResponse
      • CampaignModel
      • CreateSearch
      • TaskPaginatedResponse
      • LocationResponse
      • CreateCampaignRequest
      • ProxyTestResult
      • UpdateCampaignRequest
      • CreateReportTaskBody
      • BulkUpdateCampaignStatusReq
      • CreateEmailReportTaskBody
      • NegativeSeoData
      • BatchReportTaskItem
      • CreateProjectRequest
      • CreateReportTaskResponse
      • UpdateProjectRequest
      • BatchReportTaskResponse
      • ProjectModel
      • BulkUpdateProjectRequest
      • ReportTask
      • WorkerHandshakeRequest
      • UpdateReportTaskStatusBody
      • WorkerHandshakeResponse
      • UpdateReportTaskStatusResponse
      • WorkerHeartbeatPayload
      • PlatformsListResponse
      • WorkerGlobalSettings
      • ReportTaskStatsResponse
      • TaskPullRequest
      • ExecuteReportTaskResponse
      • WorkerFatalLog
      • CreateSearchTask
      • TaskModel
      • Proxy
      • TaskUpdateDto
      • CreateProxyBody
      • ReportTaskModel
      • CreateProxyResponse
      • ReportTaskResult
      • ResetProcessResponse
      • PCReportResponse
      • MonitorResponse
      • ReportSiteItem
      • CreateReportSiteRequest
      • TestProxyResponse
      • GPTConfig
      • TestProfileResponse
      • ResponseConfig
      • ReportDomainsResponse
      • ReportDomainItem
      • AddReportDomainRequest
      • UpdateReportDomainRequest
      • BulkUpdateDashboardRequest
      • ProxyModel
      • CreateProxyRequest
      • UpdateProxyRequest
      • SMTPServerConfig
      • EmailTaskLog
      • GeoLocation
      • CampaignConfigs
      • ProjectAttribute
      • TaskTrafficType
      • ReportTaskItem
      • SummaryStats
      • DailyStats
      • BrandStats
      • ProfileStats
      • FieldConfig
  1. Architecture

Logs And Monitoring

Nhật Ký Và Giám Sát — Tools V2 Worker Engine

Phiên bản: 2.5.0
Cập nhật lần cuối: 26/03/2026


1. Tổng Quan Hệ Thống Logging

1.1. Kiến Trúc Logger

Hệ thống logging của Tools V2 được xây dựng hoàn toàn tùy chỉnh, không dùng thư viện bên ngoài như Winston hay Pino. Toàn bộ nằm trong src/utils/logger/ với bốn thành phần chính:

  • CoreLogger: Nền móng xử lý output streams, quản lý file và console.
  • LogFormatter: Định dạng message thành chuỗi có cấu trúc.
  • ErrorCategorizer: Phân loại lỗi tự động theo nhóm và loại.
  • StructuredLogger: Cung cấp methods log có cấu trúc cho API calls, webhooks, GPT prompts.

Entry point là src/utils/logger/index.ts, export singleton logger và class Logger.

1.2. Singleton Logger

// Dùng trong toàn bộ codebase
import { logger } from "@/utils/logger";
import { logger } from "@/utils"; // Cũng hoạt động qua barrel export

// Log đơn giản
logger.info("Server started", { port: 3005 });
logger.error("Task failed", { taskId: "abc" }, error);

// Child logger với service name
const _logger = logger.child("task-group");
_logger.info("Task started", { taskId: "abc" });
// Output: [timestamp] [LOG_LEVEL_INFO] Task started | LOG_DATA: {"taskId":"abc"}
// File: storage/log/task-group/YYYY-MM-DD/info.log

1.3. Child Logger Pattern

Mỗi class tạo child logger với tên service riêng:

class CronTaskGroup {
  private _logger = logger.child("task-group-cron");
}

class ProxyService {
  private _logger = logger.child("proxy");
}

class ReportTaskCron {
  private readonly logger = logger.child("report-task-cron");
}

Child logger ghi log vào thư mục riêng: storage/log/{service-name}/YYYY-MM-DD/.


2. CoreLogger — Chi Tiết

2.1. Khởi Tạo

CoreLogger được khởi tạo với service name và options:

const coreLogger = new CoreLogger("task-group", {
  level: "info",
  writeToFile: true,
  writeToConsole: true,
  colorized: true,
});

Options được đọc từ biến môi trường nếu không được truyền vào:

  • level: Từ LOG_LEVEL, mặc định info.
  • timestamp: Từ LOG_TIMESTAMP, mặc định false.
  • colorized: Từ LOG_COLORIZED, mặc định false.
  • writeToFile: Từ LOG_WRITE_TO_FILE, mặc định false.
  • writeToConsole: Từ LOG_WRITE_TO_CONSOLE, mặc định true.
  • logDir: Từ LOG_DIR, mặc định storage/log.

2.2. Console Output Whitelist

Đây là điểm đặc biệt của CoreLogger: không phải tất cả log đều được in ra console. Chỉ các log khớp với whitelist mới được in:

const isCounterLog = msgLower.includes("[success]") ||
                     msgLower.includes("[fail]") ||
                     msgLower.includes("total success") ||
                     msgLower.includes("total fails");

const isProxyLog = msgLower.includes("assigned zingproxy") ||
                   msgLower.includes("proxy assigned") ||
                   msgLower.includes("using existing proxy") ||
                   msgLower.includes("browser started") ||
                   msgLower.includes("[proxy_check]") ||
                   msgLower.includes("[debug]") ||
                   msgLower.includes("[api_info]") ||
                   msgLower.includes("cron reached limit") ||
                   msgLower.includes("task allocation");

Tất cả log khác chỉ được ghi vào file, không in ra console. Điều này giúp console không bị ngập bởi log không quan trọng trong production.

2.3. File Output

Log được ghi vào file theo cấu trúc:

storage/log/{service}/{YYYY-MM-DD}/{level}.log

Ví dụ:

storage/log/task-group-cron/2026-03-26/info.log
storage/log/task-group-cron/2026-03-26/error.log
storage/log/proxy/2026-03-26/warn.log

Mỗi level có file riêng. Không có file combined.log — mỗi level được tách biệt.

2.4. Local Development Log

Trong development (NODE_ENV=development), logger còn ghi thêm vào logs.txt ở thư mục gốc:

  • File này bị xóa và tạo lại mỗi khi server khởi động.
  • Tiện lợi để xem log nhanh mà không cần navigate vào storage/log/.
  • Chỉ hoạt động trong development, không có trong production.

2.5. Log Level Filtering

private isLevelEnabled(level: LogLevel): boolean {
  const levels: LogLevel[] = ["error", "warn", "info", "debug"];
  const configLevelIndex = levels.indexOf(this.options.level);
  const logLevelIndex = levels.indexOf(level);
  return logLevelIndex <= configLevelIndex;
}

Với LOG_LEVEL=info:

  • error → enabled (index 0 <= 2).
  • warn → enabled (index 1 <= 2).
  • info → enabled (index 2 <= 2).
  • debug → disabled (index 3 > 2).

3. LogFormatter — Định Dạng Log

3.1. Format Chuẩn

Mỗi log entry có format:

[{ISO_TIMESTAMP}] [{LEVEL_MARKER}] {message} | LOG_ERROR_CATEGORY: {category} | LOG_ERROR_MESSAGE: {msg} | LOG_ERROR_CODE: {code} | LOG_DATA: {json}

Ví dụ thực tế:

[2026-03-26T09:30:00.000Z] [LOG_LEVEL_INFO] Task started | LOG_DATA: {"taskId":"abc123","type":"normalClick"}
[2026-03-26T09:30:05.000Z] [LOG_LEVEL_ERROR] Task failed | LOG_ERROR_CATEGORY: NETWORK:TIMEOUT:ETIMEDOUT | LOG_ERROR_MESSAGE: Navigation timeout | LOG_ERROR_CODE: ETIMEDOUT | LOG_DATA: {"taskId":"abc123"}

3.2. Level Markers

LevelMarker
error[LOG_LEVEL_ERROR]
warn[LOG_LEVEL_WARN]
info[LOG_LEVEL_INFO]
debug[LOG_LEVEL_DEBUG]

3.3. Context Serialization

Context object được serialize thành JSON và append sau LOG_DATA::

logger.info("Proxy rotated", {
  proxyId: "proxy-123",
  newIp: "1.2.3.4",
  region: "VN",
});
// Output: ... | LOG_DATA: {
//   "proxyId": "proxy-123",
//   "newIp": "1.2.3.4",
//   "region": "VN"
// }

Nếu context không thể serialize (circular reference), ghi [Unable to serialize context].


4. ErrorCategorizer — Phân Loại Lỗi

4.1. Error Groups

ErrorCategorizer phân loại lỗi thành các nhóm:

GroupMô tả
NETWORKLỗi kết nối mạng
APILỗi từ API responses
DATABASELỗi MongoDB
VALIDATIONLỗi validation dữ liệu
AUTHENTICATIONLỗi xác thực
EXTERNAL_SERVICELỗi từ dịch vụ bên ngoài
UNKNOWNKhông xác định được

4.2. Error Types

TypeĐiều kiện phát hiệnRetryable
CONNECTION_REFUSEDECONNREFUSED trong message hoặc codeCó
TIMEOUTETIMEDOUT, ECONNRESET, "timeout"Có
NOT_FOUNDHTTP 404, "not found"Không
VALIDATION_FAILEDHTTP 400, "validation"Không
UNAUTHORIZEDHTTP 401, 403Không
RATE_LIMITHTTP 429Có
SERVER_ERRORHTTP 5xxCó
CLIENT_ERRORHTTP 4xx khácKhông
PARSE_ERROR"parse", "json" trong messageKhông
DUPLICATE_KEY"E11000", "duplicate key"Không
UNKNOWNKhông khớp với bất kỳ điều kiện nàoKhông

4.3. Format Output

ErrorCategorizer.formatCategory(category)
// Output: "NETWORK:TIMEOUT:ETIMEDOUT"
// Format: "{group}:{type}:{code}"

Ví dụ các category strings:

  • NETWORK:CONNECTION_REFUSED:ECONNREFUSED
  • NETWORK:TIMEOUT:ETIMEDOUT
  • API:RATE_LIMIT:429
  • API:SERVER_ERROR:500
  • DATABASE:DUPLICATE_KEY:E11000
  • AUTHENTICATION:UNAUTHORIZED:401

4.4. Retryable Flag

retryable: true cho biết lỗi này có thể retry. Được dùng bởi các services để quyết định có retry không:

  • Network errors (ECONNREFUSED, TIMEOUT): Retryable.
  • Rate limit (429): Retryable sau khi chờ.
  • Server errors (5xx): Retryable.
  • Client errors (4xx), validation, auth: Không retryable.

5. StructuredLogger — Log Có Cấu Trúc

5.1. logApiCall

Dùng để log các API calls đến Go API Backend:

structuredLogger.logApiCall("info", "requestTasks", "REQUEST", {
  url: "http://api-host/api/task/request",
  method: "POST",
  requestPayload: { count: 10 },
});

structuredLogger.logApiCall("info", "requestTasks", "SUCCESS", {
  url: "http://api-host/api/task/request",
  responsePayload: { tasks: [...] },
  statusCode: 200,
});

structuredLogger.logApiCall("error", "requestTasks", "ERROR", {
  url: "http://api-host/api/task/request",
  error: new Error("Connection refused"),
});

Output format: API_CALL:{action}:{status} với đầy đủ context.

5.2. logWebhook

Dùng để log webhook calls:

structuredLogger.logWebhook("info", "updateTaskStatus", "REQUEST", {
  url: "http://api-host/webhook/task/update-status",
  requestPayload: { taskId: "abc", status: "completed" },
});

Output format: WEBHOOK:{action}:{status}.

5.3. logGptPrompt

Dùng để log OpenAI API calls:

structuredLogger.logGptPrompt("info", "generateReport", "SUCCESS", {
  model: "gpt-4o-mini",
  tokens: 1500,
  cost: 0.0003,
  response: "{ ... }",
});

Output format: GPT_PROMPT:{action}:{status} với tokens và cost.


6. SessionLogger — Log Browser Sessions

6.1. Mục Đích

SessionLogger trong src/utils/browser_manager/logger/session-logger.ts cung cấp methods log chuẩn hóa cho browser session events.

6.2. logBrowserStart

Được gọi khi một browser session mới được tạo:

SessionLogger.logBrowserStart(
  session.id,
  userAgent,
  proxy,
  geolocation,
  profileInfo
);

Output ví dụ:

[2026-03-26T09:30:00.000Z] [LOG_LEVEL_INFO] Browser Started | LOG_DATA: {
  "sessionId": "01JQXYZ...",
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
  "proxy": "http://1.2.3.4:8080",
  "geolocation": "10.7769, 106.7009",
  "profile": "Incognito (no profile)"
}

6.3. logActionStart và logActionResult

Log khi action bắt đầu và kết thúc:

SessionLogger.logActionStart(sessionId, taskId, "ads-flow", config);
SessionLogger.logActionResult(sessionId, taskId, "ads-flow", true, result);
SessionLogger.logActionResult(sessionId, taskId, "ads-flow", false, null, error);

7. Cấu Trúc File Log

7.1. Tổ Chức Thư Mục

storage/log/
├── app/                          ← Default logger (service="app")
│   └── 2026-03-26/
│       ├── info.log
│       ├── warn.log
│       └── error.log
├── task-group-cron/              ← CronTaskGroup logger
│   └── 2026-03-26/
│       ├── info.log
│       ├── warn.log
│       └── error.log
├── task-group/                   ← TaskGroupService logger
│   └── 2026-03-26/
│       └── info.log
├── report-task-cron/             ← ReportTaskCron logger
│   └── 2026-03-26/
│       ├── info.log
│       └── error.log
├── proxy/                        ← ProxyService logger
│   └── 2026-03-26/
│       └── info.log
├── cron_proxy/                   ← CronProxy logger
│   └── 2026-03-26/
│       ├── info.log
│       └── warn.log
├── browser_manager/              ← BrowserManager logger
│   └── 2026-03-26/
│       ├── info.log
│       └── error.log
├── monitor/                      ← MonitorService logger
│   └── 2026-03-26/
│       └── info.log
├── human-behavior-service/       ← HumanBehaviorService logger
│   └── 2026-03-26/
│       └── debug.log
└── task-group-cleanup/           ← TaskGroupCleanupService logger
    └── 2026-03-26/
        └── info.log

7.2. Nội Dung Từng File

info.log: Các sự kiện bình thường — task start/complete, proxy rotation, browser start.

warn.log: Cảnh báo — proxy chậm, retry attempts, stuck tasks được reset.

error.log: Lỗi nghiêm trọng — task failed, browser crash, API unreachable.

debug.log: Chi tiết kỹ thuật — cursor coordinates, network calls. Chỉ có khi LOG_LEVEL=debug.

7.3. Đọc Log Từ Xa

Endpoint /logs cho phép đọc file log mà không cần SSH:

# Đọc error log hôm nay
curl "http://localhost:3005/logs?filePath=task-group-cron/2026-03-26/error.log"

# Đọc info log của proxy cron
curl "http://localhost:3005/logs?filePath=cron_proxy/2026-03-26/info.log"

# Đọc warn log của browser manager
curl "http://localhost:3005/logs?filePath=browser_manager/2026-03-26/warn.log"

Trả về 404 nếu file không tồn tại.


8. Monitoring Endpoints

8.1. GET / — Trạng Thái Tổng Quan

Endpoint quan trọng nhất để giám sát worker:

curl http://localhost:3005/

Response:

{
  "name": "Traffic tool API",
  "version": "2.5.0",
  "environment": "production",
  "browserSessionRunning": 15,
  "task": {
    "maxProcess": 25,
    "totalProcessRunning": 12
  },
  "proxy": {
    "maxProcess": 5,
    "totalProcessRunning": 3,
    "processRunning": ["proxy-id-1", "proxy-id-2", "proxy-id-3"]
  }
}

Các chỉ số cần theo dõi:

  • browserSessionRunning: Số Chrome instances đang chạy. Nếu bằng BROWSER_LIMIT_PER_PROCESS liên tục, worker đang full capacity.
  • task.totalProcessRunning: Số task đang thực thi. Nếu luôn bằng maxProcess, worker đang full.
  • task.totalProcessRunning = 0: Không có task nào đang chạy — có thể là vấn đề.
  • proxy.totalProcessRunning: Số proxy đang được xử lý.

Thêm header Show-Env: true để xem toàn bộ env config (chỉ trong development):

curl -H "Show-Env: true" http://localhost:3005/

8.2. GET /health — Health Check

curl http://localhost:3005/health

Response:

{
  "status": "ok",
  "time": "2026-03-26T09:30:00.000Z",
  "uptime": 3600.5
}
  • status: Luôn là "ok" nếu server đang chạy.
  • time: Thời điểm hiện tại theo ISO 8601.
  • uptime: Số giây server đã chạy.

Endpoint này được Go API Backend gọi định kỳ để kiểm tra worker còn sống không.

8.3. GET /api/monitor/ — System Metrics

Endpoint cung cấp thông tin chi tiết về tài nguyên hệ thống:

curl http://localhost:3005/api/monitor/

Response:

{
  "ip": "192.168.1.100",
  "cpu": {
    "usage": 45.5,
    "free": 54.5,
    "cores": 8,
    "threads": 8
  },
  "ram": {
    "available": 8192,
    "used": 4096,
    "total": 16384,
    "free": 4096,
    "used_percent": 50.0,
    "unit": "MB"
  },
  "disk": {
    "total": 500,
    "used": 250,
    "free": 250,
    "used_percent": 50.0,
    "unit": "GB"
  },
  "browser": {
    "total_session": 100,
    "used_session": 15,
    "browser_limit_per_session": 28
  },
  "cron_task_limit": 25,
  "task_traffic_limit": 50,
  "cron_search_limit": 1,
  "search_task_limit": 1000
}

Các chỉ số quan trọng:

  • ram.used_percent: Nếu > 85%, cần giảm BROWSER_LIMIT_PER_PROCESS.
  • cpu.usage: Nếu > 90% liên tục, server đang quá tải.
  • browser.used_session: Số Chrome instances đang chạy.
  • disk.used_percent: Nếu > 80%, cần dọn dẹp log files và screenshots.

8.4. GET /logs — Đọc Log Files

# Cú pháp
curl "http://localhost:3005/logs?filePath={service}/{date}/{level}.log"

# Ví dụ
curl "http://localhost:3005/logs?filePath=task-group-cron/2026-03-26/error.log"
curl "http://localhost:3005/logs?filePath=cron_proxy/2026-03-26/warn.log"
curl "http://localhost:3005/logs?filePath=browser_manager/2026-03-26/error.log"

Trả về nội dung file log dạng plain text. Trả về 404 nếu file không tồn tại.


9. Các Log Quan Trọng Cần Theo Dõi

9.1. Log Khởi Động

Khi server khởi động thành công, các log sau xuất hiện:

[INFO] Deleted user-data folder
[INFO] Server started on port 3005
[INFO] Swagger documentation available at http://localhost:3005/swagger
[INFO] Connected to MongoDB
[INFO] All task groups set to pending successfully

Nếu thiếu bất kỳ log nào, có vấn đề với cấu hình.

9.2. Log Task Execution

Khi task được thực thi:

[INFO] Starting 5 tasks (20 pending, 10 running, 25 max). Allocation: google_ads_click=3, kill_flow=2, home_traffic=0, coccoc_ads_click=0. Running: google_ads_click=5, kill_flow=3, home_traffic=2, coccoc_ads_click=0
[INFO] [task-id-123] Task started (11/25 running)
[INFO] Browser Started | LOG_DATA: {"sessionId":"...","proxy":"http://1.2.3.4:8080",...}
[INFO] Action Started | LOG_DATA: {"taskId":"task-id-123","actionType":"ads-flow",...}
[INFO] Action Completed | LOG_DATA: {"taskId":"task-id-123","result":"Success"}

9.3. Log Proxy Rotation

Khi proxy được rotate:

[INFO] [proxy-id-456] Proxy rotation successful | LOG_DATA: {"new_ip":"5.6.7.8","new_port":8080,"region":"VN"}
[INFO] [proxy-id-456] IP check successful | LOG_DATA: {"new_public_ip":"5.6.7.8"}
[INFO] [proxy-id-456] Calling webhook | LOG_DATA: {"webhook_url":"...","proxy_ip":"5.6.7.8"}
[INFO] [proxy-id-456] Webhook called successfully, proxy deleted

9.4. Log Cảnh Báo Cần Chú Ý

[WARN] Found 3 stuck PROCESSING tasks, resetting to PENDING
[WARN] [proxy-id-789] Proxy rotation failed | LOG_DATA: {"retry_count":2,"max_retries":15}
[WARN] [proxy-id-789] Continuing with existing proxy despite rotation failure
[WARN] Cron reached limit (25/25 running). Running types: normalClick=10, killTask=10, homeTraffic=5, coccoc=0

9.5. Log Lỗi Nghiêm Trọng

[ERROR] [task-id-123] Task failed | LOG_ERROR_CATEGORY: NETWORK:TIMEOUT:ETIMEDOUT | LOG_ERROR_MESSAGE: Navigation timeout of 30000 ms exceeded
[ERROR] [proxy-id-789] Proxy deleted after 15 failed rotation attempts
[ERROR] Error in cron start | LOG_ERROR_CATEGORY: DATABASE:CONNECTION_REFUSED:ECONNREFUSED
[ERROR] Report task execution failed | LOG_DATA: {"taskId":"...","platform":"GOOGLE_SAFE_BROWSING","error":"CAPTCHA not solved"}

10. Giám Sát Theo Thời Gian Thực

10.1. Theo Dõi Task Throughput

Để theo dõi số task được xử lý theo thời gian:

# Đếm số task completed trong ngày hôm nay
grep "Action Completed" storage/log/task-group-cron/$(date +%Y-%m-%d)/info.log | wc -l

# Đếm số task failed
grep "Action Failed" storage/log/task-group-cron/$(date +%Y-%m-%d)/error.log | wc -l

# Xem 50 dòng log cuối
tail -50 storage/log/task-group-cron/$(date +%Y-%m-%d)/info.log

Hoặc qua API:

curl "http://localhost:3005/logs?filePath=task-group-cron/$(date +%Y-%m-%d)/info.log"

10.2. Theo Dõi Proxy Health

# Xem proxy rotation failures
grep "rotation failed" storage/log/cron_proxy/$(date +%Y-%m-%d)/warn.log

# Xem proxy deletions
grep "Proxy deleted" storage/log/cron_proxy/$(date +%Y-%m-%d)/info.log | wc -l

10.3. Theo Dõi Browser Sessions

# Xem số browser sessions được tạo
grep "Browser Started" storage/log/browser_manager/$(date +%Y-%m-%d)/info.log | wc -l

# Xem browser crashes
grep "Error" storage/log/browser_manager/$(date +%Y-%m-%d)/error.log

10.4. Theo Dõi Report Tasks

# Xem report tasks completed
grep "COMPLETED" storage/log/report-task-cron/$(date +%Y-%m-%d)/info.log | wc -l

# Xem report tasks failed
grep "FAILED" storage/log/report-task-cron/$(date +%Y-%m-%d)/error.log | wc -l

# Xem CAPTCHA issues
grep "captcha" storage/log/report-task-cron/$(date +%Y-%m-%d)/error.log

11. Dấu Hiệu Cần Chú Ý

11.1. Worker Không Nhận Task

Dấu hiệu: task.totalProcessRunning = 0 trong GET / response kéo dài.

Kiểm tra:

# Xem log task request
curl "http://localhost:3005/logs?filePath=task-group-cron/$(date +%Y-%m-%d)/info.log" | grep "requestTasksFromAPI"

# Kiểm tra kết nối Go API
curl $API_HOST/health

Nguyên nhân thường gặp:

  • Go API không chạy hoặc không accessible.
  • API_KEY không khớp.
  • Không có task mới từ Go API (chiến dịch đã hoàn thành).
  • Worker đang full capacity (kiểm tra task.totalProcessRunning).

11.2. Tỷ Lệ Lỗi Cao

Dấu hiệu: Nhiều [ERROR] trong log, task.totalProcessRunning thấp hơn bình thường.

Kiểm tra:

# Xem error log
curl "http://localhost:3005/logs?filePath=task-group-cron/$(date +%Y-%m-%d)/error.log"

# Xem error category phổ biến nhất
curl "http://localhost:3005/logs?filePath=task-group-cron/$(date +%Y-%m-%d)/error.log" | grep "LOG_ERROR_CATEGORY"

Nguyên nhân theo error category:

  • NETWORK:TIMEOUT: Proxy chậm hoặc trang web không load.
  • NETWORK:CONNECTION_REFUSED: Proxy bị block hoặc chết.
  • API:SERVER_ERROR: Go API đang có vấn đề.
  • UNKNOWN: Cần xem chi tiết error message.

11.3. Memory Cao

Dấu hiệu: ram.used_percent > 85% trong /api/monitor/.

Kiểm tra:

# Xem số browser sessions
curl http://localhost:3005/ | grep "browserSessionRunning"

# Xem browser manager log
curl "http://localhost:3005/logs?filePath=browser_manager/$(date +%Y-%m-%d)/error.log"

Hành động:

  • Giảm BROWSER_LIMIT_PER_PROCESS trong .env.
  • Restart worker để giải phóng memory.
  • Kiểm tra có browser leak không (sessions không được đóng).

11.4. Disk Đầy

Dấu hiệu: disk.used_percent > 80% trong /api/monitor/.

Kiểm tra:

# Xem kích thước thư mục log
du -sh storage/log/

# Xem kích thước screenshots
du -sh storage/screenshots/

Hành động:

  • Xóa log files cũ hơn 7 ngày.
  • Xóa screenshots cũ hơn 30 ngày.
  • Kiểm tra Docker images có chiếm nhiều space không.

12. Cleanup Log Files

12.1. Xóa Log Thủ Công

# Xóa log cũ hơn 7 ngày
find storage/log/ -type f -name "*.log" -mtime +7 -delete

# Xóa thư mục log cũ hơn 30 ngày
find storage/log/ -type d -mtime +30 -empty -delete

# Xóa screenshots cũ hơn 30 ngày
find storage/screenshots/ -type f -mtime +30 -delete

12.2. Tự Động Cleanup

Hiện tại Tools V2 không có cron job tự động xóa log files. Cần setup cron job trên server:

# Thêm vào crontab
0 2 * * * find /path/to/tools_v2/storage/log/ -type f -name "*.log" -mtime +30 -delete
0 3 * * * find /path/to/tools_v2/storage/screenshots/ -type f -mtime +90 -delete

12.3. Log Rotation

Hiện tại không có log rotation tự động. Mỗi ngày tạo thư mục mới, nhưng file trong ngày không bị rotate. Nếu một ngày có quá nhiều log, file có thể lớn.

Để giới hạn kích thước, có thể dùng logrotate trên Linux:

/path/to/tools_v2/storage/log/*/*/*/*.log {
    daily
    rotate 30
    compress
    missingok
    notifempty
}

13. Tích Hợp Với Go API Monitoring

13.1. Worker Health Check

Go API Backend định kỳ gọi GET /health của mỗi worker để kiểm tra còn sống không. Nếu worker không phản hồi trong thời gian quy định, Go API đánh dấu worker offline và ngừng phân phối tasks.

13.2. Monitor Endpoint

Go API cũng gọi GET /api/monitor/ để lấy thông tin tài nguyên của worker. Thông tin này được hiển thị trên Admin Dashboard trong màn hình Server Management.

Các chỉ số được hiển thị:

  • CPU usage và số cores.
  • RAM usage (MB và phần trăm).
  • Disk usage (GB và phần trăm).
  • Browser sessions đang dùng.
  • Task limits.

13.3. Server Performance Tracking

Admin Dashboard có màn hình Server Performance hiển thị:

  • Số tasks completed theo thời gian.
  • Success rate của từng worker.
  • Resource usage theo thời gian.
  • So sánh performance giữa các workers.

Dữ liệu này được Go API thu thập từ webhook callbacks của mỗi task.


14. Debug Workflow

14.1. Khi Task Thất Bại

Quy trình debug khi task thất bại:

  • Lấy task ID từ Go API hoặc Admin Dashboard.
  • Tìm task ID trong log:
curl "http://localhost:3005/logs?filePath=task-group-cron/$(date +%Y-%m-%d)/error.log" | grep "task-id-here"
  • Xem error category để xác định nguyên nhân.
  • Nếu là network error, kiểm tra proxy.
  • Nếu là browser error, kiểm tra browser manager log.
  • Nếu là API error, kiểm tra Go API.

14.2. Khi Browser Không Mở Được

# Kiểm tra browser manager error log
curl "http://localhost:3005/logs?filePath=browser_manager/$(date +%Y-%m-%d)/error.log"

# Kiểm tra số sessions hiện tại
curl http://localhost:3005/ | grep "browserSessionRunning"

# Kiểm tra Chromium dependencies
google-chrome --version 2>&1 || chromium-browser --version 2>&1

14.3. Khi Proxy Không Hoạt Động

# Xem proxy rotation log
curl "http://localhost:3005/logs?filePath=cron_proxy/$(date +%Y-%m-%d)/warn.log"

# Xem proxy deletion log
curl "http://localhost:3005/logs?filePath=cron_proxy/$(date +%Y-%m-%d)/info.log" | grep "deleted"

# Kiểm tra proxy count
curl http://localhost:3005/ | grep "proxy"

14.4. Khi Report Task Thất Bại

# Xem report task error log
curl "http://localhost:3005/logs?filePath=report-task-cron/$(date +%Y-%m-%d)/error.log"

# Tìm task cụ thể
curl "http://localhost:3005/logs?filePath=report-task-cron/$(date +%Y-%m-%d)/error.log" | grep "task-id-here"

14.5. Bật Debug Mode

Để xem log chi tiết hơn, tạm thời bật debug mode:

# Trong .env
LOG_LEVEL=debug

# Restart server
# Sau khi debug xong, đổi lại LOG_LEVEL=info

Debug mode log thêm:

  • Cursor coordinates khi di chuyển chuột.
  • Network requests của browser.
  • Chi tiết từng bước trong flow execution.
  • Memory usage checks.

15. Tóm Tắt Các Endpoint Giám Sát

EndpointMục đíchTần suất kiểm tra
GET /healthKiểm tra server còn sốngMỗi 30 giây (từ Go API)
GET /Trạng thái tổng quan: tasks, browsers, proxiesKhi cần kiểm tra
GET /api/monitor/CPU, RAM, Disk, Browser metricsMỗi 5 phút
GET /logs?filePath=...Đọc log files từ xaKhi debug

Tất cả endpoints đều yêu cầu IP trong IP_ALLOWED list. Endpoint / và /health không yêu cầu authentication. Endpoint /api/monitor/ và /logs yêu cầu IP whitelist.

Modified at 2026-03-27 02:24:32
Previous
Environment & Configuration
Next
Database Schema
Built with