Quick Start
This guide walks you through ingesting logs, traces, and metrics into IceGate and querying them via the API and Grafana.
Note
This guide assumes IceGate is already running. See Installation for Helm deployment or Development Setup for a local environment.
Ingest Logs
IceGate accepts data via the OpenTelemetry Protocol (OTLP) on the Ingest service.
Send Logs via OTLP HTTP
curl -X POST http://localhost:4318/v1/logs \
-H "Content-Type: application/json" \
-H "X-Scope-OrgID: demo" \
-d '{
"resourceLogs": [{
"resource": {
"attributes": [
{"key": "service.name", "value": {"stringValue": "my-service"}}
]
},
"scopeLogs": [{
"logRecords": [{
"timeUnixNano": "'$(date +%s)000000000'",
"body": {"stringValue": "User login successful"},
"severityText": "INFO",
"severityNumber": 9,
"attributes": [
{"key": "user.id", "value": {"stringValue": "user-42"}},
{"key": "http.method", "value": {"stringValue": "POST"}}
]
}]
}]
}]
}'
Send Logs via OTLP gRPC
Use any OpenTelemetry SDK. Example with Python:
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
provider = LoggerProvider()
provider.add_log_record_processor(
BatchLogRecordProcessor(
OTLPLogExporter(
endpoint="localhost:4317",
headers={"X-Scope-OrgID": "demo"},
insecure=True,
)
)
)
Ingest Traces
Send distributed trace spans:
curl -X POST http://localhost:4318/v1/traces \
-H "Content-Type: application/json" \
-H "X-Scope-OrgID: demo" \
-d '{
"resourceSpans": [{
"resource": {
"attributes": [
{"key": "service.name", "value": {"stringValue": "my-service"}}
]
},
"scopeSpans": [{
"spans": [{
"traceId": "5B8EFFF798038103D269B633813FC60C",
"spanId": "EEE19B7EC3C1B174",
"name": "GET /api/users",
"kind": 2,
"startTimeUnixNano": "'$(date +%s)000000000'",
"endTimeUnixNano": "'$(date +%s)100000000'",
"status": {"code": 1},
"attributes": [
{"key": "http.method", "value": {"stringValue": "GET"}},
{"key": "http.status_code", "value": {"intValue": "200"}}
]
}]
}]
}]
}'
Ingest Metrics
Send metrics data:
curl -X POST http://localhost:4318/v1/metrics \
-H "Content-Type: application/json" \
-H "X-Scope-OrgID: demo" \
-d '{
"resourceMetrics": [{
"resource": {
"attributes": [
{"key": "service.name", "value": {"stringValue": "my-service"}}
]
},
"scopeMetrics": [{
"metrics": [{
"name": "http_requests_total",
"sum": {
"dataPoints": [{
"startTimeUnixNano": "'$(date +%s)000000000'",
"timeUnixNano": "'$(date +%s)000000000'",
"asInt": "42",
"attributes": [
{"key": "method", "value": {"stringValue": "GET"}},
{"key": "status", "value": {"stringValue": "200"}}
]
}],
"aggregationTemporality": 2,
"isMonotonic": true
}
}]
}]
}]
}'
Query Logs with LogQL
IceGate provides a Loki-compatible API on the Query service (port 3100) - a subset of Loki's API,
listed in the API reference.
Basic Log Query
curl -G http://localhost:3100/loki/api/v1/query_range \
--data-urlencode 'query={service_name="my-service"}' \
--data-urlencode 'start='$(date -d '1 hour ago' +%s 2>/dev/null || date -v-1H +%s) \
--data-urlencode 'end='$(date +%s) \
--data-urlencode 'limit=100' \
-H "X-Scope-OrgID: demo"
Filter by Severity
curl -G http://localhost:3100/loki/api/v1/query_range \
--data-urlencode 'query={service_name="my-service", severity_text="ERROR"}' \
--data-urlencode 'start='$(date -d '1 hour ago' +%s 2>/dev/null || date -v-1H +%s) \
--data-urlencode 'end='$(date +%s) \
-H "X-Scope-OrgID: demo"
Search Log Content
curl -G http://localhost:3100/loki/api/v1/query_range \
--data-urlencode 'query={service_name="my-service"} |= "login"' \
--data-urlencode 'start='$(date -d '1 hour ago' +%s 2>/dev/null || date -v-1H +%s) \
--data-urlencode 'end='$(date +%s) \
-H "X-Scope-OrgID: demo"
Aggregate Logs into Metrics
# Count logs per 5-minute window
curl -G http://localhost:3100/loki/api/v1/query_range \
--data-urlencode 'query=count_over_time({service_name="my-service"}[5m])' \
--data-urlencode 'start='$(date -d '1 hour ago' +%s 2>/dev/null || date -v-1H +%s) \
--data-urlencode 'end='$(date +%s) \
--data-urlencode 'step=300' \
-H "X-Scope-OrgID: demo"
# Error rate per second
curl -G http://localhost:3100/loki/api/v1/query_range \
--data-urlencode 'query=rate({severity_text="ERROR"}[1m])' \
--data-urlencode 'start='$(date -d '1 hour ago' +%s 2>/dev/null || date -v-1H +%s) \
--data-urlencode 'end='$(date +%s) \
--data-urlencode 'step=60' \
-H "X-Scope-OrgID: demo"
Explore Labels and Series
List All Labels
curl http://localhost:3100/loki/api/v1/labels \
-H "X-Scope-OrgID: demo"
Get Values for a Label
curl http://localhost:3100/loki/api/v1/label/service_name/values \
-H "X-Scope-OrgID: demo"
Find Matching Series
curl -G http://localhost:3100/loki/api/v1/series \
--data-urlencode 'match[]={service_name=~"my-.*"}' \
-H "X-Scope-OrgID: demo"
Using Grafana
IceGate is compatible with Grafana's Loki data source for log visualization and dashboarding.
Add IceGate as a Data Source
- Open Grafana (default: http://localhost:3000)
- Go to Connections > Data sources > Add data source
- Select Loki
- Set the URL to
http://icegate-query:3100(orhttp://localhost:3100for local access) - Under HTTP Headers, add:
- Header:
X-Scope-OrgID - Value:
demo
- Header:
- Click Save & Test
Explore Logs
- Go to Explore
- Select the Loki data source
- Enter a LogQL query:
{service_name="my-service"} - Click Run query
- Switch between Logs and Graph views
Build a Dashboard
- Go to Dashboards > New > New Dashboard
- Add a Logs panel:
- Query:
{service_name="my-service"} - Visualization: Logs
- Query:
- Add a Time series panel for error rate:
- Query:
sum by (service_name) (rate({severity_text="ERROR"}[5m])) - Visualization: Time series
- Query:
- Add a Stat panel for log volume:
- Query:
sum(count_over_time({service_name="my-service"}[1h])) - Visualization: Stat
- Query:
Pre-Built Dashboards
If deployed with the Kustomize overlays or Docker Compose, Grafana comes pre-configured with IceGate dashboards for Ingest and Query service metrics.
Using the OpenTelemetry Collector
For production workloads, use the OpenTelemetry Collector to forward data from your applications to IceGate:
# otel-collector-config.yaml
exporters:
otlp/icegate:
endpoint: icegate-ingest:4317
tls:
insecure: true
headers:
X-Scope-OrgID: my-tenant
service:
pipelines:
logs:
receivers: [otlp]
exporters: [otlp/icegate]
traces:
receivers: [otlp]
exporters: [otlp/icegate]
metrics:
receivers: [otlp]
exporters: [otlp/icegate]
Multi-Tenancy
IceGate isolates data by tenant using the X-Scope-OrgID header. Each tenant's data is physically partitioned.
# Ingest for tenant "team-a"
curl -X POST http://localhost:4318/v1/logs \
-H "X-Scope-OrgID: team-a" \
-H "Content-Type: application/json" \
-d '...'
# Query only sees team-a's data
curl -G http://localhost:3100/loki/api/v1/query_range \
--data-urlencode 'query={service_name="api"}' \
-H "X-Scope-OrgID: team-a"
See Multi-Tenancy for details.
Next Steps
- Learn LogQL querying in depth
- Explore the Loki API reference
- Configure data ingestion pipelines
- Understand the data model