ΠΡΡΠΎΠΊΠΎΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΈ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½Π°Ρ ΠΏΠΎ ΠΏΠ°ΠΌΡΡΠΈ ΡΡΠΈΠ»ΠΈΡΠ° Π΄Π»Ρ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΡ Π»ΠΎΠ³ΠΎΠ², ΠΊΠΎΡΠΎΡΠ°Ρ ΠΌΠΎΠΆΠ΅Ρ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°ΡΡ ΡΠ°ΠΉΠ»Ρ Π»ΠΎΠ³ΠΎΠ² Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΌΠ΅ΡΠΎΠΊ, Π° Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΡΡΡΠΎΠΊ. ΠΠ΄Π΅Π°Π»ΡΠ½ΠΎ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΠΈΡ Π΄Π»Ρ ΡΠΎΡΠ½ΠΎΠ³ΠΎ Π°Π½Π°Π»ΠΈΠ·Π° Π΄Π°Π½Π½ΡΡ Π»ΠΎΠ³ΠΎΠ² Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ.
- ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ: ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π»ΠΎΠ³ΠΎΠ² Π·Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠΉ ΠΏΡΠΎΠΌΠ΅ΠΆΡΡΠΎΠΊ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ 10 ΠΌΠΈΠ½ΡΡ)
- ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π±ΠΈΠ½Π°ΡΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΈΡΠΊΠ°: ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ Π½Π°Ρ ΠΎΠ΄ΠΈΡ Π½Π°ΡΠ°Π»ΡΠ½ΡΡ ΠΏΠΎΠ·ΠΈΡΠΈΡ Π² Π±ΠΎΠ»ΡΡΠΈΡ ΡΠ°ΠΉΠ»Π°Ρ Π»ΠΎΠ³ΠΎΠ²
- 25+ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΡ ΡΠΎΡΠΌΠ°ΡΠΎΠ² Π»ΠΎΠ³ΠΎΠ²: ΠΠ΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ Π½Π°ΡΡΡΠΎΠΉΠΊΠ° Π΄Π»Ρ ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½Π΅Π½Π½ΡΡ ΡΠΈΠΏΠΎΠ² Π»ΠΎΠ³ΠΎΠ²
- ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΏΠΎ ΠΏΠ°ΠΌΡΡΠΈ: ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π±ΡΡΠ΅ΡΠΎΠΌ Π΄Π»Ρ Π½ΠΈΠ·ΠΊΠΎΠ³ΠΎ ΠΏΠΎΡΡΠ΅Π±Π»Π΅Π½ΠΈΡ ΠΏΠ°ΠΌΡΡΠΈ
- ΠΡΡΠΎΠΊΠ°Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ: Π Π°Π·ΡΠ°Π±ΠΎΡΠ°Π½ΠΎ Π΄Π»Ρ ΡΠΊΠΎΡΠΎΡΡΠΈ Ρ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΠΌΠΈ Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΡΠΌΠΈ ΠΏΠ°ΠΌΡΡΠΈ
- ΠΠ±ΡΠ°ΡΠ½Π°Ρ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ: Π‘ΠΎΡ ΡΠ°Π½ΡΠ΅Ρ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ API Ρ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΠΎΠΉ Π²Π΅ΡΡΠΈΠ΅ΠΉ
go install github.com/sakateka/ttail/cmd/ttail@latest
ΠΠ»ΠΈ ΡΠ±ΠΎΡΠΊΠ° ΠΈΠ· ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°:
git clone https://github.com/sakateka/ttail.git
cd ttail
go build ./cmd/ttail
# ΠΡΡΠ»Π΅Π΄ΠΈΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ 10 ΡΠ΅ΠΊΡΠ½Π΄ ΠΎΡ ΡΠ΅ΠΊΡΡΠ΅Π³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ
ttail -n 10s /var/log/app.log
# ΠΡΡΠ»Π΅Π΄ΠΈΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ 5 ΠΌΠΈΠ½ΡΡ ΠΎΡ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΌΠ΅ΡΠΊΠΈ Π² ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΉ ΡΡΡΠΎΠΊΠ΅
ttail -n 5m -l /var/log/app.log
# ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΉ ΡΠΈΠΏ Π»ΠΎΠ³Π° (ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π΅ Π½ΡΠΆΠ΅Π½!)
ttail -n 1h -t apache /var/log/apache/access.log
# ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠΉ ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ
ttail -n 30s -t custom_format -c /path/to/config.toml /var/log/app.log
# ΠΠΊΠ»ΡΡΠΈΡΡ ΠΎΡΠ»Π°Π΄ΠΎΡΠ½ΡΠΉ Π²ΡΠ²ΠΎΠ΄
ttail -d -n 30s /var/log/app.log
-n duration
: ΠΡΠΎΠΌΠ΅ΠΆΡΡΠΎΠΊ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π΄Π»Ρ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΡ (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ: 10s)-l
: ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΌΠ΅ΡΠΊΡ ΠΈΠ· ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΉ ΡΡΡΠΎΠΊΠΈ Π²ΠΌΠ΅ΡΡΠΎ ΡΠ΅ΠΊΡΡΠ΅Π³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ-t type
: Π’ΠΈΠΏ Π»ΠΎΠ³Π° (ΡΠΌ. ΠΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΡΠΈΠΏΡ Π»ΠΎΠ³ΠΎΠ² Π½ΠΈΠΆΠ΅)-c config
: ΠΡΡΡ ΠΊ ΡΠ°ΠΉΠ»Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ (Π½Π΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ)-d
: ΠΠΊΠ»ΡΡΠΈΡΡ ΠΎΡΠ»Π°Π΄ΠΎΡΠ½ΡΠΉ Π²ΡΠ²ΠΎΠ΄
10s
- 10 ΡΠ΅ΠΊΡΠ½Π΄5m
- 5 ΠΌΠΈΠ½ΡΡ2h
- 2 ΡΠ°ΡΠ°1h30m
- 1 ΡΠ°Ρ 30 ΠΌΠΈΠ½ΡΡ
TTail Π²ΠΊΠ»ΡΡΠ°Π΅Ρ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ Π±ΠΎΠ»Π΅Π΅ 25 ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½Π΅Π½Π½ΡΡ ΡΠΎΡΠΌΠ°ΡΠΎΠ² Π»ΠΎΠ³ΠΎΠ². Π€Π°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ!
apache
,apache_common
,apache_combined
- ΠΠΎΠ³ΠΈ Π΄ΠΎΡΡΡΠΏΠ° Apachenginx
- ΠΠΎΠ³ΠΈ Π΄ΠΎΡΡΡΠΏΠ° Nginx (ΡΠΎΡΠΌΠ°Ρ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ)nginx_iso
- Nginx Ρ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΌΠΈ ΠΌΠ΅ΡΠΊΠ°ΠΌΠΈ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ ISO
java
- ΠΠΎΠ³ΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Java (2023-12-25 10:30:45
)java_iso
- Java Ρ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΌΠΈ ΠΌΠ΅ΡΠΊΠ°ΠΌΠΈ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ ISO (2023-12-25T10:30:45
)python
- Π€ΠΎΡΠΌΠ°Ρ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Pythongo
- Π‘ΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΡΠΎΡΠΌΠ°Ρ Π»ΠΎΠ³ΠΎΠ² Go (2023/12/25 10:30:45
)rails
- ΠΠΎΠ³ΠΈ Ruby on Railsdjango
- ΠΠΎΠ³ΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Django
docker
- ΠΠΎΠ³ΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠ² Docker (Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΌΠ΅ΡΠΊΠΈ Π² UTC)docker_local
- Docker Ρ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠΌ ΡΠ°ΡΠΎΠ²ΡΠΌ ΠΏΠΎΡΡΠΎΠΌkubernetes
- ΠΠΎΠ³ΠΈ ΠΏΠΎΠ΄ΠΎΠ² Kubernetes
mysql
- ΠΠΎΠ³ΠΈ ΠΎΡΠΈΠ±ΠΎΠΊ MySQLmysql_general
- ΠΠ±ΡΠΈΠ΅ Π»ΠΎΠ³ΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ² MySQLpostgresql
- ΠΠΎΠ³ΠΈ PostgreSQLelasticsearch
- ΠΠΎΠ³ΠΈ Elasticsearch
kern
- ΠΠΎΠ³ΠΈ ΡΠ΄ΡΠ°/ΡΠΈΡΡΠ΅ΠΌΡ (journalctl, systemd)syslog
- Π’ΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΠΉ syslog (RFC 3164)syslog_rfc5424
- Π‘ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΉ syslog (RFC 5424)tskv
- Π€ΠΎΡΠΌΠ°Ρ ΠΊΠ»ΡΡ-Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅, ΡΠ°Π·Π΄Π΅Π»Π΅Π½Π½ΡΠΉ ΡΠ°Π±ΡΠ»ΡΡΠΈΠ΅ΠΉ (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ)
json
- JSON Π»ΠΎΠ³ΠΈ Ρ ΠΏΠΎΠ»Π΅ΠΌtimestamp
json_time
- JSON Π»ΠΎΠ³ΠΈ Ρ ΠΏΠΎΠ»Π΅ΠΌtime
logstash
- Π€ΠΎΡΠΌΠ°Ρ JSON Logstash
# ΠΠΎΠ³ΠΈ Π΄ΠΎΡΡΡΠΏΠ° Apache
ttail -n 1h -t apache /var/log/apache2/access.log
# ΠΠΎΠ³ΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠ² Docker
ttail -n 30m -t docker /var/lib/docker/containers/*/container.log
# ΠΠΎΠ³ΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Java
ttail -n 15m -l -t java /var/log/myapp/application.log
# ΠΠΎΠ³ΠΈ ΠΏΠΎΠ΄ΠΎΠ² Kubernetes
kubectl logs pod-name | ttail -n 10m -t kubernetes
# Π‘ΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ Π»ΠΎΠ³ΠΈ
ttail -n 2h -t kern /var/log/kern.log
ΠΡ Π²ΡΠ΅ Π΅ΡΠ΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ ΡΠΎΡΠΌΠ°ΡΡ Π»ΠΎΠ³ΠΎΠ² Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠ°ΠΉΠ»Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ TOML:
[custom_app]
timeReStr = 'timestamp=(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})'
timeLayout = "2006-01-02T15:04:05"
bufSize = 16384
stepsLimit = 1024
timeReStr
: Π Π΅Π³ΡΠ»ΡΡΠ½ΠΎΠ΅ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΡ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΌΠ΅ΡΠΊΠΈ (ΠΏΠ΅ΡΠ²Π°Ρ Π·Π°Ρ Π²Π°ΡΡΠ²Π°ΡΡΠ°Ρ Π³ΡΡΠΏΠΏΠ°)timeLayout
: Π€ΠΎΡΠΌΠ°Ρ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Go Π΄Π»Ρ ΡΠ°Π·Π±ΠΎΡΠ° Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΌΠ΅ΡΠΎΠΊbufSize
: Π Π°Π·ΠΌΠ΅Ρ Π±ΡΡΠ΅ΡΠ° Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡ ΡΠ°ΠΉΠ»Π° (Π² Π±Π°ΠΉΡΠ°Ρ , Π½Π΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ)stepsLimit
: ΠΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠ°Π³ΠΎΠ² Π΄Π»Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΈΡΠΊΠ° (Π½Π΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ)
package main
import (
"os"
"time"
"github.com/sakateka/ttail"
)
func main() {
file, err := os.Open("/var/log/app.log")
if err != nil {
panic(err)
}
defer file.Close()
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° TFile
tfile := ttail.NewTimeFile(file,
ttail.WithDuration(5*time.Minute),
ttail.WithTimeFromLastLine(true),
)
// ΠΠ°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠΏΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠΉ Π½Π°ΡΠ°Π»ΡΠ½ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ
err = tfile.FindPosition()
if err != nil {
panic(err)
}
// ΠΠΎΠΏΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅ΠΉ ΡΠ°ΡΡΠΈ Π² stdout
_, err = tfile.CopyTo(os.Stdout)
if err != nil {
panic(err)
}
}
// ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΡ
ΡΠΈΠΏΠΎΠ² Π»ΠΎΠ³ΠΎΠ²
tfile, err := ttail.NewTFileWithConfig(
file,
"", // ΠΏΡΡΡΠΎΠΉ ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΡΠΈΠΏΡ
"apache",
10*time.Minute,
true,
)
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΡ
ΠΎΠΏΡΠΈΠΉ
tfile := ttail.NewTimeFile(file,
ttail.WithDuration(1*time.Hour),
ttail.WithBufSize(32768),
ttail.WithStepsLimit(2048),
ttail.WithTimeReAsStr(`(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})`),
ttail.WithTimeLayout("2006-01-02 15:04:05"),
)
ΠΠΎΠ΄Π΅ΡΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ttail ΠΎΡΠ³Π°Π½ΠΈΠ·ΠΎΠ²Π°Π½ Π² Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠΏΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ²:
internal/config
: Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠ΅ΠΉ ΠΈ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΡΠΈΠΏΡ Π»ΠΎΠ³ΠΎΠ²internal/parser
: Π Π°Π·Π±ΠΎΡ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΌΠ΅ΡΠΎΠΊ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΡΠ΅Π³ΡΠ»ΡΡΠ½ΡΡ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉinternal/buffer
: ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½Π°Ρ Π±ΡΡΠ΅ΡΠΈΠ·Π°ΡΠΈΡ ΡΡΡΠΎΠΊ ΠΈ ΡΡΠ΅Π½ΠΈΠ΅internal/searcher
: Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π±ΠΈΠ½Π°ΡΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠΈΡΠΊΠ° Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ
-
ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΏΠΎ ΠΏΠ°ΠΌΡΡΠΈ:
- ΠΠ½ΠΎΠ³ΠΎΡΠ°Π·ΠΎΠ²ΡΠ΅ Π±ΡΡΠ΅ΡΡ Π΄Π»Ρ ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΠΉ ΠΏΠ°ΠΌΡΡΠΈ
- ΠΠ°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌΡΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΡ Π±ΡΡΠ΅ΡΠΎΠ² Π΄Π»Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ ΡΡΠ΅Π½Π°ΡΠΈΠ΅Π² ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
- ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½ΡΠΉ ΡΠ°Π·Π±ΠΎΡ ΡΡΡΠΎΠΊ Π±Π΅Π· Π½Π΅Π½ΡΠΆΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°Π½ΠΈΡ
-
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΠΏΠΎΠΈΡΠΊΠ°:
- ΠΠΈΠ½Π°ΡΠ½ΡΠΉ ΠΏΠΎΠΈΡΠΊ Π΄Π»Ρ Π±ΠΎΠ»ΡΡΠΈΡ ΡΠ°ΠΉΠ»ΠΎΠ²
- ΠΠ½ΡΠ΅Π»Π»Π΅ΠΊΡΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π±ΡΡΠ΅ΡΠ°
- ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΉ Π²Π²ΠΎΠ΄Π°-Π²ΡΠ²ΠΎΠ΄Π°
-
ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΡΠ°:
- ΠΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΡΠ΅Π³ΡΠ»ΡΡΠ½ΡΡ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉ
- ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΡΠΎ ΡΡΡΠΎΠΊΠ°ΠΌΠΈ
- Π£ΠΌΠ΅Π½ΡΡΠ΅Π½ΠΈΠ΅ Π½Π°ΠΊΠ»Π°Π΄Π½ΡΡ ΡΠ°ΡΡ ΠΎΠ΄ΠΎΠ² Π½Π° Π²ΡΠ·ΠΎΠ²Ρ ΡΡΠ½ΠΊΡΠΈΠΉ
ΠΠ°ΠΏΡΡΡΠΈΡΠ΅ ΠΏΠΎΠ»Π½ΡΠΉ Π½Π°Π±ΠΎΡ ΡΠ΅ΡΡΠΎΠ²:
# ΠΠ°ΠΏΡΡΡΠΈΡΡ Π²ΡΠ΅ ΡΠ΅ΡΡΡ
go test ./...
# ΠΠ°ΠΏΡΡΡΠΈΡΡ ΡΠ΅ΡΡΡ Ρ ΠΏΠΎΠΊΡΡΡΠΈΠ΅ΠΌ
go test -cover ./...
# ΠΠ°ΠΏΡΡΡΠΈΡΡ Π±Π΅Π½ΡΠΌΠ°ΡΠΊΠΈ
go test -bench=. ./...
# ΠΡΠΎΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠ΅ ΡΠΈΠΏΡ Π»ΠΎΠ³ΠΎΠ²
go test -v ./internal/config -run TestBuiltinLogTypes
ΠΠΎΠ΄Π΅ΡΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½Π°Ρ Π²Π΅ΡΡΠΈΡ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ»ΡΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ:
- ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠ°ΠΌΡΡΠΈ: Π‘Π½ΠΈΠΆΠ΅Π½ΠΈΠ΅ Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΠΉ ΠΏΠ°ΠΌΡΡΠΈ Π½Π° 40%
- Π‘ΠΊΠΎΡΠΎΡΡΡ ΠΏΠΎΠΈΡΠΊΠ°: ΠΠΈΠ½Π°ΡΠ½ΡΠΉ ΠΏΠΎΠΈΡΠΊ Π½Π° 60% Π±ΡΡΡΡΠ΅Π΅
- ΠΡΠΎΠΏΡΡΠΊΠ½Π°Ρ ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡΡ: Π£Π»ΡΡΡΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π΄Π°Π½Π½ΡΡ Π½Π° 25%
ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ttail ΠΎΠΆΠΈΠ΄Π°Π΅Ρ Π»ΠΎΠ³ΠΈ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ TSKV (Tab-Separated Key-Value):
timestamp=2023-12-25T10:30:45 level=info msg=example log entry
Π Π΅Π³ΡΠ»ΡΡΠ½ΠΎΠ΅ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ: \ttimestamp=(\d{4}-\d{2}-\d{2}T\d\d:\d\d:\d\d)\t
ttail ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ:
- Π€Π°ΠΉΠ» Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½: Π§Π΅ΡΠΊΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅
- ΠΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΌΠ΅ΡΠΊΠΈ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Ρ: ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ ΠΊ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²ΡΠ΅Π³ΠΎ ΡΠ°ΠΉΠ»Π°
- ΠΠ΅Π²Π΅ΡΠ½ΡΠΉ ΡΠΎΡΠΌΠ°Ρ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΌΠ΅ΡΠΊΠΈ: ΠΡΠΎΠΏΡΡΠΊΠ°Π΅Ρ Π½Π΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠ΅ Π·Π°ΠΏΠΈΡΠΈ
- ΠΠΎΠ»ΡΡΠΈΠ΅ ΡΠ°ΠΉΠ»Ρ: ΠΡΡΠ΅ΠΊΡΠΈΠ²Π½Π°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π±Π΅Π· ΠΏΡΠΎΠ±Π»Π΅ΠΌ Ρ ΠΏΠ°ΠΌΡΡΡΡ
- Π‘Π΄Π΅Π»Π°ΠΉΡΠ΅ ΡΠΎΡΠΊ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΡ
- Π‘ΠΎΠ·Π΄Π°ΠΉΡΠ΅ Π²Π΅ΡΠΊΡ Π΄Π»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎΡΡΠΈ
- ΠΠΎΠ±Π°Π²ΡΡΠ΅ ΡΠ΅ΡΡΡ Π΄Π»Ρ Π½ΠΎΠ²ΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎΡΡΠΈ
- Π£Π±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ Π²ΡΠ΅ ΡΠ΅ΡΡΡ ΠΏΡΠΎΡ ΠΎΠ΄ΡΡ
- ΠΡΠΏΡΠ°Π²ΡΡΠ΅ pull request
git clone https://github.com/sakateka/ttail.git
cd ttail
go mod download
go test ./...
Π§ΡΠΎΠ±Ρ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π½ΠΎΠ²ΡΠΉ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΉ ΡΠΈΠΏ Π»ΠΎΠ³Π°, ΠΎΡΡΠ΅Π΄Π°ΠΊΡΠΈΡΡΠΉΡΠ΅ internal/config/config.go
:
"myformat": LogType{
TimeReStr: `^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})`,
TimeLayout: "2006-01-02 15:04:05",
},
ΠΠ°ΡΠ΅ΠΌ Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ ΡΠ΅ΡΡΡ Π² internal/config/builtin_types_test.go
.
MIT License
Copyright (c) 2023 ttail contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ΠΠΎΠ»Π½Π°Ρ ΡΠ΅ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡ ΠΊΠΎΠ΄Π° Π² ΡΠΏΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ
- 25+ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΡ ΡΠΈΠΏΠΎΠ² ΡΠΎΡΠΌΠ°ΡΠΎΠ² Π»ΠΎΠ³ΠΎΠ² (ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π΅ Π½ΡΠΆΠ΅Π½)
- ΠΠ½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ»ΡΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ
- ΠΠΎΠ²ΡΡΠ΅Π½Π½Π°Ρ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΏΠ°ΠΌΡΡΠΈ
- ΠΡΠ΅ΡΡΠΎΡΠΎΠ½Π½Π΅Π΅ ΡΠ΅ΡΡΠΎΠ²ΠΎΠ΅ ΠΏΠΎΠΊΡΡΡΠΈΠ΅
- ΠΠ±ΡΠ°ΡΠ½ΠΎ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΡΠΉ API
- Π£Π»ΡΡΡΠ΅Π½Π½Π°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ
- Π£Π»ΡΡΡΠ΅Π½Π½Π°Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ
- ΠΠ°Π·ΠΎΠ²Π°Ρ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎΡΡΡ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΡ ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ
- ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΡΠΎΡΠΌΠ°ΡΠ° TSKV
- ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΡΠ°ΠΉΠ»Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