Elasticsearch
Migrate from Elasticsearch to Parseable
Migrate your log data and workflows from Elasticsearch to Parseable.
Overview
Migrate from Elasticsearch to Parseable to:
- Reduce Costs - Lower storage and operational costs
- Simplify Operations - No cluster management
- Faster Queries - Optimized for log analytics
- Native SQL - Use familiar SQL syntax
Migration Strategies
Strategy 1: Parallel Ingestion
Run both systems in parallel during migration.
Log Sources → [Fluent Bit] → Elasticsearch
→ ParseableStrategy 2: Historical Export
Export historical data from Elasticsearch to Parseable.
Strategy 3: Cut-over
Switch log ingestion from Elasticsearch to Parseable.
Parallel Ingestion Setup
Fluent Bit Configuration
service:
flush: 5
log_level: info
pipeline:
inputs:
- name: tail
path: /var/log/*.log
tag: logs
outputs:
# Continue sending to Elasticsearch
- name: es
match: '*'
host: elasticsearch
port: 9200
index: logs
type: _doc
# Also send to Parseable
- name: http
match: '*'
host: parseable
port: 8000
uri: /api/v1/ingest
format: json
header: Authorization Basic YWRtaW46YWRtaW4=
header: X-P-Stream application-logsHistorical Data Export
Using Elasticdump
Export data from Elasticsearch:
# Install elasticdump
npm install -g elasticdump
# Export to JSON
elasticdump \
--input=http://elasticsearch:9200/logs \
--output=/tmp/logs.json \
--type=data \
--limit=10000Import to Parseable
import json
import requests
from datetime import datetime
PARSEABLE_URL = "http://parseable:8000"
PARSEABLE_AUTH = ("admin", "admin")
STREAM = "elasticsearch-import"
def import_to_parseable(file_path):
batch = []
batch_size = 1000
with open(file_path, 'r') as f:
for line in f:
doc = json.loads(line)
source = doc.get('_source', doc)
# Transform Elasticsearch document
log_entry = {
'timestamp': source.get('@timestamp', datetime.utcnow().isoformat() + 'Z'),
'message': source.get('message', ''),
'level': source.get('level', source.get('log.level', 'info')),
**{k: v for k, v in source.items() if k not in ['@timestamp', 'message', 'level']}
}
batch.append(log_entry)
if len(batch) >= batch_size:
send_batch(batch)
batch = []
if batch:
send_batch(batch)
def send_batch(batch):
response = requests.post(
f"{PARSEABLE_URL}/api/v1/ingest",
json=batch,
auth=PARSEABLE_AUTH,
headers={'X-P-Stream': STREAM}
)
response.raise_for_status()
print(f"Imported {len(batch)} documents")
import_to_parseable('/tmp/logs.json')Query Migration
Elasticsearch to SQL
| Elasticsearch | Parseable SQL |
|---|---|
match: { message: "error" } | WHERE message LIKE '%error%' |
term: { level: "error" } | WHERE level = 'error' |
range: { @timestamp: { gte: "now-1h" } } | WHERE p_timestamp > NOW() - INTERVAL '1 hour' |
aggs: { count: { terms: { field: "level" } } } | SELECT level, COUNT(*) GROUP BY level |
Example Queries
Elasticsearch:
{
"query": {
"bool": {
"must": [
{ "match": { "level": "error" } },
{ "range": { "@timestamp": { "gte": "now-24h" } } }
]
}
},
"aggs": {
"by_service": {
"terms": { "field": "service.keyword" }
}
}
}Parseable SQL:
SELECT service, COUNT(*) as error_count
FROM "application-logs"
WHERE level = 'error'
AND p_timestamp > NOW() - INTERVAL '24 hours'
GROUP BY service
ORDER BY error_count DESCIndex Pattern to Stream Mapping
| Elasticsearch Index | Parseable Stream |
|---|---|
logs-* | application-logs |
nginx-* | nginx-logs |
kubernetes-* | k8s-logs |
Kibana to Parseable Dashboard
Visualization Mapping
| Kibana | Parseable |
|---|---|
| Discover | SQL Editor |
| Lens | Dashboards |
| Canvas | Dashboards |
| Alerts | Alerts |
Recreate Dashboards
- Export Kibana dashboard JSON
- Map visualizations to Parseable queries
- Create equivalent dashboards in Parseable or Grafana
Logstash to Fluent Bit
Logstash Config
input {
beats { port => 5044 }
}
filter {
grok { match => { "message" => "%{COMBINEDAPACHELOG}" } }
}
output {
elasticsearch { hosts => ["elasticsearch:9200"] }
}Equivalent Fluent Bit
pipeline:
inputs:
- name: tcp
listen: 0.0.0.0
port: 5044
format: json
filters:
- name: parser
match: '*'
key_name: message
parser: apache
outputs:
- name: http
match: '*'
host: parseable
port: 8000
uri: /api/v1/ingest
format: json
header: Authorization Basic YWRtaW46YWRtaW4=
header: X-P-Stream apache-logsBest Practices
- Run Parallel First - Validate data before switching
- Map Fields - Document field mappings
- Test Queries - Verify query results match
- Migrate Gradually - Start with non-critical logs
- Update Dashboards - Recreate visualizations
Troubleshooting
Data Mismatch
- Compare document counts
- Verify field mappings
- Check timestamp formats
Query Differences
- Elasticsearch full-text vs SQL LIKE
- Aggregation syntax differences
- Time zone handling
Next Steps
- Set up alerts in Parseable
- Create dashboards for monitoring
- Configure Grafana for visualization
Was this page helpful?