<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenSearch API - Documenta莽茫o</title>
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.css" rel="stylesheet" />
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
line-height: 1.6;
color: #333;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
header {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 10px 40px rgba(0,0,0,0.1);
}
h1 {
color: #667eea;
font-size: 2.5em;
margin-bottom: 10px;
}
.subtitle {
color: #666;
font-size: 1.2em;
}
nav {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
}
nav ul {
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 20px;
}
nav a {
color: #667eea;
text-decoration: none;
padding: 10px 20px;
border-radius: 8px;
background: #f7f7ff;
transition: all 0.3s;
}
nav a:hover {
background: #667eea;
color: white;
transform: translateY(-2px);
}
.section {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
}
h2 {
color: #667eea;
margin-bottom: 20px;
font-size: 1.8em;
border-bottom: 2px solid #f0f0f0;
padding-bottom: 10px;
}
h3 {
color: #764ba2;
margin: 20px 0 15px 0;
font-size: 1.3em;
}
.code-tabs {
background: #f8f9fa;
border-radius: 10px;
overflow: hidden;
margin: 20px 0;
}
.tab-buttons {
display: flex;
background: #e9ecef;
}
.tab-button {
padding: 12px 24px;
background: none;
border: none;
cursor: pointer;
font-weight: 600;
color: #666;
transition: all 0.3s;
}
.tab-button.active {
background: #667eea;
color: white;
}
.tab-content {
padding: 20px;
display: none;
}
.tab-content.active {
display: block;
}
pre {
background: #2d2d2d !important;
border-radius: 8px;
padding: 20px !important;
overflow-x: auto;
margin: 15px 0;
}
code {
font-family: 'Fira Code', 'Courier New', monospace;
font-size: 14px;
}
.inline-code {
background: #f0f0f0;
padding: 2px 6px;
border-radius: 4px;
color: #e83e8c;
}
.endpoint {
background: #f8f9fa;
border-left: 4px solid #667eea;
padding: 15px;
margin: 15px 0;
border-radius: 5px;
}
.method {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-weight: bold;
font-size: 12px;
margin-right: 10px;
}
.method.get { background: #61affe; color: white; }
.method.post { background: #49cc90; color: white; }
.method.put { background: #fca130; color: white; }
.method.delete { background: #f93e3e; color: white; }
.alert {
padding: 15px;
border-radius: 8px;
margin: 20px 0;
}
.alert.info {
background: #e7f3ff;
border-left: 4px solid #2196F3;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>馃摎 OpenSearch API Documentation</h1>
<p class="subtitle">Gateway unificado para logs, m茅tricas, traces, busca textual e vetorial</p>
</header>
<nav>
<ul>
<li><a href="#quickstart">馃殌 Quick Start</a></li>
<li><a href="#logs">馃摑 Logs</a></li>
<li><a href="#metrics">馃搳 M茅tricas</a></li>
<li><a href="#traces">馃攳 Traces</a></li>
<li><a href="#search">馃攷 Busca Textual</a></li>
<li><a href="#vectors">馃 Vetores ML</a></li>
<li><a href="#reports">馃搱 Relat贸rios</a></li>
<li><a href="/playground">馃幃 Playground</a></li>
</ul>
</nav>
<section id="quickstart" class="section">
<h2>馃殌 Quick Start</h2>
<div class="alert info">
<strong>Base URL:</strong> <code class="inline-code">https://opensearch-api.evoluame.com</code><br>
<strong>Autentica莽茫o:</strong> API Key no header <code class="inline-code">X-API-Key</code>
</div>
<h3>Obter API Key</h3>
<div class="code-tabs">
<div class="tab-buttons">
<button class="tab-button active" onclick="switchTab(event, 'qs-curl')">cURL</button>
<button class="tab-button" onclick="switchTab(event, 'qs-rust')">Rust</button>
</div>
<div id="qs-curl" class="tab-content active">
<pre><code class="language-bash">curl -X POST https://opensearch-api.evoluame.com/auth/login \
-H "Content-Type: application/json" \
-d '{
"username": "demo",
"password": "demo123"
}'</code></pre>
</div>
<div id="qs-rust" class="tab-content">
<pre><code class="language-rust">use reqwest;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.post("https://opensearch-api.evoluame.com/auth/login")
.json(&json!({
"username": "demo",
"password": "demo123"
}))
.send()
.await?;
let data: serde_json::Value = response.json().await?;
println!("API Key: {}", data["token"]);
Ok(())
}</code></pre>
</div>
</div>
</section>
<section id="logs" class="section">
<h2>馃摑 Logs - Centraliza莽茫o e An谩lise</h2>
<h3>Enviar Logs de Aplica莽茫o</h3>
<div class="endpoint">
<span class="method post">POST</span>
<code>/index/logs-{app}-{date}</code>
</div>
<div class="code-tabs">
<div class="tab-buttons">
<button class="tab-button active" onclick="switchTab(event, 'logs-curl')">cURL</button>
<button class="tab-button" onclick="switchTab(event, 'logs-rust')">Rust</button>
</div>
<div id="logs-curl" class="tab-content active">
<pre><code class="language-bash"># Log de erro com stack trace
curl -X POST https://opensearch-api.evoluame.com/index/logs-backend-$(date +%Y.%m.%d) \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"@timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")'",
"level": "ERROR",
"service": "payment-api",
"environment": "production",
"host": "api-server-01",
"correlation_id": "abc-123-def",
"user_id": "user_8472",
"message": "Payment processing failed",
"error": {
"type": "PaymentGatewayException",
"message": "Gateway timeout after 30s",
"stack_trace": "PaymentGatewayException: Gateway timeout...",
"code": "GATEWAY_TIMEOUT"
},
"context": {
"amount": 150.00,
"currency": "BRL",
"payment_method": "credit_card",
"gateway": "stripe"
}
}'</code></pre>
</div>
<div id="logs-rust" class="tab-content">
<pre><code class="language-rust">use reqwest;
use serde_json::json;
use chrono::Utc;
pub struct Logger {
client: reqwest::Client,
api_key: String,
base_url: String,
}
impl Logger {
pub fn new(api_key: String) -> Self {
Self {
client: reqwest::Client::new(),
api_key,
base_url: "https://opensearch-api.evoluame.com".to_string(),
}
}
pub async fn log_error(&self, service: &str, error: &dyn std::error::Error) {
let index = format!("logs-{}-{}", service, Utc::now().format("%Y.%m.%d"));
let url = format!("{}/index/{}", self.base_url, index);
let log_entry = json!({
"@timestamp": Utc::now().to_rfc3339(),
"level": "ERROR",
"service": service,
"environment": std::env::var("ENV").unwrap_or("development".to_string()),
"message": error.to_string(),
"error": {
"message": error.to_string(),
}
});
let _ = self.client
.post(&url)
.header("X-API-Key", &self.api_key)
.json(&log_entry)
.send()
.await;
}
}</code></pre>
</div>
</div>
</section>
<section id="metrics" class="section">
<h2>馃搳 M茅tricas - Monitoramento de Performance</h2>
<h3>Enviar M茅tricas de Sistema</h3>
<div class="endpoint">
<span class="method post">POST</span>
<code>/index/metrics-{service}-{date}</code>
</div>
<div class="code-tabs">
<div class="tab-buttons">
<button class="tab-button active" onclick="switchTab(event, 'metrics-curl')">cURL</button>
<button class="tab-button" onclick="switchTab(event, 'metrics-rust')">Rust</button>
</div>
<div id="metrics-curl" class="tab-content active">
<pre><code class="language-bash"># M茅tricas de aplica莽茫o
curl -X POST https://opensearch-api.evoluame.com/index/metrics-api-$(date +%Y.%m.%d) \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"@timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")'",
"service": "payment-api",
"host": "api-01",
"metrics": {
"cpu": {
"usage_percent": 45.2,
"cores": 4
},
"memory": {
"used_mb": 3200,
"total_mb": 8192,
"usage_percent": 39.1
},
"application": {
"requests_per_second": 1250,
"response_time_p50_ms": 45,
"response_time_p95_ms": 125,
"response_time_p99_ms": 250,
"error_rate": 0.02
}
}
}'</code></pre>
</div>
<div id="metrics-rust" class="tab-content">
<pre><code class="language-rust">use sysinfo::{System, SystemExt};
pub struct MetricsCollector {
client: reqwest::Client,
api_key: String,
}
impl MetricsCollector {
pub async fn collect_and_send(&mut self, service: &str) {
let mut system = System::new_all();
system.refresh_all();
let metrics = json!({
"@timestamp": Utc::now().to_rfc3339(),
"service": service,
"metrics": {
"cpu": {
"usage_percent": system.global_cpu_info().cpu_usage(),
},
"memory": {
"used_mb": system.used_memory() / 1024,
"total_mb": system.total_memory() / 1024,
}
}
});
let index = format!("metrics-{}-{}", service, Utc::now().format("%Y.%m.%d"));
self.client
.post(&format!("https://opensearch-api.evoluame.com/index/{}", index))
.header("X-API-Key", &self.api_key)
.json(&metrics)
.send()
.await;
}
}</code></pre>
</div>
</div>
</section>
<section id="traces" class="section">
<h2>馃攳 Distributed Tracing</h2>
<h3>Enviar Traces (OpenTelemetry)</h3>
<div class="endpoint">
<span class="method post">POST</span>
<code>/index/traces-{service}-{date}</code>
</div>
<div class="code-tabs">
<div class="tab-buttons">
<button class="tab-button active" onclick="switchTab(event, 'traces-curl')">cURL</button>
<button class="tab-button" onclick="switchTab(event, 'traces-rust')">Rust</button>
</div>
<div id="traces-curl" class="tab-content active">
<pre><code class="language-bash"># Trace de uma requisi莽茫o completa
curl -X POST https://opensearch-api.evoluame.com/index/traces-api-$(date +%Y.%m.%d) \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"@timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")'",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"operation_name": "POST /api/payment",
"service": "payment-api",
"duration_ms": 234,
"status": "ok",
"attributes": {
"http.method": "POST",
"http.url": "/api/payment",
"http.status_code": 200,
"user.id": "user_123",
"payment.amount": 150.00
}
}'</code></pre>
</div>
<div id="traces-rust" class="tab-content">
<pre><code class="language-rust">use tracing::{instrument, info};
#[instrument(
skip(db),
fields(
user.id = %user_id,
otel.kind = "server"
)
)]
pub async fn process_payment(
db: &Database,
user_id: &str,
amount: f64,
) -> Result<Payment, Error> {
info!("Processing payment");
let user = db.query_user(user_id)
.instrument(info_span!("database.query"))
.await?;
let result = charge_card(amount, &user)
.instrument(info_span!("payment.charge"))
.await?;
info!("Payment processed successfully");
Ok(result)
}</code></pre>
</div>
</div>
</section>
<section id="search" class="section">
<h2>馃攷 Busca Textual - Crawlers e Documentos</h2>
<h3>Indexar Conte煤do Web (Crawler)</h3>
<div class="endpoint">
<span class="method post">POST</span>
<code>/index/content-{domain}-{date}</code>
</div>
<div class="code-tabs">
<div class="tab-buttons">
<button class="tab-button active" onclick="switchTab(event, 'crawler-curl')">cURL</button>
<button class="tab-button" onclick="switchTab(event, 'crawler-rust')">Rust Crawler</button>
</div>
<div id="crawler-curl" class="tab-content active">
<pre><code class="language-bash"># Indexar p谩gina web crawleada
curl -X POST https://opensearch-api.evoluame.com/index/content-website-$(date +%Y.%m) \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"@timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")'",
"url": "https://example.com/blog/opensearch-guide",
"domain": "example.com",
"path": "/blog/opensearch-guide",
"title": "Complete Guide to OpenSearch",
"content": {
"raw_text": "OpenSearch is a powerful open-source search and analytics engine...",
"word_count": 1250,
"reading_time_minutes": 6
},
"meta": {
"description": "Learn how to use OpenSearch for search and analytics",
"keywords": ["opensearch", "elasticsearch", "search", "analytics"],
"author": "John Doe",
"published_date": "2024-01-15"
}
}'</code></pre>
</div>
<div id="crawler-rust" class="tab-content">
<pre><code class="language-rust">use scraper::{Html, Selector};
pub struct WebCrawler {
client: reqwest::Client,
opensearch: OpenSearchClient,
}
impl WebCrawler {
pub async fn crawl_and_index(&self, url: &str) -> Result<(), Error> {
let response = self.client.get(url).send().await?;
let body = response.text().await?;
let document = Html::parse_document(&body);
let title = self.extract_text(&document, "title");
let content = self.extract_content(&document);
let doc = json!({
"@timestamp": Utc::now().to_rfc3339(),
"url": url,
"title": title,
"content": {
"raw_text": content,
"word_count": content.split_whitespace().count(),
}
});
let index = format!("content-{}", Utc::now().format("%Y.%m"));
self.opensearch.index(&index, doc).await?;
Ok(())
}
}</code></pre>
</div>
</div>
</section>
<section id="vectors" class="section">
<h2>馃 Busca Vetorial - Machine Learning</h2>
<h3>Indexar Embeddings</h3>
<div class="endpoint">
<span class="method post">POST</span>
<code>/index/vectors-{model}-{date}</code>
</div>
<div class="code-tabs">
<div class="tab-buttons">
<button class="tab-button active" onclick="switchTab(event, 'vectors-curl')">cURL</button>
<button class="tab-button" onclick="switchTab(event, 'vectors-rust')">Rust + ML</button>
</div>
<div id="vectors-curl" class="tab-content active">
<pre><code class="language-bash"># Indexar documento com embedding
curl -X POST https://opensearch-api.evoluame.com/index/vectors-products-$(date +%Y.%m) \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"@timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")'",
"product": {
"id": "prod_123",
"name": "Smartphone XYZ Pro Max",
"description": "Latest flagship smartphone with advanced camera system",
"category": "Electronics",
"price": 4999.90
},
"embedding": {
"model": "sentence-transformers/all-MiniLM-L6-v2",
"dimension": 384,
"vector": [0.0234, -0.1456, 0.0891]
}
}'</code></pre>
</div>
<div id="vectors-rust" class="tab-content">
<pre><code class="language-rust">pub struct VectorSearch {
client: OpenSearchClient,
}
impl VectorSearch {
pub async fn index_with_embedding(&self, text: &str, metadata: serde_json::Value) {
let embedding = self.generate_embedding(text)?;
let doc = json!({
"@timestamp": Utc::now().to_rfc3339(),
"text": text,
"metadata": metadata,
"embedding": {
"model": "sentence-transformers/all-MiniLM-L6-v2",
"dimension": embedding.len(),
"vector": embedding,
}
});
let index = format!("vectors-{}", Utc::now().format("%Y.%m"));
self.client.index(&index, doc).await?;
}
pub async fn semantic_search(&self, query: &str, k: usize) -> Vec<SearchResult> {
let query_embedding = self.generate_embedding(query)?;
let search_query = json!({
"size": k,
"query": {
"knn": {
"embedding.vector": {
"vector": query_embedding,
"k": k
}
}
}
});
self.client.search("vectors-*", search_query).await
}
}</code></pre>
</div>
</div>
</section>
<section id="reports" class="section">
<h2>馃搱 Gera莽茫o de Relat贸rios</h2>
<h3>Relat贸rio de Logs e Erros</h3>
<pre><code class="language-bash"># Relat贸rio di谩rio de erros
curl -X POST https://opensearch-api.evoluame.com/_search/logs-* \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"size": 0,
"query": {
"range": {"@timestamp": {"gte": "now-1d"}}
},
"aggs": {
"error_summary": {
"filter": {"term": {"level": "ERROR"}},
"aggs": {
"by_service": {
"terms": {"field": "service.keyword"},
"aggs": {
"by_error_type": {
"terms": {"field": "error.type.keyword"}
}
}
}
}
}
}
}'</code></pre>
<h3>Relat贸rio de Performance</h3>
<pre><code class="language-rust">pub async fn generate_performance_report(&self, date: &str) -> Report {
let query = json!({
"size": 0,
"query": {
"range": {
"@timestamp": {
"gte": format!("{}T00:00:00Z", date),
"lt": format!("{}T23:59:59Z", date)
}
}
},
"aggs": {
"services": {
"terms": {"field": "service.keyword"},
"aggs": {
"response_times": {
"percentiles": {
"field": "metrics.application.response_time_ms",
"percents": [50, 75, 90, 95, 99]
}
},
"availability": {
"stats": {"field": "metrics.uptime_percent"}
}
}
}
}
});
let data = self.client.search("metrics-*", query).await?;
self.parse_report(data)
}</code></pre>
</section>
</div>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-bash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-rust.js"></script>
<script>
function switchTab(evt, tabName) {
const container = evt.target.closest('.code-tabs');
const tabs = container.querySelectorAll('.tab-content');
const buttons = container.querySelectorAll('.tab-button');
tabs.forEach(tab => tab.classList.remove('active'));
buttons.forEach(btn => btn.classList.remove('active'));
document.getElementById(tabName).classList.add('active');
evt.target.classList.add('active');
}
</script>
</body>
</html>