Skip to main content

Overview

Every query, command, and API call that flows through Formal Connectors is logged and stored for auditing, compliance, and security analysis. Formal’s log system provides comprehensive visibility into data access across your organization. Formal console logs

What Gets Logged

Database Queries

Full SQL/NoSQL queries, execution time, rows affected

API Calls

HTTP requests, headers, request/response bodies, status codes

SSH Commands

Every command executed in SSH sessions

Kubernetes Exec

kubectl exec sessions and commands

Control Plane API Calls

Create, Read, Update, and Delete API calls made to the Control Plane

Log Enrichment

Formal automatically enriches each Connector log entry with contextual information:
FieldDescription
TimestampWhen the query/command was executed
UserFormal user who made the request
End-UserActual end-user (for BI tool queries)
ResourceTarget database, API, or server
ConnectorWhich Connector processed the request
Session IDAssociated session identifier
Policy ActionsAny policy enforcement (mask, block, filter, etc.)
Client IPSource IP address
ApplicationClient application (psql, Looker, etc.)
DurationQuery execution time
Rows AffectedNumber of records touched
Control Plane API calls are enriched with the following information:
FieldDescription
TimestampWhen the API call was made
UserFormal user who made the request
CommandThe API call that was made (e.g. UpdatePolicy) and type (create, read, update, delete)
ArgumentsThe arguments passed to the API call as part of the request payload (sensitive arguments like passwords are always redacted)
ServiceThe service that the API call was made to (e.g. logs)
Request MethodThe HTTP method used for the API call (e.g. GET, POST)
IP AddressSource IP address

Accessing Logs

Navigate to Logs in the Formal console to view all logged activity.

Viewing Modes

Default view that displays all log entries chronologically.
  • See individual queries/commands
  • Click any row to open detailed panel
  • Filter and search across all fields
  • Export to CSV

Aggregation Examples

Use Aggregation Mode to answer common operational and security questions:
QuestionGroup ByVisualizationFilter
Which users run the most queries?user.formal.user.emailBar chartevent_type:request
What resources get the most traffic?resource.namePie chartevent_type:request
How many policy blocks per day?timestamp (1d interval)Timeseriestriggered_policies.type:block
Top blocked queries by useruser.formal.user.emailTabletriggered_policies.type:block
Query volume by technologyresource.technologyPie chartevent_type:request
Failed login attempts over timetimestamp (1h interval)Timeseriesevent_type:session-login-failed
Data access by groupuser.formal.user.groupsBar chartevent_type:request
Masking activity per resourceresource.nameBar charttriggered_policies.type:mask
Combine aggregation with time range filters to compare patterns across periods — for example, compare this week’s query volume to last week’s to spot anomalies.

Log Details Panel

Click any log entry to view comprehensive details: Log details panel

What’s Included

  • Full Query/Command: Complete text of what was executed
  • User Context: User, end-user, groups, email
  • Resource Information: Database, hostname, port, technology
  • Policy Evaluation: Which policies evaluated, actions taken, reasons
  • Performance Metrics: Duration, rows affected, data transferred
  • Network Information: Client IP, application, connection details
  • Session Link: Jump to associated session recording

Log Schema Reference

Every log entry follows a structured schema with nested fields. You can query any of these fields using Quickwit syntax.

Event and Session Fields

FieldTypeDescription
event_typeStringEvent type: request, session-start, session-end, session-login, session-login-failed, session-analysis, stream-event, admin-policy-action, control-plane-request, workflow
timestampDateTimeWhen the event occurred (RFC3339)
session.idStringSession identifier
session.application.nameStringClient application (e.g., psql, mongosh)
session.network.client_ip_addressStringClient IP and port
session.network.server_ip_addressStringServer IP and port

User Fields

FieldTypeDescription
user.typeStringformal or native
user.usernameStringNative username
user.formal.user.emailStringFormal user email
user.formal.user.idStringFormal user ID
user.formal.user.typeStringhuman or machine
user.formal.user.groups[]StringUser group memberships
user.formal.end_user.emailStringEnd-user email (for BI tool queries)
user.formal.end_user.nameStringEnd-user name
user.formal.end_user.groups[]StringEnd-user groups

Resource Fields

FieldTypeDescription
resource.idStringResource identifier
resource.nameStringResource name
resource.typeStringResource type
resource.technologyStringpostgres, mysql, mongodb, snowflake, http, ssh, kubernetes, s3, etc.
resource.datastore.hostnameStringResource hostname

Request and Response Fields

FieldTypeDescription
request.query.receivedStringQuery as received from the client
request.query.sentStringQuery as sent to the resource (after rewriting)
request.query.normalizedStringNormalized query (parameters removed)
request.query.fingerprintStringQuery fingerprint for grouping similar queries
response.datastore.rows_count.receivedIntegerRows returned by the resource
response.datastore.rows_count.sentIntegerRows sent to the client (after filtering)
response.datastore.returned_columns.nameStringColumn name
response.datastore.returned_columns.pathStringFull column path
response.datastore.returned_columns.data_labelStringData classification label

Policy Fields

FieldTypeDescription
triggered_policies.idStringPolicy ID
triggered_policies.nameStringPolicy name
triggered_policies.statusStringPolicy status (active, dry_run)
triggered_policies.typeStringAction taken (block, mask, filter, allow, etc.)

Connector and Space Fields

FieldTypeDescription
connector.idStringConnector identifier
connector.nameStringConnector name
space.idStringSpace identifier
space.nameStringSpace name

Control Plane Fields

