For the complete documentation index, see llms.txt. This page is also available as Markdown.

Websocket

This page describes how to use Lenses Websocket endpoints

Query data via SQL

A WebSocket allows the client to request data using SQL as input.

Use the following URL to open a WebSocket connection. Depending on deployment, use ws (insecure) or wss (secure) connection:

WS | WSS ${LENSES_URL}/environment/${YOUR_ENVIRONMENT_NAME}/proxy/api/ws/v2/sql/execute

The query runs per environment. Add the environment name.

Establishing a connection

To authenticate, create a service account and set the token in the header for the Authorization Bearer.

Once the connection is established, the server expects the client to send a JSON message with the following structure:

{
  "sql": String,
  "live": Optional[Boolean],
  "stats": Optional[Int]
}

For example, in Python:

import os, websockets, json, asyncio

import ssl
#Optional if using self-signed cert with the websocket:
# ssl_context = ssl._create_unverified_context()

async def execute_SQL(environmentName: str, sql: str) -> dict:

    #FOR Secure Websocket use:
    #  url = str("wss://") + os.getenv("HQ_HOST") + "/api/v1/environments/" + environmentName + "/proxy/api/ws/v2/sql/execute"
    url = str("ws://") + os.getenv("HQ_HOST") + "/api/v1/environments/" + environmentName + "/proxy/api/ws/v2/sql/execute"
    headers = {"Authorization": "Bearer " + os.getenv('HQ_TOKEN')}

    data = []
    try:
        request = {
            "sql": sql,
            "live": False,
            "stats": 2
        }

        #FOR WSS use:
        #async with websockets.connect(url, ssl=ssl_context, additional_headers=headers) as websocket:
        async with websockets.connect(url, additional_headers=headers) as websocket:
            await websocket.send(json.dumps(request))
            async for message in websocket:
                response = json.loads(message)
                if response.get('type') == 'RECORD':
                    data.append(response)

    except websockets.exceptions.WebSocketException as e:

        print(f"An error occurred: {e}")
        return None
    print(data)

asyncio.run(execute_SQL("demo", "SELECT * FROM input LIMIT 100;"))

Query Request

Field
Description
Type

sql

The SQL query used to fetch data

string

live

If set, enables partial results for aggregation queries.

optional[boolean]

stats

Millis interval to receive query stats. If not provided the stats information is not sent

optional[int]

Protocol

Wait for incoming messages and stop when you receive EOF. The server sends JSON-encoded messages. The payload structure is:

Since the server sends multiple message types, the type attribute determines the data payload structure. The following table lists the possible type values:

Value
Description

HEARTBEAT

To keep the connection alive, the server injects an empty message.

RECORD

The message represents a data record.

ERROR

The message contains information about an error that occurred.

STATS

The message contains information about the current execution. The server sends it only when the request includes the stats field.

METADATA

The message contains metadata fields that each record message includes. For example: offset, partition, timestamp, __keysize, __valueSize, and valueSchemaId.

SCHEMA

Reserved.

PAGE_END

Reserved.

END

The message signals the end of the execution. The server closes the socket after it sends this message.

BADRECORD

The message contains information about the Kafka message which cannot be read. For example, if the topic expects Avro and the payload is not a valid Avro.

SENTINEL

The message contains information about the execution termination reason when query thresholds are reached.

Heartbeat

The data attribute is null. Ignore these messages.

Error

In this case, the payload structure is:

Stats

When requested the payload format is:

A possible payload can be:

Metadata

The payload format is:

End

The payload format is:

Bad record

The payload format is:

Sentinel

The payload format is:

Record

When type is RECORD, the payload contains data returned to the client. It depends on the SQL input. The payload format is:

Value
Description

data.key

Returns the underlying Kafka message key value. Only applied when * projection is used. When a key projection is used (i.e. _key.MMSI), the value is returned as data.value.MMSI.

data.data

Contains the output generated by the SQL projections. If * is used for the SQL projection, it returns the Kafka message value structure.

data.metadata

Returned when no aggregations are involved. It contains the Kafka message partition, offset, byte size information

data.rownum

Reserved optional long value.

Examples

For a topic that contains nested data for both key and value:

The payload format is:

If the Kafka message key is null, the response is:

Projecting the key does not return the key attribute:

It produces the following output:

Aggregating data does not return the key and metadata attributes:

Last updated

Was this helpful?