Dataway¶
Introduction¶
Dataway is the data gateway of Guance. All data reported by collectors to Guance must pass through the Dataway gateway.
Dataway Installation¶
- Create a New Dataway
In the Guance Management Console, go to the "Data Gateway" page and click Create Dataway. Enter the name and binding address, then click Create.
After creation, a new Dataway is automatically created and an installation script is generated.
Info
The binding address is the Dataway gateway address. It must be a complete HTTP address, for example http(s)://1.2.3.4:9528, including the protocol, host address, and port. The host address can usually be the IP address of the machine where Dataway is deployed, or it can be a domain name that has been resolved.
Note: Ensure that the collector can access this address; otherwise, data collection will not succeed.
- Install Dataway
DW_KODO=http://kodo_ip:port \
DW_TOKEN=<tkn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX> \
DW_UUID=<YOUR_UUID> \
bash -c "$(curl https://static.guance.com/dataway/install.sh)"
Host installation is no longer recommended. Please install Dataway directly via Kubernetes StatefulSet.
After installation, a dataway.yaml file is generated in the installation directory. The example content is shown below. You can modify it manually and restart the service for changes to take effect.
dataway.yaml (click to expand)
# ============= DATAWAY CONFIG =============
# Dataway UUID, we can get it on during create a new dataway
uuid:
# It's the workspace token, most of the time, it's
# system worker space's token.
token:
# secret_token used under sinker mode, and to check if incomming datakit
# requests are valid.
secret_token:
# If __internal__ token allowed? If ok, the data/request will direct to
# the workspace with the token above
enable_internal_token: false
# is empty token allowed? If ok, the data/request will direct to
# the workspace with the token above
enable_empty_token: false
# Is dataway cascaded? For cascaded Dataway, it's remote_host is
# another Dataway and not Kodo.
cascaded: false
# kodo(next dataway) related configures
remote_host:
http_timeout: 3s
http_max_idle_conn_perhost: 0 # default to CPU cores
http_max_conn_perhost: 0 # default no limit
kodo_queue:
enabled: true
workers: 256
queue_size: 1024
queue_max_bytes: 1073741824 # 1GB
enqueue_timeout: 100ms
insecure_skip_verify: false
http_client_trace: false
sni: ""
# dataway API configures
# IPv4 and IPv6 use separate listeners to avoid OS bindv6only behavior
bind: 0.0.0.0:9528
# IPv6 is disabled by default; explicitly set to "[::]:9528" when needed
bind_ipv6: ""
# Only requests from trusted proxies use forwarded headers for IP whitelist evaluation
# trusted_proxies:
# - 10.0.0.0/8
# - 2001:db8:ffff::/48
# disable 404 page
disable_404page: false
# dataway TLS file path
tls_crt:
tls_key:
# pprof is disabled by default; only loopback addresses are allowed
pprof_bind: ""
api_limit_rate : 100000 # 100K
max_http_body_bytes : 67108864 # 64MB
copy_buffer_drop_size : 262144 # 256KB, if copy buffer memory larger than this, this memory released
reserved_pool_size: 4096 # reserved pool size for better GC
within_docker: false
log_level: info
log: log
gin_log: gin.log
ip_black_list:
ttl: "1m"
clean_interval: "1h"
cache_cfg:
# cache disk path
dir: "disk_cache"
# disable cache
disabled: false
clean_interval: "1s"
# in MB, max single data package size in disk cache, such as HTTP body
max_data_size: 100
# in MB, single disk-batch(single file) size
batch_size: 128
# in MB, max disk size allowed to cache data
max_disk_size: 65535
# expire duration, default 7 days
expire_duration: "168h"
prometheus:
listen: "localhost:9090"
url: "/metrics"
enable: true
#sinker:
# cache_options:
# prealloc: true
# reserved_capacity: 10000000 # max cached items
# buckets: 64
# ttl: 10m # clear unactive matches
# etcd:
# urls:
# - http://localhost:2379 # one or multiple etcd host
# dial_timeout: 30s
# key_space: "/dw_sinker" # subscribe to the etcd key
# username: "dataway"
# password: "<PASSWORD>"
# file:
# path: /path/to/sinker.json
Dataway pod yaml is as follows:
dataway-statefulset.yaml (click to expand)
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: sts-utils-dataway
name: dataway
namespace: utils
spec:
replicas: 2
selector:
matchLabels:
app: sts-utils-dataway
serviceName: dataway
template:
metadata:
annotations:
datakit/logs: |
[
{
"disable": false,
"source": "dataway",
"service": "dataway",
"multiline_match": "^\\d{4}|^\\[GIN\\]"
}
]
datakit/prom.instances: |
[[inputs.prom]]
url = "http://$IP:9090/metrics"
source = "dataway"
measurement_name = "dw"
interval = "10s"
disable_instance_tag = true
[inputs.prom.tags]
service = "dataway"
instance = "$PODNAME" # we can set as "xxx-$PODNAME"
labels:
app: sts-utils-dataway
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- sts-utils-dataway
topologyKey: kubernetes.io/hostname
containers:
- env:
- name: DW_REMOTE_HOST
value: http://kodo.forethought-kodo:9527
- name: DW_BIND
value: 0.0.0.0:9528
# To enable IPv6, uncomment the following two lines
# - name: DW_BIND_IPV6
# value: "[::]:9528"
- name: DW_UUID
value: agnt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Dataway UUID
- name: DW_TOKEN
value: tkn_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Dataway token
- name: DW_PROM_LISTEN
value: 0.0.0.0:9090
- name: DW_LOG
value: stdout
- name: DW_LOG_LEVEL
value: info
- name: DW_GIN_LOG
value: stdout
- name: DW_DISKCACHE_DIR
value: cache
- name: DW_HTTP_TIMEOUT
value: '3s'
- name: DW_ENABLE_INTERNAL_TOKEN
value: 'false'
- name: DW_MAX_HTTP_BODY_BYTES
value: '67108864'
- name: DW_HTTP_CLIENT_TRACE
value: 'on'
- name: DW_RESERVED_POOL_SIZE
value: '0'
- name: DW_COPY_BUFFER_DROP_SIZE
value: '262144'
- name: DW_DISKCACHE_CAPACITY_MB
value: 102400
image: pubrepo.guance.com/dataflux/dataway:1.19.0
imagePullPolicy: IfNotPresent
name: dataway
ports:
- containerPort: 9528
name: 9528tcp01
protocol: TCP
resources:
limits:
cpu: '4'
memory: 4Gi
requests:
cpu: 100m
memory: 512Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /usr/local/cloudcare/dataflux/dataway/cache
name: dataway-cache
dnsPolicy: ClusterFirst
imagePullSecrets: []
#nodeSelector:
# nodepool: dataway
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
#tolerations:
# - effect: NoSchedule
# key: nodepool
# operator: Equal
# value: dataway
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dataway-cache
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: xxxxxx # High-Performance Storage StorageClass
volumeMode: Filesystem
status:
phase: Pending
---
apiVersion: v1
kind: Service
metadata:
name: dataway
namespace: utils
spec:
ipFamilyPolicy: SingleStack # Change to PreferDualStack for dual-stack
# ipFamilies:
# - IPv4
# - IPv6
ports:
- name: 9528tcp02
nodePort: 30928
port: 9528
protocol: TCP
targetPort: 9528
selector:
app: sts-utils-dataway
type: NodePort
The default example uses IPv4 single-stack. To enable dual-stack, ensure your Kubernetes cluster and CNI support IPv4/IPv6 dual-stack, then modify the following configurations:
- In the Dataway container environment variables, uncomment
DW_BIND_IPV6and set it to[::]:9528to make Dataway listen on both IPv4 and IPv6. - Change the Service's
ipFamilyPolicyfromSingleStacktoPreferDualStackand uncomment theIPv4andIPv6entries underipFamilies.
Both changes must be applied together. If you only modify the Service without setting DW_BIND_IPV6, Dataway will not accept IPv6 requests.
In the dataway-statefulset.yaml, you can modify Dataway configuration via environment variables. See here.
You can also mount a dataway.yaml via ConfigMap, but it must be mounted to /usr/local/cloudcare/dataflux/dataway/dataway.yaml:
Container installation uses the same environment variables as Kubernetes. Start a Dataway container with the following Docker command:
docker run -d \
--name <YOUR-DW-IN-DOCKER> \
-p 19528:9528 -p 19090:9090 \
--mount type=bind,source=<host/path/for/diskcache>,target=/usr/local/cloudcare/dataflux/dataway/cache \
--memory=2g --memory-reservation=256m \
--cpus="2" \
-e DW_UUID=<YOUR-AGNT_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX> \
-e DW_TOKEN=<YOUR-TKN_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX> \
-e DW_REMOTE_HOST=http://kodo.forethought-kodo:9527 \
-e DW_BIND=0.0.0.0:9528 \
-e DW_PROM_LISTEN=0.0.0.0:9090 \
-e DW_HTTP_CLIENT_TRACE=true \
-e DW_LOG_LEVEL=info \
-e DW_LOG=stdout \
-e DW_GIN_LOG=stdout \
-e DW_DISKCACHE_CAPACITY_MB=65536 \
pubrepo.guance.com/dataflux/dataway:1.19.0
Important Notes
- Dataway runs only on Linux (currently only Linux arm64/amd64 binaries are released).
- For host installation, the Dataway installation path is /usr/local/cloudcare/dataflux/dataway.
- Under Kubernetes, the default resource limits are 4000m CPU and 4Gi memory. Adjust as needed. Minimum requirements are 100m CPU and 512Mi memory.
- Verify Dataway Installation
After installation, wait a moment and refresh the "Data Gateway" page. If you see a version number in the "Version Information" column of the newly added Dataway, it means the Dataway has successfully connected to the Guance center. Front-end users can then use it to ingest data.
Once Dataway successfully connects to the Guance center, log in to the Guance console. On the "Integrations" / "DataKit" page, you will see all Dataway addresses. Select the desired Dataway gateway address, obtain the DataKit installation command, and execute it on the server to start data collection.
Manage Dataway¶
Delete Dataway¶
On the Guance Management Console "Data Gateway" page, select the Dataway to delete, click Configure, and in the Edit Dataway dialog, click the Delete button at the bottom left.
Warning
After deleting the Dataway, you must also log in to the server where the Dataway gateway is deployed, stop the Dataway process, and delete the installation directory to completely remove the Dataway.
Upgrade Dataway¶
On the Guance Management Console "Data Gateway" page, if an upgrade is available for a Dataway, an upgrade prompt will appear in the version information area.
Dataway Service Management¶
For host-installed Dataway, use the following commands to manage the Dataway service.
# Start
$ systemctl start dataway
# Restart
$ systemctl restart dataway
# Stop
$ systemctl stop dataway
For Kubernetes, restart the corresponding Pod.
Environment Variables¶
Image Environment Variables¶
When Dataway runs in a Kubernetes environment, it supports the following environment variables.
Compatibility with existing dataway.yaml
Some older Dataway deployments inject configuration via ConfigMap (the file mounted into the container is usually named dataway.yaml).
If the Dataway image detects that such a ConfigMap-mounted file exists in the installation directory after startup, the following DW_* environment variables will not take effect.
These environment variables will only take effect after the existing ConfigMap mount is removed.
When environment variables are active, a hidden file (visible with ls -a) named .dataway.yaml will be created in the Dataway installation directory. You can cat this file to verify that the environment variables have been applied.
HTTP Server Settings¶
| Env | Description |
|---|---|
| DW_REMOTE_HOST type: string required: Y |
Kodo address, or next Dataway address, e.g., http://host:port |
| DW_WHITE_LIST type: string required: N |
Dataway client IP whitelist, separated by commas (,) |
| DW_TRUSTED_PROXIES type: string required: N |
Trusted proxy IP/CIDR, separated by commas (,); only requests from trusted proxies use X-Forwarded-For or X-Real-IP for whitelist evaluation |
| DW_HTTP_TIMEOUT type: string required: N |
Timeout for Dataway requests to Kodo or the next Dataway, default 3s |
| DW_HTTP_MAX_IDLE_CONN_PERHOST type: int required: N |
Maximum idle connection setting for Dataway requests to Kodo Version-1.6.2 Default value: 1000 Version-1.11.2 |
| DW_HTTP_MAX_CONN_PERHOST type: int required: N |
Maximum number of connections for Dataway requests to Kodo. Default: no limit Version-1.6.2 |
| DW_KODO_QUEUE_ENABLED type: boolean required: N |
Enable a bounded dispatch queue before sending write/upload/OTLP HTTP requests to Kodo or the next Dataway. Default: true |
| DW_KODO_QUEUE_WORKERS type: int required: N |
Number of workers for the Kodo dispatch queue. Default: 256 |
| DW_KODO_QUEUE_SIZE type: int required: N |
Maximum number of requests waiting in the Kodo dispatch queue. Default: 1024 |
| DW_KODO_QUEUE_MAX_BYTES type: int/string required: N |
Upper limit of total body bytes for requests queued, in-flight, and waiting to enqueue in the Kodo queue. Supports formats like 1073741824, 1GB, 1024MB. Default: 1GB |
| DW_KODO_QUEUE_ENQUEUE_TIMEOUT type: string required: N |
Maximum time a request waits for a slot in the Kodo queue. After timeout, cacheable requests are written to the Dataway disk cache; if cache is unavailable, returns 503. Default: 100ms |
| DW_TOKEN_NEGATIVE_CACHE_ENABLED type: boolean required: N |
Whether to enable negative caching for invalid tokens. The cache is isolated by token, write API path, and main/headless mode. Default: true |
| DW_TOKEN_NEGATIVE_CACHE_TTL type: string required: N |
Time-to-live for negative cache entries of invalid tokens. Default: 5m |
| DW_TOKEN_NEGATIVE_CACHE_MAX_KEYS type: int required: N |
Maximum number of scope keys stored in the negative cache for invalid tokens. Default: 1000 |
| DW_BIND type: string required: N |
Dataway HTTP API IPv4 binding address. Default: 0.0.0.0:9528 |
| DW_BIND_IPV6 type: string required: N |
Dataway HTTP API IPv6 binding address. Default: not listening. Set to [::]:9528 to explicitly enable IPv6 listening. |
| DW_API_LIMIT type: int required: N |
Dataway API rate limit. For example, set to 1000 to allow a maximum of 1000 requests per second for each specific API. Default: 100K |
| DW_HEARTBEAT type: string required: N |
Heartbeat interval between Dataway and the center. Default: 60s |
| DW_MAX_HTTP_BODY_BYTES type: int required: N |
Maximum allowed HTTP body size for Dataway API (in bytes). Default: 64MB |
| DW_TLS_INSECURE_SKIP_VERIFY type: boolean required: N |
Ignore HTTPS/TLS certificate errors |
| DW_HTTP_CLIENT_TRACE type: boolean required: N |
When Dataway acts as an HTTP client, enable related metrics collection. These metrics are eventually output in its Prometheus metrics. |
| DW_ENABLE_TLS type: boolean required: N |
Enable HTTPS Version-1.4.1 |
| DW_TLS_CRT type: file-path required: N |
Specify the HTTPS/TLS crt file path Version-1.4.0 |
| DW_TLS_KEY type: file-path required: N |
Specify the HTTPS/TLS key file path Version-1.4.0 |
| DW_SNI type: string required: N |
Specify the current Dataway SNI information Version-1.6.0 |
| DW_DISABLE_404PAGE type: boolean required: N |
Disable the 404 page Version-1.6.1 |
| DW_HTTP_IP_BLACKLIST_TTL type: string required: N |
Set the IP blacklist time-to-live. Default: 1m Version-1.11.0 |
| DW_HTTP_IP_BLACKLIST_CLEAN_INTERVAL type: string required: N |
Set the IP blacklist cleanup interval. Default: 1h Version-1.11.0 |
HTTP TLS Settings¶
To generate a TLS certificate valid for one year, use the following OpenSSL command:
# Generate a TLS certificate valid for one year
$ openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out tls.crt -keyout tls.key
...
After running the command, you will be prompted to enter necessary information, including your country, region, city, organization name, department name, and email address. This information will be included in your certificate.
After completing the input, two files will be generated: tls.crt (certificate file) and tls.key (private key file). Keep your private key file secure.
To make the application use these TLS certificates, set the absolute paths of these two files to the application's environment variables. Example:
DW_ENABLE_TLSmust be enabled first for the other two ENVs (DW_TLS_CRT/DW_TLS_KEY) to take effect. Version-1.4.1
env:
- name: DW_ENABLE_TLS
value: "true"
- name: DW_TLS_CRT
value: "/path/to/your/tls.crt"
- name: DW_TLS_KEY
value: "/path/to/your/tls.key"
Replace /path/to/your/tls.crt and /path/to/your/tls.key with the actual paths to your tls.crt and tls.key files.
After configuration, test TLS with the following command:
If successful, an ASCII Art message "It's working!" will be displayed. If the certificate does not exist, Dataway logs will show an error similar to:
In this case, Dataway will not start, and the curl command above will also fail:
$ curl -vvv -k http://localhost:9528
curl: (7) Failed to connect to localhost port 9528 after 6 ms: Couldn't connect to server
Log Settings¶
| Env | Description |
|---|---|
| DW_LOG type: string required: N |
Log path, default is log. To output logs to stdout for easier log collection, set to stdout. |
| DW_LOG_LEVEL type: string required: N |
Default is info, optional debug. |
| DW_GIN_LOG type: string required: N |
Default is gin.log. Can also be set to stdout for collection. |
| DW_LOG_PKG_ID type: bool required: N |
Version-1.12.0 Whether to record package ID in logs. Default is true. |
Token/UUID Settings¶
| Env | Description |
|---|---|
| DW_UUID type: string required: Y |
Dataway UUID, generated by the system workspace when creating a new Dataway |
| DW_TOKEN type: string required: Y |
Typically the data upload token of the system workspace |
| DW_SECRET_TOKEN type: string required: N |
Can be set when Sinker functionality is enabled |
| DW_ENABLE_INTERNAL_TOKEN type: boolean required: N |
Allow __internal__ as a client token; in this case, the system workspace token is used by default |
| DW_ENABLE_EMPTY_TOKEN type: boolean required: N |
Allow data upload without a token; in this case, the system workspace token is used by default |
Sinker Settings¶
| Env | Description |
|---|---|
| DW_SECRET_TOKEN type: string required: N |
Can be set when Sinker functionality is enabled |
| DW_CASCADED type: string required: N |
Whether Dataway is cascaded |
| DW_SINKER_ETCD_URLS type: string required: N |
etcd address list, separated by ,, e.g., http://1.2.3.4:2379,http://1.2.3.4:2380 |
| DW_SINKER_ETCD_DIAL_TIMEOUT type: string required: N |
etcd connection timeout, default 30s |
| DW_SINKER_ETCD_KEY_SPACE type: string required: N |
etcd key name where Sinker configuration resides (default /dw_sinker) |
| DW_SINKER_ETCD_USERNAME type: string required: N |
etcd username |
| DW_SINKER_ETCD_PASSWORD type: string required: N |
etcd password |
| DW_SINKER_FILE_PATH type: file-path required: N |
Specify sinker rule configuration via local file |
| DW_SINKER_CACHE_BUCKETS type: int required: N |
Version-1.12.0 Specify the number of Sinker cache buckets, default 64 |
| DW_SINKER_CACHE_RESERVED_CAPACITY type: int required: N |
Version-1.12.0 Specify the maximum number of Sinker cache entries, default 100w (1<<20) |
| DW_SINKER_CACHE_TTL type: int required: N |
Version-1.12.0 Specify the time-to-live for Sinker cache entries, default 10m (10 minutes) |
| DW_SINKER_CACHE_PREALLOC type: bool required: N |
Version-1.12.0 Pre-allocate cache memory, default false |
Warning
If both the local file and etcd methods are specified, the local file Sinker rules take precedence. If neither is specified, the Sinker functionality is effectively disabled.
Prometheus Metrics Exposure¶
| Env | Description |
|---|---|
| DW_PROM_URL type: string required: N |
Prometheus metrics URL path (default /metrics) |
| DW_PROM_LISTEN type: string required: N |
Prometheus metrics exposure address (default localhost:9090) |
| DW_PROM_DISABLED type: boolean required: N |
Disable Prometheus metrics exposure |
| DW_PPROF_BIND type: string required: N |
pprof listen address; disabled by default, only accepts loopback addresses, e.g., localhost:6060 |
Disk Cache Settings¶
| Env | Description |
|---|---|
| DW_DISKCACHE_DIR type: file-path required: N |
Set the cache directory. This directory is typically mounted as external storage. |
| DW_DISKCACHE_DISABLE type: boolean required: N |
Disable disk cache. If not disabling cache, remove this environment variable. |
| DW_DISKCACHE_CLEAN_INTERVAL type: string required: N |
Cache cleanup interval, default 1s |
| DW_DISKCACHE_EXPIRE_DURATION type: string required: N |
Cache expiration time, default 168h (7d) |
| DW_DISKCACHE_CAPACITY_MB type: int required: N |
Version-1.6.0 Set the available disk space size, in MB, default 20GB |
| DW_DISKCACHE_BATCH_SIZE_MB type: int required: N |
Version-1.6.0 Set the maximum size of a single disk cache file, in MB, default 64MB |
| DW_DISKCACHE_MAX_DATA_SIZE_MB type: int required: N |
Version-1.6.0 Set the maximum size of a single cached content (e.g., a single HTTP body), in MB, default 64MB. Data packets exceeding this size are dropped. |
Tips
Setting DW_DISKCACHE_DISABLE disables disk cache.
Performance-Related Settings¶
| Env | Description |
|---|---|
| DW_COPY_BUFFER_DROP_SIZE type: int required: N |
HTTP body buffers exceeding this size (in bytes) are immediately cleared to avoid excessive memory consumption. Default: 256KB |
Dataway API List¶
Except for diagnostic and local processing interfaces, forwarding interfaces forward requests to Kodo or the next-hop Dataway according to their respective token validation rules. See below for Langfuse-compatible interface authentication behavior.
GET /v1/ping¶
- API Description: Retrieve the current Dataway version number, release date, and the client's outgoing IP address.
If the Dataway has disabled the 404 page (
disable_404page), this endpoint will not be available.
GET /v1/ntp¶
- API Description: Retrieve the current Dataway Unix timestamp (in seconds).
POST /v1/write/:category¶
- API Description: Receive various telemetry data uploaded by Datakit.
POST /v1/aggregate¶
- API Description: Receive metric aggregation data. Registered only when the aggregation function is successfully initialized.
- For detailed working modes, configuration, and request requirements, see Dataway Metric Aggregation.
POST /v1/tail_sampling, POST /v1/tail_sampling_v2, POST /v2/tail_sampling and POST /v1/tail_sampling_config¶
- API Description:
/v1/tail_samplingreceives raw tail sampling data packets and is compatible with zstd data packets sent by Datakit 2.10 without negotiation headers; the legacy path/v1/tail_sampling_v2only receives raw data packets;/v2/tail_samplingreceives zstd data packets with compression negotiation headers;/v1/tail_sampling_configreceives tail sampling configuration. Registered only when the tail sampling function is successfully initialized. - For detailed working modes, configuration, and request requirements, see Dataway Tail Sampling.
POST /otel/v1/{traces,metrics,logs}¶
- API Description: Receive OpenTelemetry OTLP HTTP/protobuf data and forward it unchanged to the corresponding Kodo path.
- Supported paths:
POST /otel/v1/tracesPOST /otel/v1/metricsPOST /otel/v1/logs
-
Request requirements:
Content-Typemust beapplication/x-protobuf, with media type parameters allowed (e.g.,application/x-protobuf; charset=utf-8)- The workspace token can be passed via the
tokenquery parameter,X-Tokenheader, orAuthorization: Bearer <token>. Bearer tokens are converted toX-Tokenbefore forwarding. - When using OpenTelemetry SDK/Agent environment variables, it is recommended to explicitly configure OTLP HTTP/protobuf and set the base endpoint to the Dataway's
/otelprefix. OpenTelemetry automatically appends/v1/traces,/v1/metrics, and/v1/logsby signal:
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://dataway.example.com/otel/v1/logs export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://dataway.example.com/otel/v1/traces export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://dataway.example.com/otel/v1/metrics export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20{token}"- The startup parameters and environment variables have the same meaning. For example, with the Java Agent, you can configure
-Dotel.exporter.otlp.protocol=http/protobuf,-Dotel.exporter.otlp.endpoint=https://dataway.example.com/otel, and-Dotel.exporter.otlp.headers=Authorization=Bearer%20{token}. If the implementation has inconsistent encoding compatibility for spaces in theAuthorizationheader, you can also useOTEL_EXPORTER_OTLP_HEADERS="X-Token={token}"or the corresponding startup parameter. - Dataway does not parse or rewrite the OTLP body.
/otel/v1/metricsis not converted to/v1/write/metricline protocol. Kodo parses it according to the default DataKit OTLP metrics rules, with the measurement beingotel_service. Metric field names retain the original OTLP metric name (e.g.,runtime.jvm.memoryis not rewritten toruntime_jvm_memory). - The original OTLP response status, response body, and necessary response headers from Kodo are passed through. If forwarding fails and the disk cache policy is satisfied, the request enters the Dataway disk cache replay chain.
GET /v1/datakit/pull¶
- API Description: Handle Datakit requests to pull center configuration (blacklist/Pipeline).
POST /v1/datakit/usage_trace¶
- API Description: Receive Datakit usage trace data.
POST /v1/write/rum/replay¶
- API Description: Receive Session Replay data uploaded by Datakit.
POST /v1/write/rum/replay_assets¶
- API Description: Receive upload requests for Session Replay-related assets.
POST /v1/check/rum/replay_assets¶
- API Description: Check if Session Replay-related assets already exist.
POST /v1/upload/profiling¶
- API Description: Receive Profiling data uploaded by Datakit.
POST /v1/input/firehose¶
- API Description: Receive Firehose input data.
POST /v1/election¶
- API Description: Handle Datakit election requests.
POST /v1/election/heartbeat¶
- API Description: Handle Datakit election heartbeat requests.
POST /v1/query/raw¶
Handle DQL query requests. Example:
POST /v1/query/raw?token=<workspace-token> HTTP/1.1
Content-Type: application/json
{
"token": "workspace-token",
"queries": [
{
"query": "M::cpu LIMIT 1"
}
],
"echo_explain": <true/false>
}
Response example:
{
"content": [
{
"series": [
{
"name": "cpu",
"columns": [
"time",
"usage_iowait",
"usage_total",
"usage_user",
"usage_guest",
"usage_system",
"usage_steal",
"usage_guest_nice",
"usage_irq",
"load5s",
"usage_idle",
"usage_nice",
"usage_softirq",
"global_tag1",
"global_tag2",
"host",
"cpu"
],
"values": [
[
1709782208662,
0,
7.421875,
3.359375,
0,
4.0625,
0,
0,
0,
1,
92.578125,
0,
0,
null,
null,
"WIN-JCHUL92N9IP",
"cpu-total"
]
]
}
],
"points": null,
"cost": "24.558375ms",
"is_running": false,
"async_id": "",
"query_parse": {
"namespace": "metric",
"sources": {
"cpu": "exact"
},
"fields": {},
"funcs": {}
},
"index_name": "",
"index_store_type": "",
"query_type": "guancedb",
"complete": false,
"index_names": "",
"scan_completed": false,
"scan_index": "",
"next_cursor_time": -1,
"sample": 1,
"interval": 0,
"window": 0
}
]
}
Response description:
- The actual data is in the inner
seriesfield. nameindicates the measurement name (here, the query is for CPU metrics; for log data, this field is absent).columnslists the names of the result columns.valuescontains the corresponding column results fromcolumns.
Info
- The token in the URL query parameter can differ from the token in the JSON body. The former is used to validate the query request, while the latter is used to determine the target workspace for the data.
- The
queriesfield can contain multiple queries, each with additional fields. For the complete list of fields, see here.
POST /v1/workspace¶
- API Description: Handle workspace query requests initiated by Datakit.
GET /v1/env_variable¶
- API Description: Retrieve workspace environment variables.
POST /v1/dataway/heartbeat¶
- API Description: Receive Dataway heartbeat reporting requests.
POST /v1/object/labels¶
- API Description: Handle requests to modify object labels.
DELETE /v1/object/labels¶
- API Description: Handle requests to delete object labels.
GET /v1/check/token/:token¶
- API Description: Check if a token is valid.
Langfuse-Compatible Interfaces¶
The following interfaces are for Langfuse client compatibility. Requests are forwarded directly upstream; Dataway does not perform token validation:
POST /api/public/otel/v1/traces: Receive Langfuse OTLP Trace data.GET /api/public/projects: Retrieve Langfuse project information.POST /api/public/ingestion: Receive Langfuse ingestion data.
Dataway Metrics Collection¶
HTTP Client Metrics Collection
To collect metrics for Dataway's HTTP requests to Kodo (or the next-hop Dataway), you must manually enable the http_client_trace configuration, or set the environment variable DW_HTTP_CLIENT_TRACE=true.
Dataway exposes Prometheus metrics. You can collect them using the Datakit built-in prom collector. Example collector configuration:
If Datakit is deployed in the cluster (requires Datakit 1.14.2 or later), you can enable Prometheus metrics exposure in Dataway (the default Dataway POD yaml already includes this):
annotations: # The following annotations are added by default
datakit/prom.instances: |
[[inputs.prom]]
url = "http://$IP:9090/metrics" # The port (default 9090) depends on the actual setup
source = "dataway"
measurement_name = "dw" # Fixed to this measurement
interval = "10s"
disable_instance_tag = true
[inputs.prom.tags]
service = "dataway"
instance = "$PODNAME"
...
env:
- name: DW_PROM_LISTEN
value: "0.0.0.0:9090" # The port here must match the port in the url above
If collection is successful, you can search for dataway in the Guance "Scenarios" / "Built-in Views" to see the corresponding monitoring dashboard.
Cache and Kodo Queue Troubleshooting¶
When Kodo returns a 5xx, Dataway fails to request Kodo, or the Kodo dispatch queue is full, Dataway attempts to write cacheable requests to disk cache. Kodo 4xx responses are not cached.
For troubleshooting, first check the following metrics:
dataway_http_api_cached_bytes{reason=...}: Request has been written to cache. Commonreasonvalues include Kodo 5xx status text,httpCliDoFailed, andkodoQueueFull.dataway_http_api_dropped_cache{reason=...}: Request attempted to cache but was not written. Commonreasonvalues includefeat-disabled,expected-api-drop,body-md5-not-matched,body-length-not-matched,expired,put-failed, andsendopt-nil.dataway_kodo_queue_full_total{action=...}: Result after the Kodo queue is full.action="cache"indicates a transfer to cache;action="reject"indicates cache is unavailable or write failed, returning503.
Dataway Metrics List¶
The following are the metrics exposed by Dataway. You can retrieve them by requesting http://localhost:9090/metrics. Use the following command to watch a specific metric in real time (3s interval):
If some metrics are not found, it may be because the relevant business module has not yet started. Some new metrics only exist in the latest version. The version information for each metric is not individually marked here; refer to the metric list returned by the
/metricsendpoint.
| TYPE | NAME | LABELS | HELP |
|---|---|---|---|
| SUMMARY | dataway_kodo_queue_wait_seconds |
api,method |
Kodo queue wait duration before worker dispatch |
| SUMMARY | dataway_http_api_elapsed_seconds |
api,method,sinked,status |
API request latency |
| SUMMARY | dataway_http_api_body_buffer_utilization |
api |
API body buffer utillization(Len/Cap) |
| SUMMARY | dataway_http_api_body_copy |
api |
API body copy |
| SUMMARY | dataway_http_api_body_copy_seconds |
api |
API body copy latency |
| SUMMARY | dataway_http_api_body_copy_enlarge |
api |
API body copy enlarged pooled buffer |
| SUMMARY | dataway_http_api_resp_size_bytes |
api,method,status |
API response size |
| SUMMARY | dataway_http_api_req_size_bytes |
api,method,status |
API request size |
| COUNTER | dataway_http_api_body_too_large_dropped_total |
api,method |
API request too large dropped |
| COUNTER | dataway_http_api_with_inner_token |
api,method |
API request with inner token |
| COUNTER | dataway_http_api_dropped_total |
api,method |
API request dropped when sinker rule match failed |
| COUNTER | dataway_ip_blacklist_blocked_total |
api,method |
IP blacklist blocked requests total |
| COUNTER | dataway_ip_blacklist_missed_total |
api,method |
IP blacklist missed total |
| COUNTER | dataway_ip_blacklist_added_total |
api,method,reason |
IP blacklist added total |
| COUNTER | dataway_syncpool_stats |
name,type |
sync.Pool usage stats |
| COUNTER | dataway_http_api_copy_body_failed_total |
api |
API copy body failed count |
| COUNTER | dataway_http_api_signed_total |
api,method |
API signature count |
| SUMMARY | dataway_http_api_cached_bytes |
api,cache_type,method,reason |
API cached body bytes |
| SUMMARY | dataway_http_api_reusable_body_read_bytes |
api,method |
API re-read body on forking request |
| SUMMARY | dataway_http_api_recv_points |
api |
API /v1/write/:category recevied points |
| SUMMARY | dataway_http_api_send_points |
api |
API /v1/write/:category send points |
| SUMMARY | dataway_http_api_cache_points |
api,cache_type |
Disk cached /v1/write/:category points |
| SUMMARY | dataway_http_api_cache_cleaned_points |
api,cache_type,status |
Disk cache cleaned /v1/write/:category points |
| COUNTER | dataway_http_api_forked_total |
api,method,token |
API request forked total |
| GAUGE | dataway_http_cli_info |
max_conn_per_host,max_idle_conn,max_idle_conn_per_host,timeout |
Dataway as client settings |
| GAUGE | dataway_http_info |
cascaded,docker,http_client_trace,listen,max_body,release_date,remote,version |
Dataway API basic info |
| GAUGE | dataway_kodo_queue_depth |
N/A |
Current Kodo dispatch queue depth including in-flight tasks |
| GAUGE | dataway_kodo_queue_bytes |
N/A |
Current Kodo dispatch queue body bytes including in-flight tasks |
| COUNTER | dataway_kodo_queue_enqueued_total |
api,method |
Kodo queue enqueued tasks |
| COUNTER | dataway_kodo_queue_full_total |
api,method,action |
Kodo queue full events |
| COUNTER | dataway_kodo_queue_dispatch_total |
api,method,status |
Kodo queue dispatch results |
| COUNTER | dataway_token_negative_cache_added_total |
api,method,error_code |
Token negative cache added total |
| COUNTER | dataway_token_negative_cache_blocked_total |
api,method,error_code |
Token negative cache blocked requests total |
| GAUGE | dataway_last_heartbeat_time |
N/A |
Dataway last heartbeat with Kodo timestamp |
| SUMMARY | dataway_http_api_copy_buffer_drop_total |
max |
API copy buffer dropped(too large cached buffer) count |
| GAUGE | dataway_cpu_usage |
N/A |
Dataway CPU usage(%) |
| GAUGE | dataway_mem_stat |
type |
Dataway memory usage stats |
| GAUGE | dataway_open_files |
N/A |
Dataway open files |
| GAUGE | dataway_open_files_by_type |
type |
Dataway open files grouped by fd type |
| GAUGE | dataway_tcp_connections |
direction,port,state |
Dataway TCP connections grouped by direction, port and state(Linux only) |
| GAUGE | dataway_cpu_cores |
N/A |
Dataway CPU cores |
| GAUGE | dataway_uptime |
N/A |
Dataway uptime |
| COUNTER | dataway_process_ctx_switch_total |
type |
Dataway process context switch count(Linux only) |
| COUNTER | dataway_process_io_count_total |
type |
Dataway process IO count |
| COUNTER | dataway_process_io_bytes_total |
type |
Dataway process IO bytes count |
| SUMMARY | dataway_http_api_dropped_cache |
api,method,reason |
Dropped cache data dur to various reasons |
| COUNTER | dataway_http_api_body_size_bytes_total |
api,token |
Accumulated API body bytes for aggregate or tailSampling |
| COUNTER | dataway_http_aggr_point_total |
api,token |
point count of aggregate or tailSampling |
| COUNTER | dataway_http_tail_sampling_trace_total |
token |
tailSampling trace count |
| COUNTER | dataway_http_tail_sampling_span_total |
token |
tailSampling span count |
| COUNTER | dataway_http_tail_sampling_packet_send_total |
token,data_type,result |
tailSampling packet send result count |
| GAUGE | dataway_httpcli_dns_resolved_address |
api,coalesced,host,server |
HTTP DNS resolved address |
| SUMMARY | dataway_httpcli_dns_cost_seconds |
api,coalesced,host,server |
HTTP DNS cost |
| SUMMARY | dataway_httpcli_tls_handshake_seconds |
api,server |
HTTP TLS handshake cost |
| SUMMARY | dataway_httpcli_http_connect_cost_seconds |
api,server |
HTTP connect cost |
| SUMMARY | dataway_httpcli_got_first_resp_byte_cost_seconds |
api,server |
Got first response byte cost |
| SUMMARY | http_latency |
api,server |
HTTP latency |
| COUNTER | dataway_httpcli_tcp_conn_total |
api,server,remote,type |
HTTP TCP connection count |
| COUNTER | dataway_httpcli_conn_reused_from_idle_total |
api,server |
HTTP connection reused from idle count |
| SUMMARY | dataway_httpcli_conn_idle_time_seconds |
api,server |
HTTP connection idle time |
| GAUGE | dataway_sinker_rule_cache_size |
name |
Sinker rule cache size |
| GAUGE | dataway_sinker_rule_error |
error |
Rule errors |
| GAUGE | dataway_sinker_default_rule_hit |
info |
Default sinker rule hit count |
| GAUGE | dataway_sinker_rule_last_applied_time |
source,version |
Rule last applied time(Unix timestamp) |
| SUMMARY | dataway_sinker_rule_cost_seconds |
type |
Rule cost time seconds |
| SUMMARY | dataway_sinker_lru_cache_cleaned |
name |
Sinker LRU cache cleanup removed entries |
| COUNTER | dataway_sinker_lru_cache_dropped_total |
bucket,name,reason |
Sinker LRU cache evicted entries total |
| HISTOGRAM | dataway_sinker_lru_cache_expired_delay_seconds |
bucket,name |
Sinker LRU cache expired entry cleanup delay |
| HISTOGRAM | dataway_sinker_lru_cache_evicted_remaining_ttl_seconds |
bucket,name |
Sinker LRU cache capacity eviction remaining TTL |
| COUNTER | dataway_sinker_pull_total |
event,source |
Sinker pulled or pushed total |
| GAUGE | dataway_sinker_rule_count |
type,with_default |
Sinker rule count |
| GAUGE | dataway_sinker_rule_cache_get_total |
name,type |
Sinker rule cache get hit/miss count |
| COUNTER | diskcache_rotate_total |
path |
Cache rotate count, mean file rotate from data to data.0000xxx |
| COUNTER | diskcache_remove_total |
path |
Removed file count, if some file read EOF, remove it from un-read list |
| COUNTER | diskcache_wakeup_total |
path |
Wakeup count on sleeping write file |
| COUNTER | diskcache_pos_updated_total |
op,path |
.pos file updated count |
| COUNTER | diskcache_seek_back_total |
path |
Seek back when Get() got any error |
| GAUGE | diskcache_capacity |
path |
Current capacity(in bytes) |
| GAUGE | diskcache_max_data |
path |
Max data to Put(in bytes), default 0 |
| GAUGE | diskcache_batch_size |
path |
Data file size(in bytes) |
| GAUGE | diskcache_size |
path |
Current cache size that waiting to be consumed(get). The size include header bytes |
| GAUGE | diskcache_open_time |
no_fallback_on_error,no_lock,no_pos,no_sync,path |
Current cache Open time in unix timestamp(second) |
| GAUGE | diskcache_last_close_time |
path |
Current cache last Close time in unix timestamp(second) |
| GAUGE | diskcache_datafiles |
path |
Current un-read data files |
| HISTOGRAM | diskcache_lock_wait_seconds |
lock_type,path |
Time spent waiting for locks by lock type |
| COUNTER | diskcache_lock_contention_total |
lock_type,path |
Number of lock contention events |
| SUMMARY | diskcache_get_latency |
path |
Get() cost seconds |
| SUMMARY | diskcache_put_latency |
path |
Put() cost seconds |
| SUMMARY | diskcache_put_bytes |
path |
Cache Put() bytes |
| SUMMARY | diskcache_get_bytes |
path |
Cache Get() bytes |
| SUMMARY | diskcache_dropped_data |
path,reason |
Dropped data during Put() when capacity reached. |
Metrics Collection in Docker Mode¶
Host installation has two modes: host-based installation and Docker installation. This section explains the differences for Docker installation.
When installed via Docker, the metrics exposure HTTP port is mapped to host port 19090 (by default). The metrics collection address is http://localhost:19090/metrics.
If a different port is specified, Docker will add 10000 to that port. Therefore, do not specify a port number exceeding 45535.
pprof is disabled by default. Docker installation does not publish the profile port to the host. For temporary troubleshooting, you can explicitly set pprof_bind or DW_PPROF_BIND to localhost:6060 and collect via docker exec, kubectl exec, or controlled port forwarding. Configuring a non-loopback address will be rejected.
Dataway Log Collection and Processing¶
Dataway logs are divided into two types: gin logs and application logs. The following Pipeline can be used to separate them:
# Pipeline for dataway logging
# Testing sample loggin
'''
2023-12-14T11:27:06.744+0800 DEBUG apis apis/api_upload_profile.go:272 save profile file to disk [ok] /v1/upload/profiling?token=****************a4e3db8481c345a94fe5a
[GIN] 2021/10/25 - 06:48:07 | 200 | 30.890624ms | 114.215.200.73 | POST "/v1/write/logging?token=tkn_5c862a11111111111111111111111111"
'''
add_pattern("TOKEN", "tkn_\\w+")
add_pattern("GINTIME", "%{YEAR}/%{MONTHNUM}/%{MONTHDAY}%{SPACE}-%{SPACE}%{HOUR}:%{MINUTE}:%{SECOND}")
grok(_,"\\[GIN\\]%{SPACE}%{GINTIME:timestamp}%{SPACE}\\|%{SPACE}%{NUMBER:dataway_code}%{SPACE}\\|%{SPACE}%{NOTSPACE:cost_time}%{SPACE}\\|%{SPACE}%{NOTSPACE:client_ip}%{SPACE}\\|%{SPACE}%{NOTSPACE:method}%{SPACE}%{GREEDYDATA:http_url}")
# gin logging
if cost_time != nil {
if http_url != nil {
grok(http_url, "%{TOKEN:token}")
cover(token, [5, 15])
replace(message, "tkn_\\w{0,5}\\w{6}", "****************$4")
replace(http_url, "tkn_\\w{0,5}\\w{6}", "****************$4")
}
group_between(dataway_code, [200,299], "info", status)
group_between(dataway_code, [300,399], "notice", status)
group_between(dataway_code, [400,499], "warning", status)
group_between(dataway_code, [500,599], "error", status)
if sample(0.1) { # drop 90% debug log
drop()
exit()
} else {
set_tag(sample_rate, "0.1")
}
parse_duration(cost_time)
duration_precision(cost_time, "ns", "ms")
set_measurement('gin', true)
set_tag(service,"dataway")
exit()
}
# app logging
if cost_time == nil {
grok(_,"%{TIMESTAMP_ISO8601:timestamp}%{SPACE}%{NOTSPACE:status}%{SPACE}%{NOTSPACE:module}%{SPACE}%{NOTSPACE:code}%{SPACE}%{GREEDYDATA:msg}")
if level == nil {
grok(message,"Error%{SPACE}%{DATA:errormsg}")
if errormsg != nil {
add_key(status,"error")
drop_key(errormsg)
}
}
lowercase(level)
# if debug level enabled, drop most of them
if status == 'debug' {
if sample(0.1) { # drop 90% debug log
drop()
exit()
} else {
set_tag(sample_rate, "0.1")
}
}
group_in(status, ["error", "panic", "dpanic", "fatal","err","fat"], "error", status) # mark them as 'error'
if msg != nil {
grok(msg, "%{TOKEN:token}")
cover(token, [5, 15])
replace(message, "tkn_\\w{0,5}\\w{6}", "****************$4")
replace(msg, "tkn_\\w{0,5}\\w{6}", "****************$4")
}
set_measurement("dataway-log", true)
set_tag(service,"dataway")
}
Dataway Bug Report¶
Dataway exposes metrics and can temporarily enable profiling collection endpoints for troubleshooting. pprof is disabled by default; set pprof_bind explicitly to a loopback address before collection, and disable it again after collection.
The following information collection uses the actual configured port and address.
br_dir="dw-br-$(date +%s)"
mkdir -p $br_dir
echo "save bug report to ${br_dir}"
# Modify these settings according to the actual situation
dw_ip="localhost" # IP address where Dataway metrics/profile are exposed
metric_port=9090 # Port for metrics exposure
profile_port=6060 # Must first explicitly enable localhost:6060 pprof listener
dw_yaml_conf="/usr/local/cloudcare/dataflux/dataway/dataway.yaml"
dw_dot_yaml_conf="/usr/local/cloudcare/dataflux/dataway/.dataway.yaml" # Exists in container installation
# Collect runtime metrics
curl -v "http://${dw_ip}:${metric_port}/metrics" -o $br_dir/metrics
# Collect profiling information
curl -v "http://${dw_ip}:${profile_port}/debug/pprof/allocs" -o $br_dir/allocs
curl -v "http://${dw_ip}:${profile_port}/debug/pprof/heap" -o $br_dir/heap
curl -v "http://${dw_ip}:${profile_port}/debug/pprof/profile" -o $br_dir/profile # This command runs for about 30s
cp $dw_yaml_conf $br_dir/dataway.yaml.copy
cp $dw_dot_yaml_conf $br_dir/.dataway.yaml.copy
tar czvf ${br_dir}.tar.gz ${br_dir}
rm -rf ${br_dir}
Run the script:
After execution, a file like dw-br-1721188604.tar.gz will be generated. Extract that file.
FAQ¶
Request Body Too Large¶
Dataway has a default limit on request body size (default 64MB). When the request body is too large, the client receives an HTTP 413 error (Request Entity Too Large). If the request body is within a reasonable range, you can increase this value (in bytes):
- Set the environment variable
DW_MAX_HTTP_BODY_BYTES - Set
max_http_body_bytesin dataway.yaml
If unusually large request packets occur during runtime, this is reflected in both metrics and logs:
- The metric
dataway_http_too_large_dropped_totalexposes the count of dropped large requests. - Search the Dataway log
cat log | grep 'drop too large request'; the log will output the HTTP request header details for further understanding of the client situation.
Warning
The disk cache module also has a maximum data block write limit (default 64MB). If you increase the maximum request body configuration, you should also adjust this configuration (ENV_DISKCACHE_MAX_DATA_SIZE) to ensure large requests can be correctly written to the disk cache.
-
This limit prevents the Dataway container/Pod from being limited to approximately 20000 connections due to system constraints. Increasing the limit will affect Dataway upload efficiency. For high-traffic Dataway, consider increasing the CPU count per Dataway instance or horizontally scaling Dataway instances. ↩