splunk-hec-logging
The splunk-hec-logging plugin sends APISIX and API7 Gateway request and response logs to Splunk HTTP Event Collector (HEC) in Splunk Event Data format. The plugin batches delivery and supports customizable log formats.
Examples
The examples show how to send gateway request logs to Splunk and customize their contents with plugin metadata.
To follow the examples, set up a Splunk HEC endpoint:
- Docker
- Kubernetes
The official Splunk image is currently published for amd64. Set the gateway container name and the local evaluation credentials:
export GATEWAY_CONTAINER=replace-with-gateway-container-name
export SPLUNK_PASSWORD=Splunk-local-password-1234
export SPLUNK_HEC_TOKEN=apisix-hec-token
Create a dedicated network:
docker network create gateway-splunk-net
Connect the gateway to the network:
docker network connect gateway-splunk-net "$GATEWAY_CONTAINER"
Start Splunk Enterprise with HEC enabled. The required flags indicate acceptance of the Splunk General Terms:
docker run -d \
--platform linux/amd64 \
--name splunk-hec \
--network gateway-splunk-net \
-p 127.0.0.1:8000:8000 \
-p 127.0.0.1:8088:8088 \
-e SPLUNK_START_ARGS=--accept-license \
-e SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com \
-e SPLUNK_PASSWORD \
-e SPLUNK_HEC_TOKEN \
splunk/splunk:10.4.3-rhel9
After the container starts, verify that HEC is healthy:
curl -k "https://127.0.0.1:8088/services/collector/health"
You should receive {"text":"HEC is healthy","code":17}. If the command reports a connection error, wait a few seconds and run it again.
Set the HEC endpoint used by the Admin API and ADC examples:
export SPLUNK_HEC_ENDPOINT=https://splunk-hec:8088/services/collector/event
Splunk Web is available at http://localhost:8000; sign in as admin with the value of SPLUNK_PASSWORD.
Create a Kubernetes manifest to deploy Splunk with HEC enabled:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: aic
name: splunk-defaults
data:
default.yml: |
splunk:
hec:
enable: True
ssl: False
token: apisix-hec-token
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: splunk
spec:
replicas: 1
selector:
matchLabels:
app: splunk
template:
metadata:
labels:
app: splunk
spec:
enableServiceLinks: false
nodeSelector:
kubernetes.io/arch: amd64
containers:
- name: splunk
image: splunk/splunk:10.4.3-rhel9
env:
- name: SPLUNK_START_ARGS
value: "--accept-license"
# Accept Splunk General Terms: https://www.splunk.com/en_us/legal/splunk-general-terms.html
- name: SPLUNK_GENERAL_TERMS
value: "--accept-sgt-current-at-splunk-com"
- name: SPLUNK_PASSWORD
value: "Splunk@1234"
ports:
- name: hec
containerPort: 8088
- name: web
containerPort: 8000
volumeMounts:
- name: defaults
mountPath: /tmp/defaults
readinessProbe:
httpGet:
path: /services/collector/health
port: hec
initialDelaySeconds: 60
periodSeconds: 10
failureThreshold: 10
volumes:
- name: defaults
configMap:
name: splunk-defaults
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: splunk-hec
spec:
selector:
app: splunk
ports:
- name: hec
port: 8088
targetPort: hec
- name: web
port: 8000
targetPort: web
Apply the manifest:
kubectl apply -f splunk-hec-server.yaml
Wait for Splunk to become ready:
kubectl rollout status -n aic deployment/splunk
Set the HEC endpoint used by the Admin API and ADC examples:
export SPLUNK_HEC_ENDPOINT=http://splunk-hec.aic.svc.cluster.local:8088/services/collector/event
Port forward the Splunk Web port to your local machine:
kubectl port-forward -n aic svc/splunk-hec 8000:8000
Then open http://localhost:8000 and log in with username admin and password Splunk@1234.
The passwords and HEC token in these examples are for a trusted evaluation environment. Use the organization's secret-management system and TLS trust configuration for production deployments.
Send Logs to Splunk
The following example sends request logs from one route to Splunk HEC.
Create a route with the splunk-hec-logging plugin:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "splunk-route",
"uri": "/anything",
"plugins": {
"splunk-hec-logging": {
"endpoint": {
"uri": "$SPLUNK_HEC_ENDPOINT",
"token": "apisix-hec-token"
},
"ssl_verify": false,
"batch_max_size": 1
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}
EOF
services:
- name: httpbin
labels:
docs-example: splunk-hec-logging
routes:
- name: splunk-route
uris:
- /anything
plugins:
splunk-hec-logging:
endpoint:
uri: "${SPLUNK_HEC_ENDPOINT}"
token: apisix-hec-token
ssl_verify: false
batch_max_size: 1
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Preview the changes to services with the example label:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=splunk-hec-logging
Synchronize the reviewed changes:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=splunk-hec-logging
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: splunk-hec-logging-plugin-config
spec:
plugins:
- name: splunk-hec-logging
config:
endpoint:
uri: http://splunk-hec.aic.svc.cluster.local:8088/services/collector/event
token: apisix-hec-token
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: splunk-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: splunk-hec-logging-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: splunk-route
spec:
ingressClassName: apisix
http:
- name: splunk-route
match:
paths:
- /anything
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: splunk-hec-logging
enable: true
config:
endpoint:
uri: http://splunk-hec.aic.svc.cluster.local:8088/services/collector/event
token: apisix-hec-token
Apply the configuration:
kubectl apply -f splunk-hec-logging-ic.yaml
The Admin API and ADC examples set batch_max_size to 1 so each event is delivered immediately for verification. Omit this field to retain the default batching behavior. For the Docker HTTPS endpoint, ssl_verify: false accepts Splunk's self-signed evaluation certificate. Configure a trusted certificate and keep the default verification enabled in production.
Send a request to the route:
curl -i "http://127.0.0.1:9080/anything"
You should receive an HTTP/1.1 200 OK response.
In Splunk Web, open Search & Reporting. Search for source="apache-apisix-splunk-hec-logging" to find events from the gateway.
Log Request and Response Headers With Plugin Metadata
The following example uses plugin metadata to add selected request and response headers to splunk-hec-logging instances that do not define their own log_format. The metadata values reference built-in variables, so one configuration applies the same log fields across multiple routes and services.
Create a route with the splunk-hec-logging plugin:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "splunk-route",
"uri": "/anything",
"plugins": {
"splunk-hec-logging": {
"endpoint": {
"uri": "$SPLUNK_HEC_ENDPOINT",
"token": "apisix-hec-token"
},
"ssl_verify": false,
"batch_max_size": 1
}
},
"upstream": {
"nodes": {
"httpbin.org:80": 1
},
"type": "roundrobin"
}
}
EOF
services:
- name: httpbin
labels:
docs-example: splunk-hec-logging
routes:
- name: splunk-route
uris:
- /anything
plugins:
splunk-hec-logging:
endpoint:
uri: "${SPLUNK_HEC_ENDPOINT}"
token: apisix-hec-token
ssl_verify: false
batch_max_size: 1
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Preview the changes to services with the example label:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=splunk-hec-logging
Synchronize the reviewed changes:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=splunk-hec-logging
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: splunk-hec-logging-plugin-config
spec:
plugins:
- name: splunk-hec-logging
config:
endpoint:
uri: http://splunk-hec.aic.svc.cluster.local:8088/services/collector/event
token: apisix-hec-token
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: splunk-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: splunk-hec-logging-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: splunk-route
spec:
ingressClassName: apisix
http:
- name: splunk-route
match:
paths:
- /anything
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: splunk-hec-logging
enable: true
config:
endpoint:
uri: http://splunk-hec.aic.svc.cluster.local:8088/services/collector/event
token: apisix-hec-token
Apply the configuration:
kubectl apply -f splunk-hec-logging-ic.yaml
Configure the plugin metadata for splunk-hec-logging:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/splunk-hec-logging" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"log_format": {
"host": "$host",
"@timestamp": "$time_iso8601",
"route_id": "$route_id",
"client_ip": "$remote_addr",
"env": "$http_env",
"resp_content_type": "$sent_http_Content_Type"
}
}'
Plugin metadata is a global collection and cannot be isolated with a label selector. Export the complete collection before changing this entry:
adc dump -o adc-metadata.yaml --with-id \
--include-resource-type plugin_metadata
Add or update the splunk-hec-logging entry while preserving every other entry in adc-metadata.yaml:
plugin_metadata:
# Keep all other plugin metadata entries from the exported file.
splunk-hec-logging:
log_format:
host: "$host"
"@timestamp": "$time_iso8601"
route_id: "$route_id"
client_ip: "$remote_addr"
env: "$http_env"
resp_content_type: "$sent_http_Content_Type"
Preview the complete metadata change and confirm that it contains no unintended updates or deletions:
adc diff -f adc-metadata.yaml \
--include-resource-type plugin_metadata
Synchronize the reviewed plugin metadata collection:
adc sync -f adc-metadata.yaml \
--include-resource-type plugin_metadata
Add the following entry under spec.pluginMetadata in the complete GatewayProxy manifest used by the deployment:
splunk-hec-logging:
log_format:
host: "$host"
"@timestamp": "$time_iso8601"
route_id: "$route_id"
client_ip: "$remote_addr"
env: "$http_env"
resp_content_type: "$sent_http_Content_Type"
Apply the updated complete manifest through the deployment's normal Kubernetes or GitOps workflow.
❶ Log the custom request header env.
❷ Log the response header Content-Type.
Send a request to the route with the env header:
curl -i "http://127.0.0.1:9080/anything" -H "env: dev"
In Splunk Web, open Search & Reporting and search for source="apache-apisix-splunk-hec-logging".