Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Trickster works with virtually any Dashboard application that makes queries to a

<img src="./docs/images/external/influx_logo_60.png" width=16 /> InfluxDB

Elasticsearch

See the [Supported TSDB Providers](./docs/supported-backend-providers.md) document for full details

### How Trickster Accelerates Time Series
Expand Down
2 changes: 1 addition & 1 deletion deploy/kube/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ data:
default:

# provider identifies the backend provider.
# Valid options are: prometheus, influxdb, clickhouse, reverseproxycache (or just rpc)
# Valid options are: prometheus, influxdb, clickhouse, elasticsearch, reverseproxycache (or just rpc)
# provider is a required configuration value
provider: prometheus

Expand Down
12 changes: 12 additions & 0 deletions docs/developer/environment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,25 @@ You can combine these make actions `make developer-start serve-dev` if you want.

Once you have the Docker Compose running, and Trickster running locally, visit
the Grafana Dashboard at <http://127.0.0.1:3000/d/uAJ8w1wZz/trickster-status>.
The Kibana frontend is available at <http://127.0.0.1:5601> and is configured
to use Trickster's `es1` Elasticsearch backend at
`http://host.docker.internal:8480/es1`.

The data in this dashboard is polled by Prometheus from your local Trickster
dev instance. So the longer you keep this dashboard up and refreshing, the more
you can test out Trickster acceleration features. You can change the Data Source
selector to go between various Trickster configs, or bypass Trickster altogether
for verification purposes.

Elasticsearch is seeded on startup with the `trickster-dev-logs` index. The seed
data includes recent and older `@timestamp` values so developers can verify
Elasticsearch date histogram caching through Trickster.
After Kibana connects through Trickster, the Kibana seed container creates the
`Trickster Dev Logs` data view, saved search, and dashboard for that index. The
dashboard includes a minute-aligned log-volume histogram that exercises Delta
Proxy Cache requests, followed by the generated log documents. It is available at
<http://127.0.0.1:5601/app/dashboards#/view/trickster-dev-logs-dashboard>.

You can stop the developer environment by running `make developer-stop`. To
delete the developer environment, run `make developer-delete` which will destroy
all data.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/bin/sh

#
# Copyright 2018 The Trickster Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

set -eu

ES_URL="${ES_URL:-http://elasticsearch:9200}"
ES_INDEX="${ES_INDEX:-trickster-dev-logs}"

wait_for_elasticsearch() {
echo "waiting for Elasticsearch at ${ES_URL}"
until curl -fsS "${ES_URL}/_cluster/health?wait_for_status=yellow&timeout=1s" >/dev/null 2>&1; do
sleep 2
done
}

iso_utc() {
date -u -d "@$1" '+%Y-%m-%dT%H:%M:%SZ'
}

create_index() {
echo "creating ${ES_INDEX}"
curl -fsS -X DELETE "${ES_URL}/${ES_INDEX}" >/dev/null 2>&1 || true
curl -fsS -X PUT "${ES_URL}/${ES_INDEX}" \
-H 'Content-Type: application/json' \
-d '{
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"event_id": { "type": "keyword" },
"service": { "type": "keyword" },
"level": { "type": "keyword" },
"status_code": { "type": "integer" },
"duration_ms": { "type": "integer" },
"cacheable": { "type": "boolean" },
"message": { "type": "text" }
}
}
}' >/dev/null
}

append_log() {
event_id="$1"
timestamp="$2"
service="$3"
level="$4"
status_code="$5"
duration_ms="$6"
cacheable="$7"
message="$8"

printf '{"index":{"_index":"%s","_id":"%s"}}\n' "${ES_INDEX}" "${event_id}" >> "${BULK_FILE}"
printf '{"@timestamp":"%s","event_id":"%s","service":"%s","level":"%s","status_code":%s,"duration_ms":%s,"cacheable":%s,"message":"%s"}\n' \
"${timestamp}" "${event_id}" "${service}" "${level}" "${status_code}" "${duration_ms}" "${cacheable}" "${message}" >> "${BULK_FILE}"
}

seed_recent_logs() {
now="$(date -u +%s)"
i=0
while [ "${i}" -lt 180 ]; do
ts="$(iso_utc "$((now - (i * 60)))")"
case $((i % 4)) in
0) service="api"; level="info"; status=200; cacheable=true ;;
1) service="worker"; level="info"; status=202; cacheable=true ;;
2) service="edge"; level="warn"; status=429; cacheable=false ;;
*) service="checkout"; level="error"; status=500; cacheable=false ;;
esac
duration="$((25 + (i % 45)))"
append_log "recent-${i}" "${ts}" "${service}" "${level}" "${status}" "${duration}" "${cacheable}" "recent trickster developer log ${i}"
i=$((i + 1))
done
}

seed_older_logs() {
now="$(date -u +%s)"
i=0
while [ "${i}" -lt 72 ]; do
ts="$(iso_utc "$((now - (3 * 86400) - (i * 3600)))")"
case $((i % 3)) in
0) service="api"; level="info"; status=200; cacheable=true ;;
1) service="edge"; level="warn"; status=404; cacheable=false ;;
*) service="worker"; level="error"; status=503; cacheable=false ;;
esac
duration="$((50 + (i % 75)))"
append_log "older-${i}" "${ts}" "${service}" "${level}" "${status}" "${duration}" "${cacheable}" "older trickster developer log ${i}"
i=$((i + 1))
done
}

