- name
- databricks-isv-telemetry-attribution
- description
- PWAF User-Agent telemetry: format, per-driver configuration (Python SDK, Java SDK/JDBC, Go SDK/SQL, Node.js, REST, Databricks Connect). Use when setting up User-Agent attribution in any connector.
<!-- skill-version: 1.0.0 -->
# Telemetry & Attribution (PWAF)
User-Agent configuration for PWAF-compliant partner integrations across all Databricks drivers and SDKs. Reference: [PWAF Telemetry & Attribution](https://databrickslabs.github.io/partner-architecture/isv-partners/telemetry-attribution/).
## Why Telemetry is Required
PWAF requires User-Agent tagging in all partner integrations for:
| Purpose | Description |
|---------|-------------|
| **Usage Attribution** | Track partner product usage for reporting |
| **Joint Customer Visibility** | Identify how many joint customers use the integration |
| **GTM Initiatives** | Measure integration adoption and effectiveness |
## User-Agent Format
**Required format**:
```
<isv-name>_<product-name>/<product-version>
```
**Rules**:
- Use underscore (`_`) as separator between ISV name and product name
- Use forward slash (`/`) before version
- Keep ISV name consistent across all products
- Version is optional but recommended
**Examples**:
```
AcmePartner_DataConnector/2.1.0
BigCorp_ETLTool/3.5
MyCompany_AnalyticsPlatform/1.0.0-beta
```
---
## SDK-level User-Agent Registration (withPartner / withProduct)
Per [PWAF SDKs telemetry](https://databrickslabs.github.io/partner-architecture/isv-partners/telemetry-attribution/sdks), Databricks **SDKs** use dedicated static/global registration functions. These register product and partner identifiers that are applied to **all** subsequent SDK HTTP requests. Call once before creating any client.
### Java SDK
```java
import com.databricks.sdk.core.UserAgent;
UserAgent.withProduct("<product-name>", "<product-version>");
UserAgent.withPartner("<isv-name>");
// Then create WorkspaceClient as normal
WorkspaceClient client = new WorkspaceClient(config);
```
### Python SDK
```python
from databricks.sdk import WorkspaceClient, useragent
useragent.with_partner("<isv-name>")
useragent.with_product("<product-name>", "<product-version>")
# Then create WorkspaceClient as normal
client = WorkspaceClient(host="https://<host>", token="<token>")
```
### Go SDK
```go
import (
"github.com/databricks/databricks-sdk-go"
"github.com/databricks/databricks-sdk-go/useragent"
)
useragent.WithPartner("<isv-name>")
useragent.WithProduct("<product-name>", "<product-version>")
// Then create WorkspaceClient as normal
client, err := databricks.NewWorkspaceClient(&databricks.Config{...})
```
### Summary table
| SDK | Partner function | Product function | Scope |
|-----|-----------------|------------------|-------|
| **Java** | `UserAgent.withPartner(isv)` | `UserAgent.withProduct(name, ver)` | Static/global |
| **Python** | `useragent.with_partner(isv)` | `useragent.with_product(name, ver)` | Module/global |
| **Go** | `useragent.WithPartner(isv)` | `useragent.WithProduct(name, ver)` | Package/global |
**Note:** These SDK functions are distinct from the driver-level `UserAgentEntry` property used by JDBC, ODBC, Node.js SQL driver, and Databricks SQL Driver for Go. Both approaches use the same `<isv>_<product>/<version>` format; the SDK functions decompose it into separate partner and product registrations.
---
## JDBC Driver (OSS)
Per [PWAF SQL Drivers telemetry](https://databrickslabs.github.io/partner-architecture/isv-partners/telemetry-attribution/sql-drivers), set `UserAgentEntry` on every JDBC connection.
### Using JDBC URL
```java
String jdbcUrl =
"jdbc:databricks://<host>:443;" +
"httpPath=<http-path>;" +
"AuthMech=11;" +
"Auth_Flow=1;" +
"OAuth2ClientId=<client-id>;" +
"OAuth2Secret=<client-secret>;" +
"SSL=1;" +
"UserAgentEntry=YourCompany_YourProduct/1.0.0";
Connection conn = DriverManager.getConnection(jdbcUrl);
```
### Using Properties
```java
Properties props = new Properties();
props.put("httpPath", "<http-path>");
props.put("AuthMech", "11");
props.put("Auth_Flow", "1");
props.put("OAuth2ClientId", "<client-id>");
props.put("OAuth2Secret", "<client-secret>");
props.put("SSL", "1");
props.put("UserAgentEntry", "YourCompany_YourProduct/1.0.0");
Connection conn = DriverManager.getConnection("jdbc:databricks://<host>:443", props);
```
### Using DataSource
```java
import com.databricks.client.jdbc.DataSource;
DataSource ds = new DataSource();
Properties props = new Properties();
props.setProperty("UserAgentEntry", "YourCompany_YourProduct/1.0.0");
props.setProperty("AuthMech", "11");
props.setProperty("Auth_Flow", "1");
props.setProperty("OAuth2ClientId", "<client-id>");
props.setProperty("OAuth2Secret", "<client-secret>");
props.setProperty("SSL", "1");
ds.setServerHostname("<host>");
ds.setPort(443);
ds.setHttpPath("<http-path>");
ds.setProperties(props);
Connection conn = ds.getConnection();
```
---
## ODBC Driver
### DSN Configuration (Linux/Mac)
In `~/.odbc.ini` or `/etc/odbc.ini`:
```ini
[DatabricksConnection]
Driver=/opt/simba/spark/lib/64/libsparkodbc_sb64.so
Host=<server-hostname>
Port=443
HTTPPath=<http-path>
SSL=1
ThriftTransport=2
AuthMech=11
Auth_Flow=1
OAuth2ClientId=<client-id>
OAuth2Secret=<client-secret>
UserAgentEntry=YourCompany_YourProduct/1.0.0
```
### DSN-less Connection String
```
Driver=/opt/simba/spark/lib/64/libsparkodbc_sb64.so;
Host=<server-hostname>;
Port=443;
HTTPPath=<http-path>;
SSL=1;
ThriftTransport=2;
AuthMech=11;
Auth_Flow=1;
OAuth2ClientId=<client-id>;
OAuth2Secret=<client-secret>;
UserAgentEntry=YourCompany_YourProduct/1.0.0;
```
---
## Node.js Driver
```javascript
const { DBSQLClient } = require('@databricks/sql');
const client = new DBSQLClient();
await client.connect({
host: process.env.DATABRICKS_HOST,
path: process.env.DATABRICKS_HTTP_PATH,
token: process.env.DATABRICKS_TOKEN, // or OAuth config
userAgentEntry: 'YourCompany_YourProduct/1.0.0'
});
const session = await client.openSession();
const result = await session.executeStatement('SELECT 1');
```
---
## Go Driver
```go
package main
import (
"database/sql"
"os"
dbsql "github.com/databricks/databricks-sql-go"
)
func main() {
connector, err := dbsql.NewConnector(
dbsql.WithServerHostname(os.Getenv("DATABRICKS_HOST")),
dbsql.WithPort(443),
dbsql.WithHTTPPath(os.Getenv("DATABRICKS_HTTP_PATH")),
dbsql.WithAccessToken(os.Getenv("DATABRICKS_TOKEN")),
dbsql.WithUserAgentEntry("YourCompany_YourProduct/1.0.0"),
)
if err != nil {
panic(err)
}
db := sql.OpenDB(connector)
defer db.Close()
// Execute queries...
}
```
---
## Python SQL Connector
```python
from databricks import sql
connection = sql.connect(
server_hostname="<host>",
http_path="<http-path>",
access_token="<token>", # or OAuth config
_user_agent_entry="YourCompany_YourProduct/1.0.0"
)
cursor = connection.cursor()
cursor.execute("SELECT 1")
print(cursor.fetchall())
cursor.close()
connection.close()
```
---
## Python SQLAlchemy
Use `user_agent_entry` in `connect_args` (not `_user_agent_entry`; the latter is deprecated):
```python
from sqlalchemy import create_engine, text
url = "databricks://token:<token>@<host>?http_path=<path>&catalog=main&schema=default"
engine = create_engine(url, connect_args={"user_agent_entry": "YourCompany_YourProduct/1.0.0"})
with engine.connect() as conn:
conn.execute(text("SELECT 1"))
```
---
## Python SDK
Use the `useragent` module functions (recommended) for partner and product registration:
```python
from databricks.sdk import WorkspaceClient, useragent
# Register partner and product (global, call once)
useragent.with_partner("YourCompany")
useragent.with_product("YourCompany_YourProduct", "1.0.0")
client = WorkspaceClient(
host="https://<host>",
token="<token>",
)
```
**Note:** The older `product=` / `product_version=` on `WorkspaceClient` or `Config` also works but `useragent.with_partner()` / `useragent.with_product()` is the recommended approach for partner integrations.
---
## REST API (Direct HTTP)
When calling Databricks REST APIs directly, include the User-Agent header:
```bash
curl -X GET "https://<host>/api/2.0/clusters/list" \
-H "Authorization: Bearer <token>" \
-H "User-Agent: YourCompany_YourProduct/1.0.0"
```
### Java (HttpClient)
```java
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://<host>/api/2.0/clusters/list"))
.header("Authorization", "Bearer " + token)
.header("User-Agent", "YourCompany_YourProduct/1.0.0")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
```
---
## Databricks Connect
Use `.userAgent()` on the `DatabricksSession.builder` to set the partner User-Agent identifier. This is the [PWAF-recommended approach](https://databrickslabs.github.io/partner-architecture/isv-partners/telemetry-attribution/databricks-connect).
### Python
```python
from databricks.connect import DatabricksSession
from databricks.sdk.core import Config
config = Config() # Auth from environment
spark = (
DatabricksSession.builder
.sdkConfig(config)
.userAgent("YourCompany_YourProduct/1.0.0")
.getOrCreate()
)
```
### Scala
```scala
import com.databricks.connect.DatabricksSession
val spark = DatabricksSession.builder
.userAgent("YourCompany_YourProduct/1.0.0")
.getOrCreate()
```
**Note:** The older `product=` / `product_version=` on Config also works internally, but `.userAgent()` on the session builder is the official PWAF pattern.
---
## Validating Your Implementation
### Method 1: Query History UI
1. Go to Databricks workspace → SQL → Query History
2. Look for the **Source** column
3. Your User-Agent should appear there
### Method 2: System Tables Query
```sql
GitHub에서 보기