mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
The rule table mapped HOG_ -> FN_ ahead of any POSTHOG rule, so POSTHOG_FOO split into POST + HOG_ and came out POSTFN_FOO. Nothing sets that. The live pods set INSIGHTS_SKIP_MIGRATION_CHECKS, which bin/migrate-check reads on the container entrypoint, so the misspelling does not degrade a feature -- it runs migrate --check against a database whose history this tree does not share and the container never starts. Both replacements are measured against the shipped tree rather than chosen: every HOG_ name with a counterpart there is spelled INSIGHTS_ (HOG_QL -> INSIGHTS_QL, HOG_FUNCTION_TEMPLATES -> INSIGHTS_FUNCTION_TEMPLATES, 12 of 12 determinate cases), and FN_ appears in it nowhere. Upstream carries 95 HOG_ tokens and zero FN_ ones, so repairing FN_ back out is exactly the inverse of the bad rule and cannot collide with an upstream name. The rule is fixed for the next convergence, and the tree it already produced is repaired in the same commit -- the codemod is idempotent against its own output, so it cannot undo this itself.
192 lines
6.5 KiB
Bash
Executable File
192 lines
6.5 KiB
Bash
Executable File
#!/bin/sh
|
|
# Renders the OpenTelemetry Collector config for the Insights metrics agent,
|
|
# then execs the collector. See README.md for the env var surface.
|
|
#
|
|
# Config resolution order:
|
|
# 1. $CONFIG_DIR/config.yaml - full config override, used verbatim
|
|
# 2. $CONFIG_DIR/scrape_configs.yaml - custom scrape_configs spliced into the template
|
|
# 3. SCRAPE_TARGETS env var - static scrape job rendered from env
|
|
#
|
|
# Scalar values (API key, host, interval, ...) are left as ${env:VAR} references
|
|
# for the collector's native config substitution, so secrets never pass through
|
|
# this script. Only the scrape_configs block structure is rendered here, because
|
|
# env substitution cannot expand a comma-separated string into a YAML list.
|
|
#
|
|
# RENDER_ONLY=1 prints the resolved config and exits (used by tests/render).
|
|
set -eu
|
|
|
|
CONFIG_DIR="${CONFIG_DIR:-/etc/insights}"
|
|
TEMPLATE="$CONFIG_DIR/config.yaml.tmpl"
|
|
RENDERED="${RENDERED_CONFIG:-/tmp/config.yaml}"
|
|
OTELCOL="${OTELCOL_BIN:-/usr/local/bin/otelcol-contrib}"
|
|
|
|
finish() {
|
|
if [ "${RENDER_ONLY:-}" = "1" ]; then
|
|
cat "$1"
|
|
exit 0
|
|
fi
|
|
exec "$OTELCOL" --config "$1"
|
|
}
|
|
|
|
# Sharding: with SHARD_COUNT set, each instance keeps only the targets that
|
|
# hash to its SHARD_INDEX, so a fleet partitions the target set with no
|
|
# coordination. The index falls back to the hostname's trailing ordinal
|
|
# (StatefulSet pods are named <name>-<ordinal>), matching how vmagent shards.
|
|
# Resolved before any config path so mounted configs can reference
|
|
# ${env:SHARD_INDEX} too.
|
|
SHARD_COUNT="${SHARD_COUNT:-1}"
|
|
case "$SHARD_COUNT" in
|
|
'' | *[!0-9]*)
|
|
echo "error: SHARD_COUNT must be a positive integer, got '$SHARD_COUNT'" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ "$SHARD_COUNT" -gt 1 ]; then
|
|
if [ -z "${SHARD_INDEX:-}" ]; then
|
|
host="${HOSTNAME:-$(hostname)}"
|
|
SHARD_INDEX=$(printf '%s' "$host" | sed -n 's/.*-\([0-9][0-9]*\)$/\1/p')
|
|
if [ -z "$SHARD_INDEX" ]; then
|
|
echo "error: SHARD_INDEX is not set and cannot be derived from hostname '$host'" \
|
|
"(expected a trailing -<ordinal>, e.g. a StatefulSet pod name)" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
case "$SHARD_INDEX" in
|
|
'' | *[!0-9]*)
|
|
echo "error: SHARD_INDEX must be a non-negative integer, got '$SHARD_INDEX'" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ "$SHARD_INDEX" -ge "$SHARD_COUNT" ]; then
|
|
echo "error: SHARD_INDEX must be less than SHARD_COUNT ($SHARD_INDEX >= $SHARD_COUNT)" >&2
|
|
exit 1
|
|
fi
|
|
export SHARD_INDEX
|
|
fi
|
|
|
|
if [ -f "$CONFIG_DIR/config.yaml" ]; then
|
|
finish "$CONFIG_DIR/config.yaml"
|
|
fi
|
|
|
|
if [ -z "${INSIGHTS_API_KEY:-}" ]; then
|
|
echo "error: INSIGHTS_API_KEY is required (your Insights project API key)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SNIPPET=$(mktemp)
|
|
trap 'rm -f "$SNIPPET"' EXIT
|
|
|
|
if [ -f "$CONFIG_DIR/scrape_configs.yaml" ]; then
|
|
# Re-indent the mounted scrape_configs list under the prometheus receiver.
|
|
awk '{ if ($0 == "") print ""; else print " " $0 }' \
|
|
"$CONFIG_DIR/scrape_configs.yaml" >"$SNIPPET"
|
|
else
|
|
if [ -z "${SCRAPE_TARGETS:-}" ]; then
|
|
echo "error: SCRAPE_TARGETS is required (comma-separated host:port list)," \
|
|
"unless you mount $CONFIG_DIR/scrape_configs.yaml or $CONFIG_DIR/config.yaml" >&2
|
|
exit 1
|
|
fi
|
|
|
|
TARGETS=""
|
|
OLDIFS=$IFS
|
|
IFS=,
|
|
for target in $SCRAPE_TARGETS; do
|
|
target=$(printf '%s' "$target" | sed 's/^ *//;s/ *$//')
|
|
[ -n "$target" ] || continue
|
|
# Double single quotes so the target stays valid inside YAML quotes.
|
|
target=$(printf '%s' "$target" | sed "s/'/''/g")
|
|
if [ -n "$TARGETS" ]; then
|
|
TARGETS="$TARGETS, '$target'"
|
|
else
|
|
TARGETS="'$target'"
|
|
fi
|
|
done
|
|
IFS=$OLDIFS
|
|
|
|
if [ -z "$TARGETS" ]; then
|
|
echo "error: SCRAPE_TARGETS contained no targets" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cat >"$SNIPPET" <<EOF
|
|
- job_name: '\${env:SCRAPE_JOB_NAME:-insights-metrics-agent}'
|
|
scrape_interval: '\${env:SCRAPE_INTERVAL:-15s}'
|
|
metrics_path: '\${env:SCRAPE_METRICS_PATH:-/metrics}'
|
|
# OpenMetrics first so exemplars (trace links) survive the scrape.
|
|
scrape_protocols: [OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText0.0.4]
|
|
static_configs:
|
|
- targets: [$TARGETS]
|
|
EOF
|
|
|
|
if [ "$SHARD_COUNT" -gt 1 ]; then
|
|
cat >>"$SNIPPET" <<EOF
|
|
# Shard $SHARD_INDEX of $SHARD_COUNT: keep only targets that hash to this shard.
|
|
relabel_configs:
|
|
- source_labels: [__address__]
|
|
modulus: $SHARD_COUNT
|
|
target_label: __tmp_shard
|
|
action: hashmod
|
|
- source_labels: [__tmp_shard]
|
|
regex: '$SHARD_INDEX'
|
|
action: keep
|
|
EOF
|
|
fi
|
|
fi
|
|
|
|
DEBUG_ENABLED=0
|
|
case "${INSIGHTS_DEBUG:-}" in
|
|
1 | true | TRUE | yes) DEBUG_ENABLED=1 ;;
|
|
esac
|
|
|
|
PERSIST_ENABLED=0
|
|
case "${PERSIST_QUEUE:-}" in
|
|
1 | true | TRUE | yes) PERSIST_ENABLED=1 ;;
|
|
esac
|
|
|
|
awk -v snippet="$SNIPPET" -v debug="$DEBUG_ENABLED" -v persist="$PERSIST_ENABLED" '
|
|
$0 == "#__SCRAPE_CONFIGS__" {
|
|
while ((getline line < snippet) > 0) print line
|
|
close(snippet)
|
|
next
|
|
}
|
|
$0 == "#__DEBUG_EXPORTER__" {
|
|
if (debug == "1") {
|
|
print " debug:"
|
|
print " verbosity: detailed"
|
|
}
|
|
next
|
|
}
|
|
$0 == "#__SENDING_QUEUE__" {
|
|
if (persist == "1") {
|
|
print " sending_queue:"
|
|
print " enabled: true"
|
|
print " # Survives restarts: batches persist to disk until delivered."
|
|
print " storage: file_storage"
|
|
}
|
|
next
|
|
}
|
|
$0 == "#__FILE_STORAGE__" {
|
|
if (persist == "1") {
|
|
print " file_storage:"
|
|
print " directory: \x27${env:QUEUE_DIR:-/var/lib/insights-agent}\x27"
|
|
print " create_directory: true"
|
|
}
|
|
next
|
|
}
|
|
index($0, "__SERVICE_EXTENSIONS__") {
|
|
extensions = (persist == "1") ? "health_check, file_storage" : "health_check"
|
|
sub(/__SERVICE_EXTENSIONS__/, extensions)
|
|
print
|
|
next
|
|
}
|
|
index($0, "__PIPELINE_EXPORTERS__") {
|
|
exporters = (debug == "1") ? "otlphttp, debug" : "otlphttp"
|
|
sub(/__PIPELINE_EXPORTERS__/, exporters)
|
|
print
|
|
next
|
|
}
|
|
{ print }
|
|
' "$TEMPLATE" >"$RENDERED"
|
|
|
|
finish "$RENDERED"
|