Skip to content

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:

  1. In the Dataway container environment variables, uncomment DW_BIND_IPV6 and set it to [::]:9528 to make Dataway listen on both IPv4 and IPv6.
  2. Change the Service's ipFamilyPolicy from SingleStack to PreferDualStack and uncomment the IPv4 and IPv6 entries under ipFamilies.

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:

containers:
  volumeMounts:
    - name: dataway-config
      mountPath: /usr/local/cloudcare/dataflux/dataway/dataway.yaml
      subPath: config.yaml
volumes:
- configMap:
    defaultMode: 256
    name: dataway-config
    optional: false
  name: dataway-config

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.

DW_UPGRADE=1 bash -c "$(curl https://static.guance.com/dataway/install.sh)"

Simply replace the image version:

- image: pubrepo.guance.com/dataflux/dataway:1.19.0

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_TLS must 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:

$ curl -k http://localhost:9528

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:

server listen(TLS) failed: open /path/to/your/tls.{crt,key}: no such file or directory

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

Version-1.6.0

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

Version-1.11.0

  • 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

Version-1.6.0

  • 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_sampling receives 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_v2 only receives raw data packets; /v2/tail_sampling receives zstd data packets with compression negotiation headers; /v1/tail_sampling_config receives 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}

Version-1.17.0

  • API Description: Receive OpenTelemetry OTLP HTTP/protobuf data and forward it unchanged to the corresponding Kodo path.
  • Supported paths:
    • POST /otel/v1/traces
    • POST /otel/v1/metrics
    • POST /otel/v1/logs
  • Request requirements:

    • Content-Type must be application/x-protobuf, with media type parameters allowed (e.g., application/x-protobuf; charset=utf-8)
    • The workspace token can be passed via the token query parameter, X-Token header, or Authorization: Bearer <token>. Bearer tokens are converted to X-Token before 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 /otel prefix. OpenTelemetry automatically appends /v1/traces, /v1/metrics, and /v1/logs by 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 the Authorization header, you can also use OTEL_EXPORTER_OTLP_HEADERS="X-Token={token}" or the corresponding startup parameter.
    • Dataway does not parse or rewrite the OTLP body. /otel/v1/metrics is not converted to /v1/write/metric line protocol. Kodo parses it according to the default DataKit OTLP metrics rules, with the measurement being otel_service. Metric field names retain the original OTLP metric name (e.g., runtime.jvm.memory is not rewritten to runtime_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 series field.
  • name indicates the measurement name (here, the query is for CPU metrics; for log data, this field is absent).
  • columns lists the names of the result columns.
  • values contains the corresponding column results from columns.

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 queries field 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:

[[inputs.prom]]
  ## Exporter URLs.
  urls = [ "http://localhost:9090/metrics", ]
  source = "dataway"
  election = true
  measurement_name = "dw" # dataway measurement is fixed to dw; do not change
[inputs.prom.tags]
  service = "dataway"

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. Common reason values include Kodo 5xx status text, httpCliDoFailed, and kodoQueueFull.
  • dataway_http_api_dropped_cache{reason=...}: Request attempted to cache but was not written. Common reason values include feat-disabled, expected-api-drop, body-md5-not-matched, body-length-not-matched, expired, put-failed, and sendopt-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, returning 503.

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 /metrics endpoint.

watch -n 3 'curl -s http://localhost:9090/metrics | grep -a <METRIC-NAME>'
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.

dw-bug-report.sh
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:

$ sh dw-bug-report.sh
...

After execution, a file like dw-br-1721188604.tar.gz will be generated. Extract that file.

FAQ

Request Body Too Large

Version-1.3.7

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_bytes in 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_total exposes 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.


  1. 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. ↩

Feedback

Is this page helpful?