load_bulk_data() {
echo "loading generated log data into ${ES_INDEX}"
curl -fsS -X POST "${ES_URL}/_bulk?refresh=true" \
-H 'Content-Type: application/x-ndjson' \
--data-binary "@${BULK_FILE}" >/dev/null
}

BULK_FILE="$(mktemp)"
trap 'rm -f "${BULK_FILE}"' EXIT

wait_for_elasticsearch
create_index
seed_recent_logs
seed_older_logs
load_bulk_data

echo "seeded ${ES_INDEX}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/bin/sh

#
# Copyright 2018 The Trickster Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

set -eu

KIBANA_URL="${KIBANA_URL:-http://kibana:5601}"
KIBANA_VERSION="${KIBANA_VERSION:-8.17.3}"

wait_for_kibana() {
echo "waiting for Kibana at ${KIBANA_URL}"
i=0
until curl -fsS "${KIBANA_URL}/api/status" 2>/dev/null | grep -q '"level":"available"'; do
i=$((i + 1))
if [ "${i}" -gt 450 ]; then
echo "timed out waiting for Kibana" >&2
return 1
fi
sleep 2
done
}

post_json() {
path="$1"
file="$2"
curl -fsS -X POST "${KIBANA_URL}${path}" \
-H 'kbn-xsrf: true' \
-H 'Content-Type: application/json' \
--data-binary "@${file}" >/dev/null
}

create_kibana_config() {
cat > "${CONFIG_FILE}" <<JSON
{
"attributes": {
"defaultIndex": "trickster-dev-logs",
"dateFormat:tz": "UTC"
}
}
JSON
post_json "/api/saved_objects/config/${KIBANA_VERSION}?overwrite=true" "${CONFIG_FILE}"
}

create_data_view() {
cat > "${DATA_VIEW_FILE}" <<JSON
{
"data_view": {
"id": "trickster-dev-logs",
"title": "trickster-dev-logs",
"name": "Trickster Dev Logs",
"timeFieldName": "@timestamp"
},
"override": true
}
JSON
post_json "/api/data_views/data_view" "${DATA_VIEW_FILE}"
}

create_saved_search() {
cat > "${SEARCH_FILE}" <<JSON
{
"attributes": {
"title": "Trickster Dev Logs",
"description": "Generated Elasticsearch logs for Trickster developer environment verification.",
"columns": ["@timestamp", "level", "service", "message", "duration_ms", "cacheable"],
"sort": [["@timestamp", "desc"]],
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
}
},
"references": [
{
"name": "kibanaSavedObjectMeta.searchSourceJSON.index",
"type": "index-pattern",
"id": "trickster-dev-logs"
}
]
}
JSON
post_json "/api/saved_objects/search/trickster-dev-logs-search?overwrite=true" "${SEARCH_FILE}"
}

create_log_volume_visualization() {
cat > "${VISUALIZATION_FILE}" <<JSON
{
"attributes": {
"title": "Trickster Dev Log Volume",
"description": "Minute-by-minute log volume used to exercise Elasticsearch date histogram caching through Trickster.",
"visState": "{\"title\":\"Trickster Dev Log Volume\",\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":false,\"legendPosition\":\"right\",\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"m\",\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"drop_partials\":false,\"min_doc_count\":0,\"extended_bounds\":{},\"extendToTimeRange\":true}}],\"listeners\":{}}",
"uiStateJSON": "{}",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
}
},
"references": [
{
"name": "kibanaSavedObjectMeta.searchSourceJSON.index",
"type": "index-pattern",
"id": "trickster-dev-logs"
}
]
}
JSON
post_json "/api/saved_objects/visualization/trickster-dev-log-volume?overwrite=true" "${VISUALIZATION_FILE}"
}

create_dashboard() {
cat > "${DASHBOARD_FILE}" <<JSON
{
"attributes": {
"title": "Trickster Dev Logs",
"description": "Out-of-box dashboard for the generated Elasticsearch log data served through Trickster.",
"hits": 0,
"optionsJSON": "{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}",
"panelsJSON": "[{\"version\":\"8.17.3\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":12,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{},\"panelRefName\":\"panel_1\"},{\"version\":\"8.17.3\",\"type\":\"search\",\"gridData\":{\"x\":0,\"y\":12,\"w\":48,\"h\":18,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{},\"panelRefName\":\"panel_2\"}]",
"timeRestore": true,
"timeFrom": "now-120m/m",
"timeTo": "now/m-1ms",
"refreshInterval": {
"pause": true,
"value": 0
},
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
}
},
"references": [
{
"name": "panel_1",
"type": "visualization",
"id": "trickster-dev-log-volume"
},
{
"name": "panel_2",
"type": "search",
"id": "trickster-dev-logs-search"
}
]
}
JSON
post_json "/api/saved_objects/dashboard/trickster-dev-logs-dashboard?overwrite=true" "${DASHBOARD_FILE}"
}

CONFIG_FILE="$(mktemp)"
DATA_VIEW_FILE="$(mktemp)"
SEARCH_FILE="$(mktemp)"
VISUALIZATION_FILE="$(mktemp)"
DASHBOARD_FILE="$(mktemp)"
trap 'rm -f "${CONFIG_FILE}" "${DATA_VIEW_FILE}" "${SEARCH_FILE}" "${VISUALIZATION_FILE}" "${DASHBOARD_FILE}"' EXIT

wait_for_kibana
create_kibana_config
create_data_view
create_saved_search
create_log_volume_visualization
create_dashboard

echo "seeded Kibana data view, visualization, and dashboard for trickster-dev-logs"
Loading
Loading