Files
dotlog-demo/index.html
2026-04-21 13:49:12 +08:00

936 lines
29 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>dotlog — 把所有日誌管線串成一行</title>
<meta name="description" content="dotlog 是為工程師而生的 CLI 工具:一條指令完成擷取、過濾、聚合、輸出。" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
<style>
/* ===================== Tokens ===================== */
:root {
--background: #fcfcfc;
--foreground: #171717;
--card: #fcfcfc;
--primary: #00bb7f;
--primary-soft: rgba(0, 187, 127, 0.25);
--primary-bg: rgba(0, 187, 127, 0.10);
--secondary: #fdfdfd;
--muted: #ededed;
--muted-foreground: #525252;
--neutral-400: #a1a1a1;
--accent: #ededed;
--border: #dfdfdf;
--ring: #72e3ad;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-lg: 0 12px 32px -14px rgba(0, 0, 0, 0.18);
--radius-xs: 4px;
--radius-md: 10px;
--radius-2xl: 16px;
--radius-3xl: 24px;
--font-sans: "Space Grotesk", system-ui, -apple-system, "Noto Sans TC", sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
--transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--container: 1152px;
}
html.dark {
--background: #121212;
--foreground: #e2e8f0;
--card: #171717;
--primary: #00bb7f;
--primary-soft: rgba(74, 222, 128, 0.30);
--primary-bg: rgba(0, 187, 127, 0.14);
--secondary: #242424;
--muted: #1f1f1f;
--muted-foreground: #a2a2a2;
--accent: #313131;
--border: #292929;
--ring: #4ade80;
--shadow-lg: 0 12px 32px -14px rgba(0, 0, 0, 0.6);
}
/* ===================== Reset ===================== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--font-sans);
background: var(--background);
color: var(--foreground);
font-size: 16px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
transition: background var(--transition), color var(--transition);
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; padding: 0; }
code { font-family: var(--font-mono); background: var(--muted); padding: 1px 6px; border-radius: var(--radius-xs); font-size: 0.875em; }
.container {
max-width: var(--container);
margin: 0 auto;
padding: 0 24px;
}
/* ===================== Header ===================== */
.site-header {
position: sticky;
top: 0;
z-index: 50;
height: 64px;
display: flex;
align-items: center;
background: color-mix(in srgb, var(--background) 78%, transparent);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border);
}
.site-header .container {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.brand {
display: flex;
align-items: center;
gap: 10px;
font-weight: 700;
font-size: 18px;
letter-spacing: -0.01em;
}
.brand-dot {
width: 10px; height: 10px;
border-radius: 50%;
background: var(--primary);
box-shadow: 0 0 10px var(--primary);
}
.nav {
display: flex;
align-items: center;
gap: 6px;
}
.nav > a {
padding: 8px 12px;
font-size: 14px;
color: var(--muted-foreground);
border-radius: 8px;
transition: color var(--transition);
}
.nav > a:hover { color: var(--primary); }
.theme-toggle {
width: 36px; height: 36px;
border-radius: var(--radius-md);
display: grid;
place-items: center;
border: 1px solid var(--border);
transition: background var(--transition), border-color var(--transition);
margin: 0 4px;
}
.theme-toggle:hover { background: var(--accent); border-color: var(--primary-soft); }
.theme-toggle svg { width: 16px; height: 16px; }
.theme-toggle .sun { display: none; }
html.dark .theme-toggle .sun { display: block; }
html.dark .theme-toggle .moon { display: none; }
.nav-github {
padding: 8px 14px !important;
font-size: 13.5px !important;
border-radius: 12px !important;
}
@media (max-width: 639px) {
.nav > a:not(.nav-github) { display: none; }
}
/* ===================== Buttons ===================== */
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 12px 24px;
border-radius: var(--radius-2xl);
font-weight: 600;
font-size: 15px;
transition: transform var(--transition), box-shadow var(--transition), background var(--transition), border-color var(--transition), color var(--transition);
border: 1px solid transparent;
cursor: pointer;
white-space: nowrap;
}
.btn-primary {
background: var(--primary);
color: #fff;
}
.btn-primary:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-lg);
}
.btn-outline {
background: transparent;
color: var(--foreground);
border-color: var(--border);
}
.btn-outline:hover {
background: var(--accent);
border-color: var(--primary);
}
/* ===================== Hero ===================== */
.hero {
padding: 96px 0 72px;
text-align: center;
position: relative;
overflow: hidden;
}
.hero::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 60% 50% at 50% 0%, var(--primary-bg), transparent 70%);
pointer-events: none;
}
.hero > * { position: relative; }
.hero h1 {
font-size: clamp(36px, 7.2vw, 72px);
line-height: 1.02;
letter-spacing: -0.03em;
font-weight: 700;
margin: 0 0 24px;
}
.hero h1 .accent { color: var(--primary); }
.hero .subtitle {
font-size: clamp(16px, 1.5vw, 20px);
line-height: 1.55;
color: var(--muted-foreground);
max-width: 42rem;
margin: 0 auto 28px;
}
.hero-badges {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: 12px 14px;
margin-bottom: 40px;
font-size: 13px;
color: var(--muted-foreground);
font-family: var(--font-mono);
}
.hero-badges .sep { color: var(--neutral-400); }
.hero-ctas {
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
}
/* ===================== Section base ===================== */
.section {
padding: 80px 0;
border-top: 1px solid var(--border);
}
.section-head {
text-align: center;
margin-bottom: 56px;
}
.section-kicker {
font-family: var(--font-mono);
font-size: 12.5px;
color: var(--primary);
letter-spacing: 0.12em;
text-transform: uppercase;
margin-bottom: 14px;
font-weight: 500;
}
.section h2 {
font-size: clamp(30px, 4.2vw, 48px);
line-height: 1.1;
font-weight: 700;
margin: 0 0 14px;
letter-spacing: -0.02em;
}
.section-sub {
color: var(--muted-foreground);
font-size: 16.5px;
max-width: 40rem;
margin: 0 auto;
line-height: 1.6;
}
/* ===================== Grids ===================== */
.grid-4 {
display: grid;
gap: 20px;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1023px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 559px) { .grid-4 { grid-template-columns: 1fr; } }
.grid-steps {
display: grid;
gap: 20px;
grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1023px) { .grid-steps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 559px) { .grid-steps { grid-template-columns: 1fr; } }
.grid-apps {
display: grid;
gap: 20px;
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 767px) { .grid-apps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 479px) { .grid-apps { grid-template-columns: 1fr; } }
/* ===================== Card ===================== */
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-2xl);
padding: 24px;
transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}
.card:hover {
border-color: var(--primary-soft);
box-shadow: var(--shadow-lg);
transform: translateY(-2px);
}
.card .icon {
width: 40px; height: 40px;
display: grid; place-items: center;
border-radius: var(--radius-md);
background: var(--primary-bg);
color: var(--primary);
margin-bottom: 18px;
}
.card .icon svg { width: 20px; height: 20px; stroke-width: 1.6; }
.card h3 {
font-size: 17px;
margin: 0 0 8px;
font-weight: 600;
letter-spacing: -0.01em;
}
.card p {
margin: 0;
color: var(--muted-foreground);
font-size: 14.5px;
line-height: 1.55;
}
/* ===================== Step ===================== */
.step .num {
font-family: var(--font-mono);
font-size: 44px;
font-weight: 600;
color: var(--primary);
line-height: 1;
margin-bottom: 16px;
}
.step h3 {
font-size: 16px;
font-weight: 600;
margin: 0 0 14px;
}
.cmd {
font-family: var(--font-mono);
font-size: 13px;
background: var(--muted);
color: var(--foreground);
padding: 8px 12px;
border-radius: var(--radius-xs);
display: block;
white-space: nowrap;
overflow-x: auto;
max-width: 100%;
}
.cmd::-webkit-scrollbar { height: 0; }
/* ===================== App card ===================== */
.app-card h3 {
font-size: 15.5px;
font-weight: 600;
margin: 0 0 14px;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.tag {
font-family: var(--font-mono);
font-size: 11.5px;
background: var(--muted);
color: var(--muted-foreground);
padding: 3px 8px;
border-radius: var(--radius-xs);
}
/* ===================== Pipeline ===================== */
.pipeline-wrap {
max-width: 960px;
margin: 0 auto;
}
.pipeline {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
position: relative;
padding: 40px 0 32px;
}
.pipeline::before {
content: "";
position: absolute;
top: 47px;
left: 7%;
right: 7%;
height: 2px;
background: linear-gradient(to right,
var(--primary-soft),
var(--primary) 15%,
var(--primary) 85%,
var(--primary-soft));
z-index: 0;
opacity: 0.55;
}
.stage {
flex: 1;
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.stage .dot {
width: 14px; height: 14px;
border-radius: 50%;
background: var(--primary);
margin: 0 0 18px;
box-shadow:
0 0 0 4px var(--background),
0 0 0 6px var(--primary-soft);
}
.stage .num-sm {
font-family: var(--font-mono);
font-size: 11px;
color: var(--muted-foreground);
margin-bottom: 2px;
letter-spacing: 0.05em;
}
.stage .label {
font-size: 14px;
color: var(--foreground);
font-weight: 500;
}
@media (max-width: 767px) {
.pipeline {
flex-direction: column;
gap: 8px;
padding-left: 20px;
}
.pipeline::before {
top: 40px;
bottom: 40px;
left: 26px;
right: auto;
width: 2px;
height: auto;
background: linear-gradient(to bottom,
var(--primary-soft),
var(--primary) 15%,
var(--primary) 85%,
var(--primary-soft));
}
.stage {
flex-direction: row;
align-items: center;
gap: 14px;
text-align: left;
flex: none;
padding: 8px 0;
}
.stage .dot { margin: 0; flex-shrink: 0; }
.stage-meta { display: flex; flex-direction: column; }
}
/* ===================== FAQ ===================== */
.faq {
max-width: 760px;
margin: 0 auto;
}
.faq details {
border-bottom: 1px solid var(--border);
padding: 20px 4px;
}
.faq details:first-child { border-top: 1px solid var(--border); }
.faq details[open] summary { color: var(--primary); }
.faq summary {
list-style: none;
cursor: pointer;
font-weight: 600;
font-size: 16px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
transition: color var(--transition);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
content: "+";
font-family: var(--font-mono);
font-size: 22px;
color: var(--primary);
line-height: 1;
transition: transform var(--transition);
flex-shrink: 0;
}
.faq details[open] summary::after {
content: "";
}
.faq .answer {
color: var(--muted-foreground);
margin-top: 14px;
font-size: 15px;
line-height: 1.65;
}
/* ===================== Footer ===================== */
.site-footer {
border-top: 1px solid var(--border);
padding: 56px 0 32px;
}
.footer-grid {
display: grid;
gap: 32px;
grid-template-columns: 1.5fr 1fr 1fr 1fr;
}
@media (max-width: 767px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 479px) { .footer-grid { grid-template-columns: 1fr; } }
.footer-brand p {
color: var(--muted-foreground);
font-size: 14px;
margin: 14px 0 0;
line-height: 1.65;
max-width: 22rem;
}
.footer-col h4 {
font-size: 12px;
font-weight: 600;
margin: 0 0 16px;
color: var(--foreground);
text-transform: uppercase;
letter-spacing: 0.1em;
font-family: var(--font-mono);
}
.footer-col ul {
list-style: none;
padding: 0; margin: 0;
display: flex;
flex-direction: column;
gap: 10px;
}
.footer-col a {
color: var(--muted-foreground);
font-size: 14px;
transition: color var(--transition);
}
.footer-col a:hover { color: var(--primary); }
.copyright {
text-align: center;
margin-top: 48px;
padding-top: 24px;
border-top: 1px solid var(--border);
font-size: 13px;
color: var(--neutral-400);
font-family: var(--font-mono);
}
/* ===================== Focus ring ===================== */
:is(a, button, summary, .btn):focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
border-radius: 10px;
}
/* ===================== Fade-up ===================== */
.fade-up {
opacity: 0;
transform: translateY(14px);
transition:
opacity 520ms cubic-bezier(0.4, 0, 0.2, 1),
transform 520ms cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-up.visible {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.fade-up { opacity: 1; transform: none; transition: none; }
html { scroll-behavior: auto; }
}
/* ===================== Mobile tweaks ===================== */
@media (max-width: 639px) {
.hero { padding: 56px 0 48px; }
.section { padding: 64px 0; }
.section-head { margin-bottom: 40px; }
}
</style>
</head>
<body>
<!-- ============ Header ============ -->
<header class="site-header">
<div class="container">
<a href="#top" class="brand" aria-label="dotlog 首頁">
<span class="brand-dot" aria-hidden="true"></span>
<span>dotlog</span>
</a>
<nav class="nav" aria-label="主要導覽">
<a href="#features">功能特性</a>
<a href="#steps">文件</a>
<a href="#faq">FAQ</a>
<button class="theme-toggle" type="button" id="themeToggle" aria-label="切換深淺主題">
<svg class="moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
<svg class="sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
</svg>
</button>
<a href="#" class="btn btn-primary nav-github">在 GitHub 查看</a>
</nav>
</div>
</header>
<main id="top">
<!-- ============ Hero ============ -->
<section class="hero">
<div class="container">
<h1 class="fade-up">
把所有日誌管線<br/>
<span class="accent">串成一行</span>
</h1>
<p class="subtitle fade-up">
dotlog 是為工程師而生的 CLI 工具。一條指令完成擷取、過濾、聚合、輸出,取代雜亂的 shell pipeline 與多套 daemon。
</p>
<div class="hero-badges fade-up">
<span>⭐ 1.2k Stars</span>
<span class="sep">·</span>
<span>98% 測試通過</span>
<span class="sep">·</span>
<span>MIT 授權</span>
</div>
<div class="hero-ctas fade-up">
<a href="#steps" class="btn btn-primary">立即開始</a>
<a href="#" class="btn btn-outline">在 GitHub 查看</a>
</div>
</div>
</section>
<!-- ============ Why dotlog ============ -->
<section class="section" id="features">
<div class="container">
<div class="section-head fade-up">
<div class="section-kicker">Why dotlog</div>
<h2>為什麼選擇 dotlog</h2>
<p class="section-sub">不需要 YAML、不需要 daemon、不需要額外的容器。一支二進位檔裝了就能用。</p>
</div>
<div class="grid-4">
<article class="card fade-up">
<div class="icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
</div>
<h3>零配置啟動</h3>
<p>裝了就跑,不需要設定檔。<code>dotlog tap nginx</code> 一行搞定。</p>
</article>
<article class="card fade-up">
<div class="icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 10h18"/><path d="M8 14h2M8 17h5"/></svg>
</div>
<h3>全格式支援</h3>
<p>JSON、syslog、Apache、Nginx、K8s events 自動偵測並結構化。</p>
</article>
<article class="card fade-up">
<div class="icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h4l3-9 4 18 3-9h4"/></svg>
</div>
<h3>低資源佔用</h3>
<p>Rust 撰寫,單一二進位檔 6MB常駐記憶體不到 15MB。</p>
</article>
<article class="card fade-up">
<div class="icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/><polyline points="7 11 12 16 17 11"/><line x1="12" y1="4" x2="12" y2="16"/></svg>
</div>
<h3>原生輸出整合</h3>
<p>直接送進 S3、Loki、OpenTelemetry、Kafka無須轉接器。</p>
</article>
</div>
</div>
</section>
<!-- ============ Quick Start ============ -->
<section class="section" id="steps">
<div class="container">
<div class="section-head fade-up">
<div class="section-kicker">Quick Start</div>
<h2>5 分鐘上手</h2>
<p class="section-sub">四個指令,把你的伺服器日誌送到雲端。</p>
</div>
<div class="grid-steps">
<article class="step card fade-up">
<div class="num">01</div>
<h3>安裝</h3>
<code class="cmd">brew install dotlog</code>
</article>
<article class="step card fade-up">
<div class="num">02</div>
<h3>初始化</h3>
<code class="cmd">dotlog init</code>
</article>
<article class="step card fade-up">
<div class="num">03</div>
<h3>指定來源</h3>
<code class="cmd">dotlog tap nginx</code>
</article>
<article class="step card fade-up">
<div class="num">04</div>
<h3>串接輸出</h3>
<code class="cmd">dotlog pipe → s3</code>
</article>
</div>
</div>
</section>
<!-- ============ Integrations ============ -->
<section class="section">
<div class="container">
<div class="section-head fade-up">
<div class="section-kicker">Integrations</div>
<h2>你正在用的工具,它都支援</h2>
<p class="section-sub">開箱即用 60+ 種資料來源與 20+ 種輸出目標。</p>
</div>
<div class="grid-apps">
<article class="card app-card fade-up">
<h3>Web 伺服器</h3>
<div class="tag-list">
<span class="tag">nginx</span><span class="tag">apache</span><span class="tag">caddy</span><span class="tag">traefik</span>
</div>
</article>
<article class="card app-card fade-up">
<h3>容器</h3>
<div class="tag-list">
<span class="tag">docker</span><span class="tag">kubernetes</span><span class="tag">containerd</span><span class="tag">podman</span>
</div>
</article>
<article class="card app-card fade-up">
<h3>資料庫</h3>
<div class="tag-list">
<span class="tag">postgres</span><span class="tag">mysql</span><span class="tag">redis</span><span class="tag">mongo</span>
</div>
</article>
<article class="card app-card fade-up">
<h3>雲端服務</h3>
<div class="tag-list">
<span class="tag">aws-s3</span><span class="tag">gcs</span><span class="tag">cloudwatch</span><span class="tag">azure-logs</span>
</div>
</article>
<article class="card app-card fade-up">
<h3>訊息佇列</h3>
<div class="tag-list">
<span class="tag">kafka</span><span class="tag">nats</span><span class="tag">rabbitmq</span><span class="tag">sqs</span>
</div>
</article>
<article class="card app-card fade-up">
<h3>監控</h3>
<div class="tag-list">
<span class="tag">loki</span><span class="tag">datadog</span><span class="tag">otel</span><span class="tag">prometheus</span>
</div>
</article>
</div>
</div>
</section>
<!-- ============ Pipeline ============ -->
<section class="section">
<div class="container">
<div class="section-head fade-up">
<div class="section-kicker">Core Pipeline</div>
<h2>七個階段的完整流水線</h2>
<p class="section-sub">每一階段都能被單獨替換、停用或擴充。</p>
</div>
<div class="pipeline-wrap fade-up">
<div class="pipeline" role="list">
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">01</span>
<span class="label">擷取</span>
</div>
</div>
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">02</span>
<span class="label">解析</span>
</div>
</div>
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">03</span>
<span class="label">正規化</span>
</div>
</div>
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">04</span>
<span class="label">路由</span>
</div>
</div>
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">05</span>
<span class="label">過濾</span>
</div>
</div>
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">06</span>
<span class="label">聚合</span>
</div>
</div>
<div class="stage" role="listitem">
<div class="dot" aria-hidden="true"></div>
<div class="stage-meta">
<span class="num-sm">07</span>
<span class="label">輸出</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ============ FAQ ============ -->
<section class="section" id="faq">
<div class="container">
<div class="section-head fade-up">
<div class="section-kicker">FAQ</div>
<h2>常見問題</h2>
</div>
<div class="faq fade-up">
<details>
<summary>dotlog 的授權是什麼?</summary>
<div class="answer">採用 MIT 授權,商用、修改、再散布都沒有限制,無需付費。</div>
</details>
<details>
<summary>效能表現如何?</summary>
<div class="answer">在單一 vCPU 上可處理約 120k events/秒,約為 Fluentd 的 4 倍,記憶體佔用不到 1/5。</div>
</details>
<details>
<summary>與 Fluentd / Vector / Filebeat 有什麼差異?</summary>
<div class="answer">dotlog 強調 <strong>CLI 優先與零配置</strong>:用熟悉的 shell 就能組裝管線,無需學習自訂 DSL也不需要部署守護程序。適合需要快速串接或臨時任務的場景。</div>
</details>
<details>
<summary>支援哪些部署方式?</summary>
<div class="answer">單一靜態二進位檔,直接在 macOS、Linux、Windows 執行;也提供官方 Docker image 與 Helm chart。</div>
</details>
<details>
<summary>資料會經過你們的伺服器嗎?</summary>
<div class="answer">完全不會。dotlog 是純本地執行的工具,所有日誌只在你指定的來源與輸出之間傳遞,專案本身不收集任何遙測資料(可用 <code>--telemetry=off</code> 再次關閉驗證)。</div>
</details>
</div>
</div>
</section>
</main>
<!-- ============ Footer ============ -->
<footer class="site-footer">
<div class="container">
<div class="footer-grid">
<div class="footer-brand">
<div class="brand">
<span class="brand-dot" aria-hidden="true"></span>
<span>dotlog</span>
</div>
<p>把所有日誌管線串成一行。為工程師而生的開源 CLI 工具。</p>
</div>
<div class="footer-col">
<h4>產品</h4>
<ul>
<li><a href="#features">功能特性</a></li>
<li><a href="#steps">快速上手</a></li>
<li><a href="#">更新日誌</a></li>
</ul>
</div>
<div class="footer-col">
<h4>資源</h4>
<ul>
<li><a href="#">文件</a></li>
<li><a href="#">GitHub</a></li>
<li><a href="#">社群討論</a></li>
</ul>
</div>
<div class="footer-col">
<h4>法律</h4>
<ul>
<li><a href="#">授權條款</a></li>
<li><a href="#">隱私政策</a></li>
</ul>
</div>
</div>
<div class="copyright">© 2026 dotlog · MIT License</div>
</div>
</footer>
<script>
// ==== Theme toggle ====
(function () {
const root = document.documentElement;
const toggle = document.getElementById('themeToggle');
const stored = localStorage.getItem('dotlog-theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (stored === 'dark' || (!stored && prefersDark)) {
root.classList.add('dark');
}
toggle.addEventListener('click', () => {
root.classList.toggle('dark');
localStorage.setItem('dotlog-theme', root.classList.contains('dark') ? 'dark' : 'light');
});
})();
// ==== Fade-up on scroll ====
(function () {
const items = document.querySelectorAll('.fade-up');
if (!('IntersectionObserver' in window)) {
items.forEach((el) => el.classList.add('visible'));
return;
}
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add('visible');
io.unobserve(e.target);
}
});
}, { threshold: 0.08, rootMargin: '0px 0px -40px 0px' });
items.forEach((el) => io.observe(el));
})();
</script>
</body>
</html>