Activity logs for organizations in Workbench
Categories:
Prior reading: Manage organizations
Purpose: This document explains what activity logs are and how you can use them to gain insight about your organizations.
What are activity logs and why are they useful?
Verily Workbench activity logs are time-stamped logs that can associate a user ID, org ID, operation taken (e.g., create, clone, delete, update access), and Workbench object (e.g., workspace, data collection, storage resource, VM, Dataproc cluster).
These logs are also useful to organization admins who want to better understand how active the users who belong to their organization are in Workbench. With these logs, admins can write SQL queries to pull results that answer queries such as the following:
- How many users are in this org?
- How many workspaces have users in this org created?
- How many cloud apps (i.e., notebooks) have users in this org created?
How can I access the activity logs?
Activity logs are accessible at the data collection and organization level.
For organizations, organization admins will see a link to these logs, stored in BigQuery, from the Organizations tab:
Click the Activity Logs link to open these logs in the BigQuery UI. The logs are stored in BigQuery tables that are partitioned by organization ID:
`workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspace_activity_logs_*`
Using BigQuery, organization admins can review the schema and directly query the tables via SQL, save query results or open them in Google Sheets, and more. The tables provide information about all the organizations for which you are an admin.
Understanding table naming with org_id suffix
Each table in the activity logs dataset is partitioned by organization ID using a table suffix. The
table naming pattern is <table_name>_<org_id>. For example, if your organization ID is abc123,
the workspace activity logs table would be named wsm_workspace_activity_logs_abc123.
To query across all organizations you have access to, use the wildcard _* suffix:
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspace_activity_logs_*`
To query a specific organization, replace _* with _<your_org_id>:
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspace_activity_logs_<your_org_id>`
You can find your organization's user-facing ID in the URL when viewing your organization:
https://workbench.verily.com/organizations/{your-organization-user-facing-id}
Querying a specific organization's table is more efficient than using the wildcard, especially if you manage multiple large organizations.
Note
If you are having issues running SQL queries from any Workbench GCP project, please reach out to workbench-support@verily.com, as we may need to allowlist your email domain. If the data collection you are in disallows you from running BigQuery, you can also run the query in your personal GCP project. Alternatively, as a workaround, you can run your queries from a Workbench notebook app, as described below.Be aware
Previewing or browsing tables is not available for these datasets because data is isolated into separate tables per organization. However, you can achieve the same by running a query:
SELECT * FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspace_activity_logs_*` LIMIT 10
Schema of the activity logs tables
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspace_activity_logs_* tables:
| Field name | Type | Definition |
|---|---|---|
| workspace_id | STRING | Universally unique identifier (UUID) for workspace |
| workspace_user_facing_id | STRING | Human readable, user-facing ID for workspace |
| change_date | TIMESTAMP | Timestamp of change event |
| actor_email | STRING | The actor email |
| user_id | STRING | UUID of the user |
| change_subject_id | STRING | UUID of the Workbench resources (e.g. VM, GCS bucket, workspace itself) that was changed. |
| change_subject_type | STRING | Type of the changed resources |
| source_workspace_id | STRING | UUID of the workspace from which this workspace is cloned. NULL if this is not a duplication. |
| org_id | STRING | UUID of the organization |
| org_user_facing_id | STRING | Human readable, user-facing ID for Organization |
| pod_id | UUID | UUID of the pod |
| pod_user_facing_id | STRING | Human readable, user-facing ID for Pod |
| is_data_collection | BOOLEAN | Whether this is a data collection |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspaces_* tables:
| Field name | Type | Definition |
|---|---|---|
| workspace_id | STRING | Universally unique identifier (UUID) for workspace |
| workspace_user_facing_id | STRING | Human readable, user-facing ID for workspace |
| workspace_display_name | STRING | User-friendly display name |
| description | STRING | Workspace description |
| created_date | TIMESTAMP | The timestamp when workspace is created |
| created_by_email | STRING | Email of workspace creator |
| org_id | STRING | UUID for the Organization |
| org_user_facing_id | STRING | Human readable, user-facing ID for Organization |
| pod_id | UUID | UUID of the pod |
| pod_user_facing_id | STRING | Human readable, user-facing ID for Pod |
| cloud_platform | STRING | GCP/AWS |
| properties | STRING | JSON string of metadata on the workspace |
| workspace_metadata_policy | STRING | JSON string list of completed metadata policies |
| gcp_project_id | STRING | GCP project ID if this is a GCP workspace |
| gcp_project_number | STRING | GCP project number if this is a GCP workspace |
| is_data_collection | BOOLEAN | Whether this is a data collection |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_resources_* tables:
| Field name | Type | Definition |
|---|---|---|
| workspace_id | STRING | Universally unique identifier (UUID) for workspace |
| workspace_user_facing_id | STRING | Human readable, user-facing ID for workspace |
| resource_id | STRING | Universally unique identifier (UUID) for resource |
| resource_user_facing_id | STRING | Human readable, user-facing ID for resource |
| resource_display_name | STRING | User-friendly display name |
| description | STRING | Resource description |
| created_date | TIMESTAMP | The timestamp when this resource is created |
| created_by_email | STRING | Email of resource creator |
| resource_type | STRING | Type of resources |
| exact_resource_type | STRING | TYPE of resource, used when needing to distinguish CONTROLLED and REFERENCED resources |
| resource_lineage | STRING | Where this resource is from, e.g., the data collection ID where it's imported from |
| state | STRING | Lifecycle state of the resource |
| org_id | STRING | UUID for the Organization |
| org_user_facing_id | STRING | Human readable, user-facing ID for Organization |
| pod_id | UUID | UUID of the pod |
| pod_user_facing_id | STRING | Human readable, user-facing ID for Pod |
| is_data_collection | BOOLEAN | Whether this resource is in a data collection |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.sam_workspace_users_* tables:
| Field name | Type | Definition |
|---|---|---|
| user_email | STRING | Email of the user |
| org_id | STRING | UUID for the Organization |
| workspace_id | STRING | Universally unique identifier (UUID) for workspace |
| role | STRING | Role of the user at the workspace - one of: owner, reader, writer |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.um_users_* tables:
| Field name | Type | Definition |
|---|---|---|
| user_id | UUID | Universally unique identifier (UUID) of the user |
| STRING | User email | |
| org_id | UUID | UUID of the organization |
| org_user_facing_id | STRING | Human readable, user-facing ID for Organization |
| active_state | STRING | The current user state (ENABLED, DISABLED, ARCHIVED, INVITED) |
| tos_state | STRING | Whether the user has accepted Terms of Service (TOS_REQUIRED, TOS_OK) |
| created_date | TIMESTAMP | When the user account on Workbench is created |
| created_by_email | STRING | Email of user who created the user's account. |
| last_updated_date | TIMESTAMP | Last time the user's status, profile or other metadata is updated. |
| last_updated_by_email | STRING | Email of user who last updated the user |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.um_pods_* tables:
| Field name | Type | Definition |
|---|---|---|
| pod_id | UUID | UUID of the pod |
| pod_user_facing_id | STRING | Human readable, user-facing ID for Pod |
| description | STRING | Description for the POD |
| org_id | UUID | UUID of the organization |
| org_user_facing_id | STRING | Human readable, user-facing ID for Organization |
| org_display_name | STRING | Organization display name |
| environment_type | STRING | The cloud environment this POD supports (AWS, GCP) |
| billing_account_id | STRING | Cloud billing account ID (GCP only) |
| created_date | TIMESTAMP | When the user account on Workbench is created |
| created_by_email | STRING | Email of user who created the user's account. |
| last_updated_date | TIMESTAMP | Last time the user's status, profile or other metadata is updated. |
| last_updated_by_email | STRING | Email of user who last updated the user |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.um_user_pod_roles_* tables:
| Field name | Type | Definition |
|---|---|---|
| user_email | STRING | User email |
| policy_group | STRING | Google Group for the pod role. |
| role | STRING | User's role on the POD |
| pod_id | UUID | UUID of the pod |
| pod_user_facing_id | STRING | Human readable, user-facing ID for Pod |
| description | STRING | Description for the POD |
| org_id | STRING | UUID of the organization |
| org_user_facing_id | STRING | Human readable, user-facing ID for Organization |
| environment_type | STRING | The cloud environment this POD supports (AWS, GCP) |
| created_date | TIMESTAMP | When the pod was created |
| created_by_email | STRING | Email of pod creator |
| last_updated_date | STRING | Last time the pod was updated. |
| last_updated_by_email | STRING | Email of user who last updated the pod |
workbench-bq-log-sink.workbench_monitoring_org_logs_prod.cloud_audit_logs_* tables:
| Field name | Type | Definition |
|---|---|---|
| insert_id | STRING | Unique identifier for each audit log entry (used for deduplication) |
| timestamp | TIMESTAMP | Timestamp when the event occurred |
| org_id | STRING | UUID of the organization |
| org_user_facing_id | STRING | Human-readable, user-facing ID for organization |
| workspace_id | STRING | UUID of the workspace |
| workspace_user_facing_id | STRING | Human-readable, user-facing ID for workspace |
| gcp_project_id | STRING | GCP project ID associated with the workspace |
| gcp_project_number | STRING | GCP project number associated with the workspace |
| user_email | STRING | The end-user's email address |
| audit_log | STRING | The full audit log payload as JSON |
Note
The workbench_cloud_audit_logs_prod dataset contains cloud
audit logs that provide detailed tracking of Google Cloud Storage (GCS) and BigQuery operations
performed within your organization's workspaces. This is separate from the activity logs in
workbench_monitoring_org_logs_prod, which track workspace-level activities.
Data retention: Cloud audit logs are retained for 2 years (730 days) before being
automatically deleted. Logs are partitioned by the timestamp field for efficient querying.
Querying the activity logs tables
BigQuery UI
You can query the activity logs table directly from the BigQuery panel in the Google Cloud console, by clicking the Activity logs link from a data collection that you own.
Running queries from a Workbench app
You can also query the table from within a Workbench app, using the bigquery library, e.g.,
by running something like the following:
import pandas as pd
from google.cloud import bigquery
BQ_dataset = 'workbench-bq-log-sink.workbench_monitoring_org_logs_prod'
job_query_config = bigquery.QueryJobConfig(default_dataset=BQ_dataset)
client = bigquery.Client(default_query_job_config=job_query_config)
Next, define a query on the table:
query = """
SELECT DISTINCT(workspace_user_facing_id), workspace_id, pod_user_facing_id, is_data_collection
FROM `wsm_workspace_activity_logs_*`
ORDER BY change_date DESC
"""
Then, run the query and view a dataframe of the results:
df = client.query(query).result().to_dataframe()
df
Querying on a specific data collection
If you're an owner of multiple data collections, the logs are aggregated in one table. So if you are
interested in the usage of a particular data collection, you can first get the user-facing ID of
that data collection, and then refine your query to retrieve data for just that data collection. You
can find the user-facing ID in the path of the data collection URL like this:
https://workbench.verily.com/data-collections/{your-data-collection-user-facing-id}
Example queries
"How many users are in my org?"
SELECT COUNT(user_id)
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.um_users_*`
To query a specific organization, replace _* with your organization ID:
SELECT COUNT(user_id)
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.um_users_<your_org_id>`
WHERE org_id = '<your_org_id>'
"How many pods are in my org?"
SELECT COUNT(pod_id)
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.um_user_pod_roles_*`
"How many workspaces are in my org?"
SELECT COUNT(workspace_id)
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_workspaces_*`
"How many cloud apps (i.e., notebooks) have users in this org created?"
SELECT COUNT(resource_id)
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.wsm_resources_*`
WHERE resource_type IN ('AWS_EC2_INSTANCE', 'AWS_SAGEMAKER_NOTEBOOK', 'AI_NOTEBOOK_INSTANCE', 'DATAPROC_CLUSTER', 'GCE_INSTANCE')
"What are the most recent cloud audit log events for my organization?"
SELECT timestamp, workspace_id, user_email, org_id
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.cloud_audit_logs_*`
ORDER BY timestamp DESC
LIMIT 50
"What workspaces have the most audit log activity?"
SELECT workspace_id, org_id, COUNT(*) as event_count
FROM `workbench-bq-log-sink.workbench_monitoring_org_logs_prod.cloud_audit_logs_*`
GROUP BY workspace_id, org_id
ORDER BY event_count DESC
LIMIT 10
Querying comprehensive cloud audit logs
For detailed GCP-level audit logs across your organization, use the
workbench_cloud_audit_logs_prod dataset:
"What are the most recent comprehensive cloud audit logs for my organization?"
SELECT timestamp, workspace_id, user_email, org_id
FROM `workbench-bq-log-sink.workbench_cloud_audit_logs_prod.cloud_audit_logs_*`
ORDER BY timestamp DESC
LIMIT 50
"What are the audit logs for a specific workspace?"
SELECT timestamp, user_email, audit_log
FROM `workbench-bq-log-sink.workbench_cloud_audit_logs_prod.cloud_audit_logs_*`
WHERE workspace_id = 'your-workspace-id'
ORDER BY timestamp DESC
LIMIT 100
"What BigQuery queries were performed?"
SELECT
timestamp,
user_email,
JSON_VALUE(audit_log, '$.methodName') AS method_name,
JSON_VALUE(audit_log, '$.status.code') AS status_code,
JSON_VALUE(audit_log, '$.status.message') AS status_message,
JSON_VALUE(audit_log, '$.servicedata_v1_bigquery.jobInsertRequest.resource.jobConfiguration.query.query') AS query_text
FROM `workbench-bq-log-sink.workbench_cloud_audit_logs_prod.cloud_audit_logs_*`
WHERE JSON_VALUE(audit_log, '$.serviceName') = 'bigquery.googleapis.com' and JSON_VALUE(audit_log, '$.methodName') ='jobservice.insert'
ORDER BY timestamp DESC
LIMIT 100
"What Google Cloud Storage (GCS) operations were performed?"
SELECT
timestamp,
user_email,
JSON_VALUE(audit_log, '$.methodName') AS method_name,
JSON_VALUE(audit_log, '$.resourceName') AS resource_name,
JSON_VALUE(audit_log, '$.status.code') AS status_code,
JSON_VALUE(audit_log, '$.status.message') AS status_message
FROM `workbench-bq-log-sink.workbench_cloud_audit_logs_prod.cloud_audit_logs_*`
WHERE JSON_VALUE(audit_log, '$.serviceName') = 'storage.googleapis.com'
ORDER BY timestamp DESC
LIMIT 100
Last Modified: 3 November 2025