Custom Views
Custom Views allow you to create virtual tables that extract specific fields from your log data using JSON path expressions. This feature enables you to organize and analyze your log data with custom columns tailored to your specific use cases, without modifying the underlying data structure.
Feature Flag Required: Custom Views is currently gated behind a feature flag. Please reach out to RunReveal support to request access to this feature.
Getting Started: Navigate to Settings → Custom Views to create your first custom view, or use the CLI and API for programmatic access.
Key Features
- Virtual Tables: Create queryable views without data transformation
- JSON Path Extraction: Extract nested fields from your raw logs
- Source Filtering: Views automatically filter to specific sources
- Real-time Analysis: Query-time extraction for immediate insights
- Flexible Schema: Add custom columns for any JSON field in your logs
When to Use Custom Views
✅ Perfect For:
- Field Extraction: Pull specific fields from complex JSON logs
- Analysis Enhancement: Add columns for security analysis, compliance, or investigation
- Source-Specific Views: Create specialized views for different log sources
- Query Optimization: Pre-define commonly used field extractions
❌ Not Ideal For:
- Data Normalization: Use transforms to map fields to standard RunReveal schema
- Complex Logic: Limited to simple JSON path expressions (no SQL functions)
- Data Transformation: Views are read-only, no data modification
Architecture
Raw Log → Transform (Optional) → runreveal.logs → Custom View → Analysis
↓ ↓ ↓ ↓ ↓
Your Field Mapping Standardized Virtual Queries
JSON to Standard Data Table & Alerts
Creating Custom Views
Via Web UI
1) Navigate to Custom Views
Go to Settings → Custom Views and click “Create Custom View”.
2) Configure Basic Information
Fill in the basic information:
- Name: Descriptive name for your view
- Description: Optional description of the view’s purpose
- Source: Select the source to filter logs from
3) Add Custom Columns
Add custom columns with:
- Column Name: Name for the extracted field
- Type: ClickHouse data type (String, Int64, Bool, etc.)
- SQL Expression: JSON path to extract the field
- Description: Optional description of the column
4) Test and Save
Test your view with sample data, then save your configuration.
Via CLI
# List existing custom views
./runreveal custom-views list
# Create a new custom view
./runreveal custom-views create \
--name "my_custom_view" \
--description "Description of the view" \
--source-id "your_source_id" \
--columns '[{"name": "field_name", "type": "String", "sql": "json.path", "description": "Field description"}]'
# Get a specific view
./runreveal custom-views get --id "view_id"
# Update a view
./runreveal custom-views update --id "view_id" [flags]
# Delete a view
./runreveal custom-views delete --id "view_id"
Via API
# Create custom view
curl -X POST "https://api.runreveal.com/custom-views/create" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my_custom_view",
"description": "Description of the view",
"sourceId": "your_source_id",
"columns": [
{
"name": "field_name",
"description": "Field description",
"type": "String",
"sql": "json.path"
}
]
}'
Column Configuration
Supported Data Types
Type | Description | Example |
---|---|---|
String | Text data | "[email protected]" |
Int64 | 64-bit integer | 12345 |
UInt64 | Unsigned 64-bit integer | 4294967295 |
Float64 | 64-bit floating point | 3.14159 |
Bool | Boolean value | true |
DateTime | Date and time | 2025-01-15 10:30:00 |
Array(String) | Array of strings | ["tag1", "tag2"] |
Nullable(String) | Nullable string | null or "value" |
JSON Path Expressions
Custom views support simple JSON path expressions to extract nested fields:
Basic Syntax
field.subfield.array[0].nested_field
Examples
{
"user": {
"profile": {
"email": "[email protected]"
}
},
"tags": ["security", "alert"],
"metadata": {
"source_ip": "192.168.1.100"
}
}
Valid JSON Paths:
user.profile.email
→"[email protected]"
tags[0]
→"security"
metadata.source_ip
→"192.168.1.100"
Limitations
- No SQL Functions: Cannot use
CASE
,COALESCE
,IF
, etc. - No Conditional Logic: Cannot use
OR
,AND
statements - Simple Paths Only: Only direct field access and array indexing
Example: Jamf Protect Custom View
Use Case
Extract important security fields from Jamf Protect Device Telemetry Stream logs for analysis.
Configuration
Basic Information:
- Name:
jamf_protect_telemetry
- Description:
Jamf Protect Device Telemetry Stream analysis
- Source: Your Jamf Protect source
Custom Columns:
[
{
"name": "jamf_event_type",
"description": "Jamf event type classification",
"type": "String",
"sql": "event_type"
},
{
"name": "jamf_hostname",
"description": "Device hostname",
"type": "String",
"sql": "host.hostname"
},
{
"name": "jamf_device_serial",
"description": "Device serial number",
"type": "String",
"sql": "host.serial"
},
{
"name": "jamf_os_version",
"description": "OS version",
"type": "String",
"sql": "host.os"
},
{
"name": "jamf_protect_version",
"description": "Jamf Protect agent version",
"type": "String",
"sql": "host.protectVersion"
},
{
"name": "jamf_client_id",
"description": "Jamf client ID",
"type": "String",
"sql": "context.identity.claims.clientid"
},
{
"name": "jamf_organization",
"description": "Organization context",
"type": "String",
"sql": "context.identity.claims.hd"
},
{
"name": "jamf_actor_username",
"description": "User who performed the action",
"type": "String",
"sql": "event.exec.target.audit_token.e_username"
},
{
"name": "jamf_process_path",
"description": "Executable path",
"type": "String",
"sql": "event.exec.target.executable.path"
},
{
"name": "jamf_signing_id",
"description": "Code signing identity",
"type": "String",
"sql": "event.exec.target.signing_id"
},
{
"name": "jamf_is_platform_binary",
"description": "Is Apple-signed binary",
"type": "Bool",
"sql": "event.exec.target.is_platform_binary"
},
{
"name": "jamf_executable_sha256",
"description": "File integrity hash",
"type": "String",
"sql": "event.exec.target.executable.sha256"
}
]
Querying Custom Views
View Naming Convention
Custom views are named using the pattern: {workspace_name}_{view_name}
Example: runreveal_inc_jamf_protect_telemetry
Basic Queries
-- Get all records from the custom view
SELECT * FROM your_workspace_jamf_protect_telemetry LIMIT 10;
-- Get specific columns
SELECT
eventTime,
jamf_event_type,
jamf_hostname,
jamf_actor_username
FROM your_workspace_jamf_protect_telemetry
ORDER BY eventTime DESC;
Security Analysis Queries
-- Find non-platform binary executions
SELECT
eventTime,
jamf_hostname,
jamf_actor_username,
jamf_process_path,
jamf_signing_id,
jamf_is_platform_binary
FROM your_workspace_jamf_protect_telemetry
WHERE jamf_is_platform_binary = false
ORDER BY eventTime DESC
LIMIT 100;
-- Find process executions by specific user
SELECT
eventTime,
jamf_process_path,
jamf_executable_sha256,
jamf_signing_id
FROM your_workspace_jamf_protect_telemetry
WHERE jamf_actor_username = 'suspicious_user'
ORDER BY eventTime DESC;
-- Find unsigned or suspiciously signed binaries
SELECT
eventTime,
jamf_hostname,
jamf_process_path,
jamf_signing_id
FROM your_workspace_jamf_protect_telemetry
WHERE jamf_signing_id NOT LIKE 'com.apple.%'
AND jamf_signing_id != ''
ORDER BY eventTime DESC;
Combining with Transforms
Best Practice: Hybrid Approach
Use transforms for standard field mapping and custom views for source-specific analysis:
Transform (Data Normalization)
{
"processors": [
{
"type": "field_mapper",
"config": {
"mappings": [
{
"source": "event_type",
"target": "eventName"
},
{
"source": "host.hostname",
"target": "serviceName"
},
{
"source": "host.ips[0]",
"target": "srcIP"
},
{
"source": "event.exec.target.audit_token.e_username",
"target": "actor.username"
}
]
}
}
]
}
Custom View (Analysis Enhancement)
[
{
"name": "jamf_signing_id",
"type": "String",
"sql": "event.exec.target.signing_id"
},
{
"name": "jamf_is_platform_binary",
"type": "Bool",
"sql": "event.exec.target.is_platform_binary"
}
]
Benefits
- Standard Fields: Work with existing RunReveal detections
- Custom Fields: Enable advanced source-specific analysis
- Flexibility: Query either standard table or custom view as needed
Using Custom Views in Detections
Custom views can be targeted in detection rules:
title: Suspicious Process Execution
detection:
selection:
jamf_is_platform_binary: false
jamf_signing_id:
- "com.suspicious.app"
- ""
condition: selection
sourcenames:
- your_jamf_source
Limitations and Considerations
Current Limitations
- No SQL Functions: Cannot use
CASE
,COALESCE
,IF
, etc. - No Conditional Logic: Cannot use
OR
,AND
statements - Simple JSON Paths Only: Limited to direct field access
- Read-Only: Views cannot modify data
Workarounds
- Multiple Columns: Create separate columns for different field paths
- Query-Time Logic: Use
COALESCE
in your queries to combine fields - Transforms: Use transforms for complex field mapping
Performance Considerations
- Query-Time Extraction: Fields are extracted during query execution
- Indexing: Custom view columns are not indexed separately
- Large Datasets: Consider query performance with large log volumes
Troubleshooting
Common Issues
”Invalid JSON path” Error
- Cause: JSON path syntax is incorrect
- Solution: Use simple dot notation:
field.subfield.array[0]
”No rows in result set”
- Cause: No logs match the source filter or time range
- Solution: Check source is active and has recent logs
”Column not found” Error
- Cause: Column name doesn’t exist in the view
- Solution: Verify column names match the custom view definition
Debugging Steps
- Check Source: Verify the source is active and receiving logs
- Verify JSON Path: Test the JSON path against sample log data
- Check Data Types: Ensure column types match the extracted data
- Review Logs: Check for any error messages in the RunReveal logs
Best Practices
Design Guidelines
- Descriptive Names: Use clear, descriptive column names
- Consistent Types: Use appropriate data types for extracted fields
- Documentation: Add descriptions to explain column purposes
- Source-Specific: Create views tailored to specific log sources
Performance Tips
- Limit Columns: Only extract fields you actually need
- Appropriate Types: Use the most specific data type possible
- Query Optimization: Use WHERE clauses to limit result sets
- Time Ranges: Always include time-based filters in queries
Security Considerations
- Sensitive Data: Be careful not to expose sensitive information in custom columns
- Access Control: Custom views inherit workspace permissions
- Audit Trail: Monitor who creates and modifies custom views
Helpful Resources
Getting Help
- Documentation: This guide and inline help in the UI
- Support: Contact RunReveal support for technical issues
- Community: Join the RunReveal community for best practices
Related Features
- Transforms: For data normalization and field mapping
- Detections: For alerting on custom view data
- Pipelines: For complex data processing workflows
- Query Builder: For interactive query construction