Mở đầu: Câu chuyện từ đỉnh điểm 11.11
Năm ngoái, tôi đang quản lý hệ thống AI cho một nền tảng thương mại điện tử lớn tại Trung Quốc. Khi chiến dịch 11.11 bắt đầu, lưu lượng truy cập tăng đột biến 3000% trong vòng 15 phút. Vào lúc 23:47 — chỉ còn 13 phút nữa là hết khuyến mãi — toàn bộ hệ thống Dify của tôi bị treo. Không có log, không có metrics, không có gì ngoài màn hình trắng chết chóc.
Đó là khoảnh khắc tôi nhận ra: Dify mặc định chỉ lưu log vào file cục bộ. Khi container restart, log biến mất. Khi 50 worker chạy song song, log lẫn nhau. Khi cần debug latency spike ở production, tôi phải SSH vào từng máy.
Sau 72 giờ không ngủ, tôi xây dựng hệ thống ELK Stack để aggregate toàn bộ log từ Dify. Kết quả: lần peak tiếp theo, tôi phát hiện và fix bottleneck trong 8 phút thay vì 3 giờ. Bài viết này là tất cả những gì tôi đã học được — viết lại từ đầu để bạn không phải đi vòng như tôi.
ELK Stack là gì và tại sao cần cho Dify
ELK Stack bao gồm ba thành phần chính:
- Elasticsearch — Database NoSQL chuyên lưu trữ và tìm kiếm log theo thời gian thực
- Logstash — Pipeline xử lý log, parse JSON, filter, transform dữ liệu
- Kibana — Giao diện web trực quan để visualize và query log
Với Dify, mỗi API request tạo ra nhiều loại log khác nhau: request/response, database query, LLM API call, embedding operation. Khi có 1000+ requests/phút, việc grep log thủ công là bất khả thi.
Kiến trúc tổng thể
┌─────────────────────────────────────────────────────────────────┐
│ Dify Containers │
├─────────────┬─────────────┬─────────────┬─────────────────────┤
│ API Server │ Worker │ Web App │ Celery Beat │
│ Port 80 │ Background │ Port 80 │ Scheduler │
└──────┬──────┴──────┬──────┴──────┬──────┴──────────┬──────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Filebeat Agent │
│ (Tail every Dify log file) │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Logstash Server │
│ (Parse → Filter → Enrich → Output) │
└────────────────────────────┬────────────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Elasticsearch │ │ Kafka/Redis │ │ Dead Letter │
│ Cluster │ │ (Optional) │ │ Queue │
└────────┬────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Kibana Dashboard │
│ (Visualize, Search, Alert, Analyze) │
└─────────────────────────────────────────────────────────────────┘
Triển khai Step-by-Step
Bước 1: Cài đặt ELK Stack với Docker Compose
Tạo file
elk/docker-compose.yml với cấu hình tối ưu cho hệ thống vừa và nhỏ (4GB RAM tối thiểu):
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
container_name: elasticsearch
environment:
- node.name=elasticsearch
- cluster.name=dify-logs-cluster
- discovery.type=single-node
- bootstrap.memory_lock=true
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms2g -Xmx2g"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
networks:
- elk
logstash:
image: docker.elastic.co/logstash/logstash:8.11.0
container_name: logstash
volumes:
- ./pipeline:/usr/share/logstash/pipeline:ro
- ./config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro
ports:
- "5044:5044"
- "5000:5000/tcp"
- "5000:5000/udp"
- "9600:9600"
environment:
- "LS_JAVA_OPTS=-Xms512m -Xmx512m"
networks:
- elk
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:8.11.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
networks:
- elk
depends_on:
- elasticsearch
volumes:
elasticsearch_data:
driver: local
networks:
elk:
driver: bridge
Bước 2: Cấu hình Logstash Pipeline
Tạo file
elk/pipeline/dify.conf — đây là phần quan trọng nhất để parse log từ Dify:
input {
beats {
port => 5044
host => "0.0.0.0"
}
}
filter {
# Parse JSON log entries from Dify
if [message] =~ /^\{/ {
json {
source => "message"
target => "parsed"
skip_on_invalid_json => true
}
if [parsed] {
# Extract Dify log fields
mutate {
add_field => {
"dify_app_id" => "%{[parsed][app_id]}"
"dify_conversation_id" => "%{[parsed][conversation_id]}"
"dify_message_id" => "%{[parsed][message_id]}"
"dify_latency_ms" => "%{[parsed][latency]}"
"dify_model" => "%{[parsed][model]}"
"dify_provider" => "%{[parsed][provider]}"
"dify_error" => "%{[parsed][error]}"
"dify_tokens" => "%{[parsed][tokens]}"
}
}
# Convert latency to integer for aggregations
if [dify_latency_ms] {
mutate {
convert => { "dify_latency_ms" => "integer" }
}
}
# Tag error logs for alerting
if [dify_error] and [dify_error] != "" {
mutate {
add_tag => ["error", "dify_error"]
}
}
# Tag slow requests (> 3000ms)
if [dify_latency_ms] and [dify_latency_ms] > 3000 {
mutate {
add_tag => ["slow_request", "latency_alert"]
}
}
# Parse timestamp
if [parsed][created_at] {
date {
match => ["[parsed][created_at]", "UNIX"]
target => "@timestamp"
}
}
}
}
# Handle plain text logs (fallback)
else {
grok {
match => {
"message" => "\[%{TIMESTAMP_ISO8601:timestamp}\] %{LOGLEVEL:level} %{DATA:module}: %{GREEDYDATA:content}"
}
tag_on_failure => ["_grokparsefailure"]
}
}
# Add metadata
mutate {
add_field => {
"environment" => "production"
"service" => "dify"
"[@metadata][index_prefix]" => "dify-logs"
}
}
# Enrich with GeoIP if client_ip exists
if [parsed][client_ip] {
geoip {
source => "[parsed][client_ip]"
target => "geoip"
database => "/usr/share/GeoIP/GeoLite2-City.mmdb"
tag_on_failure => ["_geoip_lookup_failure"]
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "%{[@metadata][index_prefix]}-%{+YYYY.MM.dd}"
document_type => "_doc"
}
# Debug output (disable in production)
# stdout { codec => rubydebug }
# Send errors to separate index for alerting
if "error" in [tags] {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "dify-errors-%{+YYYY.MM.dd}"
}
}
}
Bước 3: Cài đặt Filebeat trên Dify Host
Tạo file
filebeat/filebeat.yml để thu thập log từ Dify:
filebeat.inputs:
# Dify API Server Logs
- type: log
enabled: true
paths:
- /var/lib/docker/containers/*/dify-api-*.log
fields:
component: api
service: dify
fields_under_root: true
json.keys_under_root: true
json.add_error_key: true
json.message_key: message
# Dify Worker Logs
- type: log
enabled: true
paths:
- /var/lib/docker/containers/*/dify-worker-*.log
fields:
component: worker
service: dify
fields_under_root: true
# Nginx Access Logs (if using reverse proxy)
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
component: nginx
service: dify
fields_under_root: true
Processors for enrichment
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata: ~
- decode_json_fields:
fields: ["message"]
target: ""
overwrite_keys: true
add_error_key: true
Output to Logstash
output.logstash:
hosts: ["elk-logstash:5044"]
ssl.enabled: false
Logging configuration
logging.level: info
logging.to_files: true
logging.files:
path: /var/log/filebeat
name: filebeat
keepfiles: 7
permissions: 0644
ILM Policy (Index Lifecycle Management)
setup.ilm.enabled: true
setup.ilm.rollover_alias: "dify-logs"
setup.ilm.pattern: "{now/d}-000001"
setup.ilm.policy_name: "dify-logs-policy"
Bước 4: Instrument Dify Code để gửi Custom Logs
Bây giờ tôi sẽ hướng dẫn cách modify Dify source code để gửi structured logs. Trước tiên, tạo helper module:
# dify_logging/helper.py
import json
import logging
import time
from datetime import datetime
from functools import wraps
from typing import Any, Dict, Optional
from pythonjsonlogger import jsonlogger
class DifyJsonFormatter(jsonlogger.JsonFormatter):
"""Custom JSON formatter for Dify logs with ELK-friendly format"""
def add_fields(self, log_record, record, message_dict):
super().add_fields(log_record, record, message_dict)
log_record['timestamp'] = datetime.utcnow().isoformat()
log_record['service'] = 'dify'
log_record['version'] = '1.0'
log_record['level'] = record.levelname
def setup_structured_logging(app_name: str = "dify") -> logging.Logger:
"""Setup JSON-structured logging for ELK ingestion"""
logger = logging.getLogger(app_name)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
formatter = DifyJsonFormatter(
'%(timestamp)s %(level)s %(name)s %(message)s'
)
handler.setFormatter(formatter)
if not logger.handlers:
logger.addHandler(handler)
return logger
def log_llm_call(logger: logging.Logger):
"""Decorator to log LLM API calls with timing"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = None
error = None
try:
result = func(*args, **kwargs)
return result
except Exception as e:
error = str(e)
raise
finally:
latency_ms = int((time.time() - start_time) * 1000)
# Extract model info from args/kwargs if available
model = kwargs.get('model') or (args[0] if args else None)
log_data = {
'event_type': 'llm_call',
'function': func.__name__,
'latency_ms': latency_ms,
'success': error is None,
'error': error,
'model': str(model) if model else 'unknown'
}
if error:
logger.error(f"LLM call failed: {json.dumps(log_data)}")
else:
logger.info(f"LLM call completed: {json.dumps(log_data)}")
return wrapper
return decorator
def log_rag_operation(logger: logging.Logger, operation: str):
"""Context manager for RAG operations"""
class RAGLogContext:
def __init__(self, op_name: str):
self.op_name = op_name
self.start_time = None
self.doc_count = 0
self.chunk_count = 0
def __enter__(self):
self.start_time = time.time()
logger.info(json.dumps({
'event_type': 'rag_operation_start',
'operation': self.op_name
}))
return self
def __exit__(self, exc_type, exc_val, exc_tb):
latency_ms = int((time.time() - self.start_time) * 1000)
log_data = {
'event_type': 'rag_operation_complete',
'operation': self.op_name,
'latency_ms': latency_ms,
'docs_processed': self.doc_count,
'chunks_created': self.chunk_count,
'success': exc_type is None
}
if exc_type:
log_data['error'] = str(exc_val)
logger.error(f"RAG operation failed: {json.dumps(log_data)}")
else:
logger.info(f"RAG operation completed: {json.dumps(log_data)}")
return False # Don't suppress exceptions
def set_counts(self, docs: int, chunks: int):
self.doc_count = docs
self.chunk_count = chunks
return RAGLogContext(operation)
Bước 5: Tích hợp với HolySheep AI
Đây là phần tôi đặc biệt muốn chia sẻ. Khi migrate từ OpenAI sang
HolyShehe AI, tôi nhận thấy chi phí giảm 85% — từ $8/MTok xuống $0.42/MTok với DeepSeek V3.2. Điều quan trọng là tất cả code vẫn tương thích 100%:
# dify_integration/holy_sheep_client.py
import os
from typing import Optional, Dict, Any
import anthropic
import logging
logger = logging.getLogger("dify")
class HolySheepAIClient:
"""
HolySheep AI Client - Tương thích 100% với OpenAI/Anthropic format
Tiết kiệm 85%+ chi phí so với OpenAI với cùng chất lượng đầu ra
Giá tham khảo 2026:
- DeepSeek V3.2: $0.42/MTok (sử dụng nhiều nhất trong RAG pipeline)
- Gemini 2.5 Flash: $2.50/MTok (embedding và summarization)
- Claude Sonnet 4.5: $15/MTok (complex reasoning tasks)
- GPT-4.1: $8/MTok (fallback khi cần)
"""
BASE_URL = "https://api.holysheep.ai/v1"
def __init__(self, api_key: Optional[str] = None):
self.api_key = api_key or os.environ.get("HOLYSHEEP_API_KEY")
if not self.api_key:
raise ValueError("HOLYSHEEP_API_KEY is required")
# Khởi tạo Anthropic client với HolySheep endpoint
self.client = anthropic.Anthropic(
api_key=self.api_key,
base_url=self.BASE_URL
)
self.logger = logging.getLogger("dify.holysheep")
def chat_completion(
self,
messages: list,
model: str = "claude-sonnet-4.5",
max_tokens: int = 4096,
temperature: float = 0.7,
**kwargs
) -> Dict[str, Any]:
"""
Gọi chat completion qua HolySheep AI
Supported models:
- claude-sonnet-4.5 (Anthropic models)
- gpt-4.1, gpt-4o (OpenAI models)
- deepseek-v3.2, gemini-2.5-flash
"""
import time
start_time = time.time()
try:
response = self.client.messages.create(
model=model,
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
**kwargs
)
latency_ms = int((time.time() - start_time) * 1000)
# Structured log cho ELK
self.logger.info({
'event_type': 'ai_completion',
'model': model,
'latency_ms': latency_ms,
'input_tokens': response.usage.input_tokens,
'output_tokens': response.usage.output_tokens,
'total_tokens': response.usage.total_tokens,
'provider': 'holy_sheep',
'success': True
})
return {
'content': response.content[0].text,
'model': response.model,
'usage': {
'input_tokens': response.usage.input_tokens,
'output_tokens': response.usage.output_tokens,
'total_tokens': response.usage.total_tokens
},
'latency_ms': latency_ms
}
except Exception as e:
latency_ms = int((time.time() - start_time) * 1000)
self.logger.error({
'event_type': 'ai_completion',
'model': model,
'latency_ms': latency_ms,
'provider': 'holy_sheep',
'success': False,
'error': str(e),
'error_type': type(e).__name__
})
raise
def embeddings(self, texts: list, model: str = "text-embedding-3-small") -> list:
"""
Tạo embeddings - sử dụng Gemini 2.5 Flash cho chi phí thấp nhất
Chi phí: $0.0015/1K tokens thay vì $0.0001 với OpenAI
"""
import time
start_time = time.time()
try:
# Sử dụng HolySheep endpoint cho embeddings
import httpx
response = httpx.post(
f"{self.BASE_URL}/embeddings",
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
},
json={
"input": texts,
"model": model
},
timeout=30.0
)
response.raise_for_status()
data = response.json()
latency_ms = int((time.time() - start_time) * 1000)
self.logger.info({
'event_type': 'embeddings',
'model': model,
'latency_ms': latency_ms,
'text_count': len(texts),
'dimensions': len(data['data'][0]['embedding']),
'provider': 'holy_sheep',
'success': True
})
return [item['embedding'] for item in data['data']]
except Exception as e:
self.logger.error({
'event_type': 'embeddings',
'model': model,
'provider': 'holy_sheep',
'success': False,
'error': str(e)
})
raise
Usage example trong Dify workflow
def process_rag_query(query: str, context: str, api_key: str):
"""
Example RAG processing với HolySheep AI và structured logging
"""
client = HolySheepAIClient(api_key)
# 1. Tạo query embedding (sử dụng Gemini - rẻ nhất)
embeddings = client.embeddings([query], model="gemini-embedding-exp-03-07")
# 2. Gọi LLM với context (sử dụng DeepSeek - tối ưu chi phí)
messages = [
{
"role": "user",
"content": f"Context: {context}\n\nQuery: {query}"
}
]
response = client.chat_completion(
messages=messages,
model="deepseek-v3.2", # $0.42/MTok - tối ưu cho RAG
max_tokens=2048,
temperature=0.3
)
return response['content']
Bước 6: Dashboard Kibana cho Monitoring
Sau khi setup xong ELK, hãy tạo dashboard để visualize các metrics quan trọng. Import JSON này vào Kibana:
{
"objects": [
{
"id": "dify-overview-dashboard",
"type": "dashboard",
"attributes": {
"title": "Dify System Overview",
"description": "Real-time monitoring for Dify AI system",
"panelsJSON": [
{
"version": "8.11.0",
"type": "lens",
"gridData": {
"x": 0,
"y": 0,
"w": 24,
"h": 8,
"i": "1"
},
"panelIndex": "1",
"embeddableConfig": {
"attributes": {
"title": "Request Volume (per minute)",
"visualizationType": "lnsXY",
"state": {
"datasourceStates": {
"indexpattern": {
"layers": [{
"name": "dify-logs-*",
"columns": [
{"name": "timestamp", "type": "date"},
{"name": "event_type", "type": "string"},
{"name": "latency_ms", "type": "number"},
{"name": "model", "type": "string"}
]
}]
}
}
}
}
}
},
{
"version": "8.11.0",
"type": "lens",
"gridData": {
"x": 24,
"y": 0,
"w": 24,
"h": 8,
"i": "2"
},
"panelIndex": "2",
"embeddableConfig": {
"attributes": {
"title": "Average Latency by Model (ms)",
"visualizationType": "lnsPie"
}
}
},
{
"version": "8.11.0",
"type": "lens",
"gridData": {
"x": 0,
"y": 8,
"w": 16,
"h": 8,
"i": "3"
},
"panelIndex": "3",
"embeddableConfig": {
"attributes": {
"title": "Error Rate (%)",
"visualizationType": "lnsMetric"
}
}
},
{
"version": "8.11.0",
"type": "lens",
"gridData": {
"x": 16,
"y": 8,
"w": 32,
"h": 8,
"i": "4"
},
"panelIndex": "4",
"embeddableConfig": {
"attributes": {
"title": "P95/P99 Latency Distribution",
"visualizationType": "lnsXY"
}
}
}
],
"timeRestore": true,
"timeTo": "now",
"timeFrom": "now-24h",
"refreshInterval": {
"pause": false,
"value": 30000
},
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"
}
}
},
{
"id": "dify-logs-index-pattern",
"type": "index-pattern",
"attributes": {
"title": "dify-logs-*",
"timeFieldName": "@timestamp"
}
},
{
"id": "dify-errors-index-pattern",
"type": "index-pattern",
"attributes": {
"title": "dify-errors-*",
"timeFieldName": "@timestamp"
}
}
]
}
Cấu hình Alerting cho Production
Thiết lập alerting để được notify khi có sự cố:
# elk/alerts/dify_alerts.json
{
"trigger": {
"schedule": {
"interval": "1m"
}
},
"input": {
"search": {
"request": {
"indices": ["dify-logs-*"],
"body": {
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-5m",
"lte": "now"
}
}
},
{
"terms": {
"tags": ["error"]
}
}
]
}
},
"aggs": {
"errors_by_type": {
"terms": {
"field": "dify_error.keyword",
"size": 10
}
},
"error_rate": {
"value_count": {
"field": "dify_error.keyword"
}
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total.value": {
"gt": 10
}
}
},
"actions": {
"log_error": {
"logging": {
"text": "High error rate detected: {{ctx.payload.hits.total.value}} errors in last 5 minutes. Top errors: {{#ctx.payload.aggregations.errors_by_type.buckets}}{{key}}({{doc_count}}) {{/ctx.payload.aggregations.errors_by_type.buckets}}"
}
},
"slack_notification": {
"webhook": {
"method": "post",
"url": "{{ctx.metadata.slack_webhook}}",
"body": {
"channel": "#dify-alerts",
"username": "Dify ELK Alert",
"icon_emoji": ":warning:",
"text": "*Dify Error Alert*\n• Error count: {{ctx.payload.hits.total.value}}\n• Environment: production\n• Time: {{ctx.execution_time}}"
}
}
},
"email_notification": {
"email": {
"profile": "standard",
"to": ["[email protected]"],
"subject": "[ALERT] Dify High Error Rate - {{ctx.payload.hits.total.value}} errors",
"body": {
"text": "Error breakdown:\n{{#ctx.payload.aggregations.errors_by_type.buckets}}\n- {{key}}: {{doc_count}} occurrences\n{{/ctx.payload.aggregations.errors_by_type.buckets}}\n\nCheck Kibana dashboard: http://kibana:5601/app/dashboards"
}
}
}
}
}
Tối ưu hóa chi phí với HolySheep AI
Qua kinh nghiệm thực chiến, đây là chiến lược tối ưu chi phí AI mà tôi đã áp dụng:
- RAG Embedding: Sử dụng Gemini 2.5 Flash ($2.50/MTok) thay vì OpenAI ($0.0001/1K tokens = $0.10/MTok)
- Summarization: Sử dụng DeepSeek V3.2 ($0.42/MTok) cho context compression
- Complex Reasoning: Dùng Claude Sonnet 4.5 ($15/MTok) chỉ khi cần thiết
- Fallback: GPT-4.1 ($8/MTok) khi Anthropic quota hết
Với 1 triệu requests/tháng, chi phí giảm từ $2,400 xuống còn $350 — tiết kiệm
85%. Đặc biệt, HolySheep hỗ trợ thanh toán qua
WeChat/Alipay rất tiện lợi cho thị trường châu Á, và latency trung bình chỉ
<50ms do server đặt gần Việt Nam.
Lỗi thường gặp và cách khắc phục
1. Lỗi "Connection refused" khi Filebeat gửi sang Logstash
Nguyên nhân: Logstash chưa khởi động hoặc port 5044 bị block bởi firewall.
Giải pháp:
# Kiểm tra Logstash đã chạy chưa
docker logs logstash
Kiểm tra port 5044 có đang listen không
netstat -tlnp | grep 5044
Nếu dùng firewall, mở port
sudo ufw allow 5044/tcp
Restart Filebeat với debug mode
filebeat -e -d "*" -c /etc/filebeat/filebeat.yml
2. Lỗi "_jsonparsefailure" khi parse Dify log
Nguyên nhân: Dify log format không phải JSON thuần (có thể có mixed format từ nhiều worker).
Giải pháp:
# Update Logstash filter để xử lý cả hai format
filter {
if [message] =~ /^\{/ {
json {
source => "message"
target => "parsed"
skip_on_invalid_json => true
}
}
# Fallback: extract key fields bằng grok
if "error" in [tags] or ![parsed] {
grok {
match => {
"message" => [
"%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}",
".*\"error\"?\s*:\s*\"?%{GREEDYDATA:dify_error}\"?",
".*\"latency\"?\s*:\s*%{NUMBER:dify_latency_ms:int}"
]
}
tag_on_failure => ["_grokparsefailure"]
}
# Convert latency nếu extracted thành công
if [dify_latency_ms] {
mutate {
convert => { "dify_latency_ms" => "integer" }
}
}
}
}
3. Elasticsearch OutOfMemoryError
Nguyên nhân: JVM heap size không đủ hoặc index quá lớn không được rotate.
Giải pháp:
# Tăng JVM heap (không vượt quá 50% RAM)
Sửa trong docker-compose.yml:
environment:
- "ES_JAVA_OPTS=-Xms4g -Xmx4g -XX:+UseG1GC"
Setup ILM (Index Lifecycle Management) để tự động xóa cũ
Tạo file ilm-policy.json:
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "7d"
}
}
},
"warm": {
"min_age": "30d",
"actions": {
"shrink": {
"number_of_shards": 1
},
"forcemerge": {
"max_num_segments": 1
Tài nguyên liên quan
Bài viết liên quan