FieldTypeDescription
control_plane_request.command.nameStringAPI command (e.g., UpdatePolicy)
control_plane_request.command.typeStringcreate, read, update, delete
control_plane_request.serviceStringService name (e.g., policies, logs)
control_plane_request.methodStringHTTP method
control_plane_request.user.emailStringUser who made the API call

Device Fields

FieldTypeDescription
session.device.hardware.model_nameStringDevice model
session.device.hardware.model_numberStringDevice model number
session.device.software.system_versionStringOS version
session.device.software.kernel_versionStringKernel version
Formal uses Quickwit query engine for powerful search capabilities.

Basic Filters

Use the sidebar to filter by:
  • Connector
  • Resource
  • User
  • End-user
  • Group
  • Technology (postgres, ssh, http, etc.)
  • Time range
Write Quickwit queries for complex searches:
# Find all queries by user Alice
user:alice@example.com

# Find queries that triggered policies
policy_actions:* AND NOT policy_actions:allow

# Find slow queries (>1 second)
duration_ms:[1000 TO *]

# Find DELETE statements in production
query:"DELETE" AND resource:production-postgres

# Find SSH commands containing "sudo"
command:"sudo" AND technology:ssh

# Find queries accessing specific table
query:"FROM users" OR query:"JOIN users"

# Complex: Find non-admin users accessing PII tables
user.groups:(NOT admin) AND (table:"users_pii" OR table:"customers_sensitive")

# Time-based: Queries in the last 24 hours
timestamp:[now-24h TO now]

# Failed authentications
status:denied AND policy_action:block_authentication

Query Templates

Formal provides pre-built query templates:
TemplateDescriptionQuery
Formal UsersSystem-generated usersuser.type:formal
Native UsersQueries using native credentialsuser_type:native
Triggered PoliciesLogs with policy enforcementpolicy_actions:* AND NOT policy_actions:allow
Datastore QueriesDatabase queriestechnology:(postgres OR mysql OR mongodb OR snowflake)
HTTP RequestsAPI callstechnology:http
S3 RequestsS3 operationstechnology:s3
Encrypted RequestsQueries with encryptionrequest.query.encrypted:true
SSH SessionsTerminal sessionstechnology:ssh

Query Library

Query actions Access your queries by clicking Queries in the toolbar. The Query Library provides three tabs:

Recent Queries

View your search history:
  1. Click Queries to open the Query Library
  2. View the Recent tab (default)
  3. Select any previous query to re-run it
  4. History persists across sessions

Saved Queries

Save frequently used queries for quick access:
  1. Create your query with filters or search terms
  2. Click Save in the toolbar
  3. Name your query
  4. Access later from QueriesSaved tab

Template Queries

Pre-built queries for common use cases. Click QueriesTemplates to browse available templates (see Query Templates above)

Exporting Logs

CSV Export

Export search results to CSV for offline analysis:
  1. Apply filters or search query
  2. Click Export to CSV
  3. Download the file

Log Integration

Forward all logs to external systems:
  • AWS S3: Long-term archive, compliance storage
  • Datadog: Real-time monitoring and alerting
  • Splunk: SIEM integration
See Log Integration for setup instructions.

Log Retention

Connector Logs

Connector logs (queries, commands, API calls) are stored in Formal’s Quickwit index and are available for as long as your account is active. For long-term archival or compliance requirements, use Log Integration to forward logs to:
  • AWS S3: Cost-effective long-term storage for compliance (e.g., 7-year SOC 2 retention)
  • Datadog: Real-time monitoring with configurable retention periods
  • Splunk: SIEM integration with custom retention policies

Policy Evaluation Input Retention

Policy evaluation inputs (the input data passed to policies) contain sensitive information and have a configurable retention period of 0 to 30 days. This data powers policy impact reports. Configure retention at Log Configurations independently for each evaluation stage:
StageWhat’s RetainedUse Case
SessionUser, resource, device, connection contextBacktest session-level policies
RequestQuery text, table paths, schema pathsBacktest pre-request policies
ResponseColumn data, row counts, data labelsBacktest post-request masking/filtering
Retention can be scoped at multiple levels (in precedence order):
  1. Resource — per-resource override
  2. Connector — per-connector default
  3. Space — per-space default
  4. Account — organization-wide default
Setting retention to 0 days disables retention for that stage. Policy impact reports won’t have data to backtest against for disabled stages. Changes to retention settings may take up to a day to take effect.
Policy evaluation inputs may contain sensitive data depending on your policies. Retention is subject to a maximum of 30 days. Changing retention settings may take a day to take effect.

Best Practices

Save frequently used searches for compliance, security, or operational monitoring.
Forward logs to your SIEM or data lake for advanced analytics and long-term retention beyond Formal’s console.
Schedule weekly or monthly log reviews to identify unusual patterns, policy gaps, or security incidents.
Leverage aggregation and visualization to spot trends that aren’t obvious in individual log entries.
Regularly review logs where policies blocked or masked data to ensure policies are working as intended.

Policy Evaluation Input Retention

Formal can optionally retain the input data passed to policies during evaluation. This enables policy backtesting — testing new or modified policies against historical access patterns. Refer to policies evaluation docs for what is available as input at each stage. See Log Retention above for configuration details, scope hierarchy, and retention limits.

Integration with Policies

Policies can enrich logs with contextual information:
package formal.v2

import future.keywords.if

post_request := {
  "action": "allow",
  "reason": "Query approved for analytics team",
  "contextual_data": sprintf(
    "Approved query on %s by %s from %s",
    [input.resource.name, input.user.email, input.client_ip_address]
  )
} if {
  "analytics" in input.user.groups
}
The reason and contextual_data fields appear in the log entry, providing audit trail context.

Next Steps