Pull documents with the _search API, or let a short Python script page through them with helpers.scan. If your pipeline kept the original log line, usually in message or event.original, extract just that field and you get the raw logs back. OpenSearch Dashboards can generate reports from saved searches, but not in a format LogTotal reads today.
OpenSearch backs a lot of homegrown SIEMs and log platforms, including Amazon OpenSearch Service and the Wazuh indexer. Prime Core has 23,466 detection rules for OpenSearch, mapped to 671 MITRE ATT&CK techniques. Below is how to get a clean slice of data out, sanitize it, and investigate it for free in LogTotal.
Before you start
Permissions. With the security plugin enabled, your role needs read access on the index pattern: the read action group, or at least indices:data/read/search* and indices:data/read/scroll*. On Amazon OpenSearch Service, that’s either a fine-grained access control user or IAM credentials with SigV4 signing.
Find the right fields. Index patterns differ between pipelines. Check one document and the mapping before you write a query:
GET logs-*/_search?size=1
GET logs-*/_mapping
You’re looking for the time field (@timestamp or timestamp) and, ideally, a field that holds the original line (message, event.original, full_log in Wazuh).
Count first. Run GET logs-*/_count with the same query to see what you’re about to pull.
The commands below follow the OpenSearch 2.x documentation, checked October 2026.
Option 1: Python with opensearch-py (recommended)
helpers.scan handles paging and cleans up after itself. Install opensearch-py, then:
import json, os
from opensearchpy import OpenSearch, helpers
client = OpenSearch(
"https://opensearch.example.com:9200",
http_auth=("reader", os.environ["OS_PASSWORD"]),
verify_certs=True,
)
query = {"query": {"range": {"@timestamp": {
"gte": "2026-10-19T00:00:00Z", "lt": "2026-10-20T00:00:00Z"}}}}
with open("opensearch_1019.jsonl", "w") as out:
for hit in helpers.scan(client, index="logs-*", query=query, size=1000):
out.write(json.dumps(hit["_source"]) + "\n")
To get raw lines instead of documents, write hit[“_source”].get(“message”, “”) instead of the whole _source. To keep the file small, add “_source”: [“@timestamp”, “host.name”, “message”] to the query.
Option 2: curl for small exports
For up to 10,000 documents, one request is enough:
curl -sS -u reader -H 'Content-Type: application/json' \
"https://opensearch.example.com:9200/logs-*/_search" -d '{
"size": 10000,
"query": {"range": {"@timestamp": {"gte": "2026-10-19T00:00:00Z", "lt": "2026-10-20T00:00:00Z"}}},
"sort": [{"@timestamp": "asc"}]
}' | jq -c '.hits.hits[]._source' > opensearch_small.jsonl
10,000 is the default index.max_result_window. Past that, the request fails, and you want Option 1, or a point in time (PIT) with search_after if you’d rather script it yourself.
Step 3: Upload, sanitize and review in LogTotal
- Upload. Open logtotal.com and drop in the .jsonl file.
- Sanitize. Look it over before you continue.
- Review.
When it goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| security_exception / 403 | Role lacks search or scroll permissions | Ask for read on the index pattern |
| Result window is too large | More than 10,000 hits in one request | Use helpers.scan or PIT with search_after |
| Zero hits, but the data is there | Wrong time field name, or a time zone mix-up | Check the mapping; use explicit Z timestamps |
| No search context found | Scroll expired between pages | Pass scroll=”5m” to helpers.scan; use smaller pages |
| Signature errors on Amazon OpenSearch Service | IAM-based domain expects SigV4 | Use AWSV4SignerAuth from opensearch-py |
FAQ
Does this work for Wazuh?
Yes. The Wazuh indexer is OpenSearch-based. Alerts usually live in wazuh-alerts-*, and the original log line in full_log.
Should I export everything in _source?
Only if you need it. Pipelines often add dozens of enrichment fields. Trimming to time, host and the raw message keeps files small and uploads fast.